1 /*
  2  * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_VM_OOPS_VALUEPAYLOAD_HPP
 26 #define SHARE_VM_OOPS_VALUEPAYLOAD_HPP
 27 
 28 #include "oops/inlineOop.hpp"
 29 #include "oops/instanceKlass.hpp"
 30 #include "oops/layoutKind.hpp"
 31 #include "oops/oopHandle.hpp"
 32 #include "oops/oopsHierarchy.hpp"
 33 #include "runtime/handles.hpp"
 34 #include "utilities/exceptions.hpp"
 35 #include "utilities/globalDefinitions.hpp"
 36 #include "utilities/macros.hpp"
 37 #include "utilities/ostream.hpp"
 38 
 39 class fieldDescriptor;
 40 class JavaThread;
 41 class outputStream;
 42 class ResolvedFieldEntry;
 43 
 44 class ValuePayload {
 45 private:
 46   template <typename OopOrHandle> class StorageImpl {
 47   private:
 48     union {
 49       struct {
 50         OopOrHandle _container;
 51         ptrdiff_t _offset;
 52       };
 53       address _absolute_addr;
 54     };
 55     InlineKlass* _klass;
 56     LayoutKind _layout_kind;
 57     bool _uses_absolute_addr;
 58 
 59   public:
 60     inline StorageImpl();
 61     inline StorageImpl(OopOrHandle container,
 62                        ptrdiff_t offset,
 63                        InlineKlass* klass,
 64                        LayoutKind layout_kind);
 65     inline StorageImpl(address absolute_addr,
 66                        InlineKlass* klass,
 67                        LayoutKind layout_kind);
 68     inline ~StorageImpl();
 69     inline StorageImpl(const StorageImpl& other);
 70     inline StorageImpl& operator=(const StorageImpl& other);
 71 
 72     inline OopOrHandle& container();
 73     inline OopOrHandle container() const;
 74 
 75     inline ptrdiff_t& offset();
 76     inline ptrdiff_t offset() const;
 77 
 78     inline address& absolute_addr();
 79     inline address absolute_addr() const;
 80 
 81     inline InlineKlass* klass() const;
 82 
 83     inline LayoutKind layout_kind() const;
 84 
 85     inline bool uses_absolute_addr() const;
 86   };
 87 
 88   using Storage = StorageImpl<oop>;
 89 
 90   Storage _storage;
 91 
 92 protected:
 93   static constexpr ptrdiff_t BAD_OFFSET = -1;
 94 
 95   ValuePayload() = default;
 96   ValuePayload(const ValuePayload&) = default;
 97   ValuePayload& operator=(const ValuePayload&) = default;
 98 
 99   // Constructed from parts container and offset
100   inline ValuePayload(oop container,
101                       ptrdiff_t offset,
102                       InlineKlass* klass,
103                       LayoutKind layout_kind);
104 
105   // Constructed from parts absolute_addr
106   inline ValuePayload(address absolute_addr,
107                       InlineKlass* klass,
108                       LayoutKind layout_kind);
109 
110   inline void set_offset(ptrdiff_t offset);
111 
112   static inline void copy(const ValuePayload& src,
113                           const ValuePayload& dst,
114                           LayoutKind copy_layout_kind);
115 
116   inline void mark_as_non_null();
117   inline void mark_as_null();
118 
119   inline bool uses_absolute_addr() const;
120 
121   inline oop& container();
122   inline oop container() const;
123 
124 private:
125   inline void print_on(outputStream* st) const NOT_DEBUG_RETURN;
126   inline void assert_post_construction_invariants() const NOT_DEBUG_RETURN;
127   static inline void assert_pre_copy_invariants(const ValuePayload& src,
128                                                 const ValuePayload& dst,
129                                                 LayoutKind copy_layout_kind) NOT_DEBUG_RETURN;
130 
131 public:
132   inline InlineKlass* klass() const;
133   inline ptrdiff_t offset() const;
134   inline LayoutKind layout_kind() const;
135 
136   inline address addr() const;
137 
138   inline bool has_null_marker() const;
139   inline bool is_payload_null() const;
140 
141   class Handle;
142   class OopHandle;
143 
144   [[nodiscard]] static inline ValuePayload construct_from_parts(address absolute_addr,
145                                                                 InlineKlass* klass,
146                                                                 LayoutKind layout_kind);
147 };
148 
149 class BufferedValuePayload : public ValuePayload {
150   friend class FlatValuePayload;
151 
152 private:
153   inline BufferedValuePayload(inlineOop container,
154                               ptrdiff_t offset,
155                               InlineKlass* klass,
156                               LayoutKind layout_kind);
157 
158 public:
159   BufferedValuePayload() = default;
160   BufferedValuePayload(const BufferedValuePayload&) = default;
161   BufferedValuePayload& operator=(const BufferedValuePayload&) = default;
162 
163   explicit inline BufferedValuePayload(inlineOop buffer);
164   inline BufferedValuePayload(inlineOop buffer, InlineKlass* klass);
165 
166   inline inlineOop container() const;
167 
168   inline void copy_to(const BufferedValuePayload& dst);
169 
170   class Handle;
171   class OopHandle;
172 
173   inline Handle make_handle(JavaThread* thread) const;
174   inline OopHandle make_oop_handle(OopStorage* storage) const;
175 };
176 
177 class FlatValuePayload : public ValuePayload {
178 protected:
179   inline FlatValuePayload(oop container,
180                           ptrdiff_t offset,
181                           InlineKlass* klass,
182                           LayoutKind layout_kind);
183 
184 private:
185   inline inlineOop allocate_instance(TRAPS);
186 
187 public:
188   FlatValuePayload() = default;
189   FlatValuePayload(const FlatValuePayload&) = default;
190   FlatValuePayload& operator=(const FlatValuePayload&) = default;
191 
192   [[nodiscard]] inline bool copy_to(BufferedValuePayload& dst);
193   inline void copy_from(BufferedValuePayload& src);
194 
195   inline void copy_to(const FlatValuePayload& dst);
196 
197   [[nodiscard]] inline inlineOop read(TRAPS);
198   inline void write_without_nullability_check(inlineOop obj);
199   inline void write(inlineOop obj, TRAPS);
200 
201   [[nodiscard]] static inline FlatValuePayload construct_from_parts(oop container,
202                                                                     ptrdiff_t offset,
203                                                                     InlineKlass* klass,
204                                                                     LayoutKind layout_kind);
205 
206   class Handle;
207   class OopHandle;
208 
209   inline Handle make_handle(JavaThread* thread) const;
210   inline OopHandle make_oop_handle(OopStorage* storage) const;
211 };
212 
213 class FlatFieldPayload : public FlatValuePayload {
214 private:
215   inline FlatFieldPayload(instanceOop container,
216                           ptrdiff_t offset,
217                           InlineKlass* klass,
218                           LayoutKind layout_kind);
219 
220   inline FlatFieldPayload(instanceOop container,
221                           ptrdiff_t offset,
222                           InlineLayoutInfo* inline_layout_info);
223 
224 public:
225   FlatFieldPayload() = default;
226 
227   inline FlatFieldPayload(instanceOop container,
228                           fieldDescriptor* field_descriptor);
229   inline FlatFieldPayload(instanceOop container,
230                           fieldDescriptor* field_descriptor,
231                           InstanceKlass* klass);
232 
233   inline FlatFieldPayload(instanceOop container,
234                           ResolvedFieldEntry* resolved_field_entry);
235   inline FlatFieldPayload(instanceOop container,
236                           ResolvedFieldEntry* resolved_field_entry,
237                           InstanceKlass* klass);
238 
239   inline instanceOop container() const;
240 
241   class Handle;
242   class OopHandle;
243 
244   inline Handle make_handle(JavaThread* thread) const;
245   inline OopHandle make_oop_handle(OopStorage* storage) const;
246 };
247 
248 class FlatArrayPayload : public FlatValuePayload {
249 private:
250   struct Storage {
251     jint _layout_helper;
252     int _element_size;
253   } _storage;
254 
255   inline FlatArrayPayload(flatArrayOop container,
256                           ptrdiff_t offset,
257                           InlineKlass* klass,
258                           LayoutKind layout_kind,
259                           jint layout_helper,
260                           int element_size);
261 
262 public:
263   FlatArrayPayload() = default;
264   FlatArrayPayload(const FlatArrayPayload&) = default;
265   FlatArrayPayload& operator=(const FlatArrayPayload&) = default;
266 
267   explicit inline FlatArrayPayload(flatArrayOop container);
268   inline FlatArrayPayload(flatArrayOop container, FlatArrayKlass* klass);
269 
270   inline FlatArrayPayload(flatArrayOop container, int index);
271   inline FlatArrayPayload(flatArrayOop container, int index, FlatArrayKlass* klass);
272 
273   inline flatArrayOop container() const;
274 
275   inline void set_index(int index);
276   inline void advance_index(int delta);
277 
278   inline void next_element();
279   inline void previous_element();
280 
281 private:
282   inline void set_offset(ptrdiff_t offset);
283 
284 public:
285   class Handle;
286   class OopHandle;
287 
288   inline Handle make_handle(JavaThread* thread) const;
289   inline OopHandle make_oop_handle(OopStorage* storage) const;
290 };
291 
292 class ValuePayload::Handle {
293 private:
294   using Storage = StorageImpl<::Handle>;
295 
296   Storage _storage;
297 
298 protected:
299   inline Handle(const ValuePayload& payload, JavaThread* thread);
300 
301   inline oop container() const;
302 
303 public:
304   Handle() = default;
305   Handle(const Handle&) = default;
306   Handle& operator=(const Handle&) = default;
307 
308   inline InlineKlass* klass() const;
309   inline ptrdiff_t offset() const;
310   inline LayoutKind layout_kind() const;
311 };
312 
313 class ValuePayload::OopHandle {
314 private:
315   using Storage = StorageImpl<::OopHandle>;
316 
317   Storage _storage;
318 
319 protected:
320   inline OopHandle(const ValuePayload& payload, OopStorage* storage);
321 
322   inline oop container() const;
323 
324 public:
325   OopHandle() = default;
326   OopHandle(const OopHandle&) = default;
327   OopHandle& operator=(const OopHandle&) = default;
328 
329   inline void release(OopStorage* storage);
330 
331   inline InlineKlass* klass() const;
332   inline ptrdiff_t offset() const;
333   inline LayoutKind layout_kind() const;
334 };
335 
336 class BufferedValuePayload::Handle : public ValuePayload::Handle {
337 public:
338   inline Handle(const BufferedValuePayload& payload, JavaThread* thread);
339 
340   inline BufferedValuePayload operator()() const;
341 
342   inline inlineOop container() const;
343 };
344 
345 class BufferedValuePayload::OopHandle : public ValuePayload::OopHandle {
346 public:
347   inline OopHandle(const BufferedValuePayload& payload, OopStorage* storage);
348 
349   inline BufferedValuePayload operator()() const;
350 
351   inline inlineOop container() const;
352 };
353 
354 class FlatValuePayload::Handle : public ValuePayload::Handle {
355 public:
356   inline Handle(const FlatValuePayload& payload, JavaThread* thread);
357 
358   inline FlatValuePayload operator()() const;
359 };
360 
361 class FlatValuePayload::OopHandle : public ValuePayload::OopHandle {
362 public:
363   inline OopHandle(const FlatValuePayload& payload, OopStorage* storage);
364 
365   inline FlatValuePayload operator()() const;
366 };
367 
368 class FlatFieldPayload::Handle : public FlatValuePayload::Handle {
369 public:
370   inline Handle(const FlatFieldPayload& payload, JavaThread* thread);
371 
372   inline FlatFieldPayload operator()() const;
373 
374   inline instanceOop container() const;
375 };
376 
377 class FlatFieldPayload::OopHandle : public FlatValuePayload::OopHandle {
378 public:
379   inline OopHandle(const FlatFieldPayload& payload, OopStorage* storage);
380 
381   inline FlatFieldPayload operator()() const;
382 
383   inline instanceOop container() const;
384 };
385 
386 class FlatArrayPayload::Handle : public FlatValuePayload::Handle {
387 private:
388   FlatArrayPayload::Storage _storage;
389 
390 public:
391   inline Handle(const FlatArrayPayload& payload, JavaThread* thread);
392 
393   inline FlatArrayPayload operator()() const;
394 
395   inline flatArrayOop container() const;
396 };
397 
398 class FlatArrayPayload::OopHandle : public FlatValuePayload::OopHandle {
399 private:
400   FlatArrayPayload::Storage _storage;
401 
402 public:
403   inline OopHandle(const FlatArrayPayload& payload, OopStorage* storage);
404 
405   inline FlatArrayPayload operator()() const;
406 
407   inline flatArrayOop container() const;
408 };
409 
410 #endif // SHARE_VM_OOPS_VALUEPAYLOAD_HPP