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   inline void print_on(outputStream* st) const NOT_DEBUG_RETURN;
125 
126 private:
127   inline void assert_is_flat_field(const InstanceKlass* klass, int offset) const NOT_DEBUG_RETURN;
128   inline void assert_post_construction_invariants() const NOT_DEBUG_RETURN;
129   static inline void assert_pre_copy_invariants(const ValuePayload& src,
130                                                 const ValuePayload& dst,
131                                                 LayoutKind copy_layout_kind) NOT_DEBUG_RETURN;
132 
133 public:
134   inline InlineKlass* klass() const;
135   inline ptrdiff_t offset() const;
136   inline LayoutKind layout_kind() const;
137 
138   inline address addr() const;
139 
140   inline bool has_null_marker() const;
141   inline bool is_payload_null() const;
142 
143   class Handle;
144   class OopHandle;
145 
146   [[nodiscard]] static inline ValuePayload construct_from_parts(address absolute_addr,
147                                                                 InlineKlass* klass,
148                                                                 LayoutKind layout_kind);
149 };
150 
151 class BufferedValuePayload : public ValuePayload {
152   friend class FlatValuePayload;
153 
154 private:
155   inline BufferedValuePayload(inlineOop container,
156                               ptrdiff_t offset,
157                               InlineKlass* klass,
158                               LayoutKind layout_kind);
159 
160 public:
161   BufferedValuePayload() = default;
162   BufferedValuePayload(const BufferedValuePayload&) = default;
163   BufferedValuePayload& operator=(const BufferedValuePayload&) = default;
164 
165   explicit inline BufferedValuePayload(inlineOop buffer);
166   inline BufferedValuePayload(inlineOop buffer, InlineKlass* klass);
167 
168   inline inlineOop container() const;
169 
170   inline void copy_to(const BufferedValuePayload& dst);
171 
172   class Handle;
173   class OopHandle;
174 
175   inline Handle make_handle(JavaThread* thread) const;
176   inline OopHandle make_oop_handle(OopStorage* storage) const;
177 };
178 
179 class FlatValuePayload : public ValuePayload {
180 protected:
181   inline FlatValuePayload(oop container,
182                           ptrdiff_t offset,
183                           InlineKlass* klass,
184                           LayoutKind layout_kind);
185 
186 private:
187   inline inlineOop allocate_instance(TRAPS);
188 
189 public:
190   FlatValuePayload() = default;
191   FlatValuePayload(const FlatValuePayload&) = default;
192   FlatValuePayload& operator=(const FlatValuePayload&) = default;
193 
194   [[nodiscard]] inline bool copy_to(BufferedValuePayload& dst);
195   inline void copy_from(BufferedValuePayload& src);
196 
197   inline void copy_to(const FlatValuePayload& dst);
198 
199   [[nodiscard]] inline inlineOop read(TRAPS);
200   inline void write_without_nullability_check(inlineOop obj);
201   inline void write(inlineOop obj, TRAPS);
202 
203   [[nodiscard]] static inline FlatValuePayload construct_from_parts(oop container,
204                                                                     ptrdiff_t offset,
205                                                                     InlineKlass* klass,
206                                                                     LayoutKind layout_kind);
207 
208   class Handle;
209   class OopHandle;
210 
211   inline Handle make_handle(JavaThread* thread) const;
212   inline OopHandle make_oop_handle(OopStorage* storage) const;
213 };
214 
215 class FlatFieldPayload : public FlatValuePayload {
216 private:
217   inline FlatFieldPayload(instanceOop container,
218                           ptrdiff_t offset,
219                           InlineKlass* klass,
220                           LayoutKind layout_kind);
221 
222   inline FlatFieldPayload(instanceOop container,
223                           ptrdiff_t offset,
224                           InlineLayoutInfo* inline_layout_info);
225 
226   inline void assert_post_construction_invariants(instanceOop container,
227                                                   ResolvedFieldEntry* resolved_field_entry,
228                                                   InstanceKlass* klass) const NOT_DEBUG_RETURN;
229   inline void assert_post_construction_invariants(instanceOop container,
230                                                   fieldDescriptor* field_descriptor,
231                                                   InstanceKlass* klass) const NOT_DEBUG_RETURN;
232 
233 public:
234   FlatFieldPayload() = default;
235 
236   inline FlatFieldPayload(instanceOop container,
237                           fieldDescriptor* field_descriptor);
238   inline FlatFieldPayload(instanceOop container,
239                           fieldDescriptor* field_descriptor,
240                           InstanceKlass* klass);
241 
242   inline FlatFieldPayload(instanceOop container,
243                           ResolvedFieldEntry* resolved_field_entry);
244   inline FlatFieldPayload(instanceOop container,
245                           ResolvedFieldEntry* resolved_field_entry,
246                           InstanceKlass* klass);
247 
248   inline instanceOop container() const;
249 
250   class Handle;
251   class OopHandle;
252 
253   inline Handle make_handle(JavaThread* thread) const;
254   inline OopHandle make_oop_handle(OopStorage* storage) const;
255 };
256 
257 class FlatArrayPayload : public FlatValuePayload {
258 private:
259   struct Storage {
260     jint _layout_helper;
261     int _element_size;
262   } _storage;
263 
264   inline FlatArrayPayload(flatArrayOop container,
265                           ptrdiff_t offset,
266                           InlineKlass* klass,
267                           LayoutKind layout_kind,
268                           jint layout_helper,
269                           int element_size);
270 
271 public:
272   FlatArrayPayload() = default;
273   FlatArrayPayload(const FlatArrayPayload&) = default;
274   FlatArrayPayload& operator=(const FlatArrayPayload&) = default;
275 
276   explicit inline FlatArrayPayload(flatArrayOop container);
277   inline FlatArrayPayload(flatArrayOop container, FlatArrayKlass* klass);
278 
279   inline FlatArrayPayload(flatArrayOop container, int index);
280   inline FlatArrayPayload(flatArrayOop container, int index, FlatArrayKlass* klass);
281 
282   inline flatArrayOop container() const;
283 
284   inline void set_index(int index);
285   inline void advance_index(int delta);
286 
287   inline void next_element();
288   inline void previous_element();
289 
290 private:
291   inline void set_offset(ptrdiff_t offset);
292 
293 public:
294   class Handle;
295   class OopHandle;
296 
297   inline Handle make_handle(JavaThread* thread) const;
298   inline OopHandle make_oop_handle(OopStorage* storage) const;
299 };
300 
301 class ValuePayload::Handle {
302 private:
303   using Storage = StorageImpl<::Handle>;
304 
305   Storage _storage;
306 
307 protected:
308   inline Handle(const ValuePayload& payload, JavaThread* thread);
309 
310   inline oop container() const;
311 
312 public:
313   Handle() = default;
314   Handle(const Handle&) = default;
315   Handle& operator=(const Handle&) = default;
316 
317   inline InlineKlass* klass() const;
318   inline ptrdiff_t offset() const;
319   inline LayoutKind layout_kind() const;
320 };
321 
322 class ValuePayload::OopHandle {
323 private:
324   using Storage = StorageImpl<::OopHandle>;
325 
326   Storage _storage;
327 
328 protected:
329   inline OopHandle(const ValuePayload& payload, OopStorage* storage);
330 
331   inline oop container() const;
332 
333 public:
334   OopHandle() = default;
335   OopHandle(const OopHandle&) = default;
336   OopHandle& operator=(const OopHandle&) = default;
337 
338   inline void release(OopStorage* storage);
339 
340   inline InlineKlass* klass() const;
341   inline ptrdiff_t offset() const;
342   inline LayoutKind layout_kind() const;
343 };
344 
345 class BufferedValuePayload::Handle : public ValuePayload::Handle {
346 public:
347   inline Handle(const BufferedValuePayload& payload, JavaThread* thread);
348 
349   inline BufferedValuePayload operator()() const;
350 
351   inline inlineOop container() const;
352 };
353 
354 class BufferedValuePayload::OopHandle : public ValuePayload::OopHandle {
355 public:
356   inline OopHandle(const BufferedValuePayload& payload, OopStorage* storage);
357 
358   inline BufferedValuePayload operator()() const;
359 
360   inline inlineOop container() const;
361 };
362 
363 class FlatValuePayload::Handle : public ValuePayload::Handle {
364 public:
365   inline Handle(const FlatValuePayload& payload, JavaThread* thread);
366 
367   inline FlatValuePayload operator()() const;
368 };
369 
370 class FlatValuePayload::OopHandle : public ValuePayload::OopHandle {
371 public:
372   inline OopHandle(const FlatValuePayload& payload, OopStorage* storage);
373 
374   inline FlatValuePayload operator()() const;
375 };
376 
377 class FlatFieldPayload::Handle : public FlatValuePayload::Handle {
378 public:
379   inline Handle(const FlatFieldPayload& payload, JavaThread* thread);
380 
381   inline FlatFieldPayload operator()() const;
382 
383   inline instanceOop container() const;
384 };
385 
386 class FlatFieldPayload::OopHandle : public FlatValuePayload::OopHandle {
387 public:
388   inline OopHandle(const FlatFieldPayload& payload, OopStorage* storage);
389 
390   inline FlatFieldPayload operator()() const;
391 
392   inline instanceOop container() const;
393 };
394 
395 class FlatArrayPayload::Handle : public FlatValuePayload::Handle {
396 private:
397   FlatArrayPayload::Storage _storage;
398 
399 public:
400   inline Handle(const FlatArrayPayload& payload, JavaThread* thread);
401 
402   inline FlatArrayPayload operator()() const;
403 
404   inline flatArrayOop container() const;
405 };
406 
407 class FlatArrayPayload::OopHandle : public FlatValuePayload::OopHandle {
408 private:
409   FlatArrayPayload::Storage _storage;
410 
411 public:
412   inline OopHandle(const FlatArrayPayload& payload, OopStorage* storage);
413 
414   inline FlatArrayPayload operator()() const;
415 
416   inline flatArrayOop container() const;
417 };
418 
419 #endif // SHARE_VM_OOPS_VALUEPAYLOAD_HPP