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