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) const NOT_DEBUG_RETURN;
228   inline void assert_post_construction_invariants(instanceOop container,
229                                                   fieldDescriptor* field_descriptor) const NOT_DEBUG_RETURN;
230 
231 public:
232   FlatFieldPayload() = default;
233 
234   inline FlatFieldPayload(instanceOop container,
235                           fieldDescriptor* field_descriptor);
236 
237   inline FlatFieldPayload(instanceOop container,
238                           ResolvedFieldEntry* resolved_field_entry);
239 
240   inline instanceOop container() const;
241 
242   class Handle;
243   class OopHandle;
244 
245   inline Handle make_handle(JavaThread* thread) const;
246   inline OopHandle make_oop_handle(OopStorage* storage) const;
247 };
248 
249 class FlatArrayPayload : public FlatValuePayload {
250 private:
251   struct Storage {
252     jint _layout_helper;
253     int _element_size;
254   } _storage;
255 
256   inline FlatArrayPayload(flatArrayOop container,
257                           ptrdiff_t offset,
258                           InlineKlass* klass,
259                           LayoutKind layout_kind,
260                           jint layout_helper,
261                           int element_size);
262 
263 public:
264   FlatArrayPayload() = default;
265   FlatArrayPayload(const FlatArrayPayload&) = default;
266   FlatArrayPayload& operator=(const FlatArrayPayload&) = default;
267 
268   explicit inline FlatArrayPayload(flatArrayOop container);
269   inline FlatArrayPayload(flatArrayOop container, FlatArrayKlass* klass);
270 
271   inline FlatArrayPayload(flatArrayOop container, int index);
272   inline FlatArrayPayload(flatArrayOop container, int index, FlatArrayKlass* klass);
273 
274   inline flatArrayOop container() const;
275 
276   inline void set_index(int index);
277   inline void advance_index(int delta);
278 
279   inline void next_element();
280   inline void previous_element();
281 
282 private:
283   inline void set_offset(ptrdiff_t offset);
284 
285 public:
286   class Handle;
287   class OopHandle;
288 
289   inline Handle make_handle(JavaThread* thread) const;
290   inline OopHandle make_oop_handle(OopStorage* storage) const;
291 };
292 
293 class ValuePayload::Handle {
294 private:
295   using Storage = StorageImpl<::Handle>;
296 
297   Storage _storage;
298 
299 protected:
300   inline Handle(const ValuePayload& payload, JavaThread* thread);
301 
302   inline oop container() const;
303 
304 public:
305   Handle() = default;
306   Handle(const Handle&) = default;
307   Handle& operator=(const Handle&) = default;
308 
309   inline InlineKlass* klass() const;
310   inline ptrdiff_t offset() const;
311   inline LayoutKind layout_kind() const;
312 };
313 
314 class ValuePayload::OopHandle {
315 private:
316   using Storage = StorageImpl<::OopHandle>;
317 
318   Storage _storage;
319 
320 protected:
321   inline OopHandle(const ValuePayload& payload, OopStorage* storage);
322 
323   inline oop container() const;
324 
325 public:
326   OopHandle() = default;
327   OopHandle(const OopHandle&) = default;
328   OopHandle& operator=(const OopHandle&) = default;
329 
330   inline void release(OopStorage* storage);
331 
332   inline InlineKlass* klass() const;
333   inline ptrdiff_t offset() const;
334   inline LayoutKind layout_kind() const;
335 };
336 
337 class BufferedValuePayload::Handle : public ValuePayload::Handle {
338 public:
339   inline Handle(const BufferedValuePayload& payload, JavaThread* thread);
340 
341   inline BufferedValuePayload operator()() const;
342 
343   inline inlineOop container() const;
344 };
345 
346 class BufferedValuePayload::OopHandle : public ValuePayload::OopHandle {
347 public:
348   inline OopHandle(const BufferedValuePayload& payload, OopStorage* storage);
349 
350   inline BufferedValuePayload operator()() const;
351 
352   inline inlineOop container() const;
353 };
354 
355 class FlatValuePayload::Handle : public ValuePayload::Handle {
356 public:
357   inline Handle(const FlatValuePayload& payload, JavaThread* thread);
358 
359   inline FlatValuePayload operator()() const;
360 };
361 
362 class FlatValuePayload::OopHandle : public ValuePayload::OopHandle {
363 public:
364   inline OopHandle(const FlatValuePayload& payload, OopStorage* storage);
365 
366   inline FlatValuePayload operator()() const;
367 };
368 
369 class FlatFieldPayload::Handle : public FlatValuePayload::Handle {
370 public:
371   inline Handle(const FlatFieldPayload& payload, JavaThread* thread);
372 
373   inline FlatFieldPayload operator()() const;
374 
375   inline instanceOop container() const;
376 };
377 
378 class FlatFieldPayload::OopHandle : public FlatValuePayload::OopHandle {
379 public:
380   inline OopHandle(const FlatFieldPayload& payload, OopStorage* storage);
381 
382   inline FlatFieldPayload operator()() const;
383 
384   inline instanceOop container() const;
385 };
386 
387 class FlatArrayPayload::Handle : public FlatValuePayload::Handle {
388 private:
389   FlatArrayPayload::Storage _storage;
390 
391 public:
392   inline Handle(const FlatArrayPayload& payload, JavaThread* thread);
393 
394   inline FlatArrayPayload operator()() const;
395 
396   inline flatArrayOop container() const;
397 };
398 
399 class FlatArrayPayload::OopHandle : public FlatValuePayload::OopHandle {
400 private:
401   FlatArrayPayload::Storage _storage;
402 
403 public:
404   inline OopHandle(const FlatArrayPayload& payload, OopStorage* storage);
405 
406   inline FlatArrayPayload operator()() const;
407 
408   inline flatArrayOop container() const;
409 };
410 
411 #endif // SHARE_VM_OOPS_VALUEPAYLOAD_HPP