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