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