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_INLINE_HPP
26 #define SHARE_VM_OOPS_VALUEPAYLOAD_INLINE_HPP
27
28 #include "oops/valuePayload.hpp"
29
30 #include "cppstdlib/type_traits.hpp"
31 #include "oops/flatArrayKlass.inline.hpp"
32 #include "oops/inlineKlass.inline.hpp"
33 #include "oops/layoutKind.hpp"
34 #include "oops/oopHandle.inline.hpp"
35 #include "oops/oopsHierarchy.hpp"
36 #include "oops/resolvedFieldEntry.hpp"
37 #include "runtime/fieldDescriptor.inline.hpp"
38 #include "runtime/handles.inline.hpp"
39 #include "runtime/javaThread.inline.hpp"
40 #include "utilities/debug.hpp"
41 #include "utilities/ostream.hpp"
42 #include "utilities/vmError.hpp"
43
44 template <typename OopOrHandle>
45 inline ValuePayload::StorageImpl<OopOrHandle>::StorageImpl()
46 : _container(nullptr),
47 _offset(BAD_OFFSET),
48 _klass(nullptr),
49 _layout_kind(LayoutKind::UNKNOWN),
50 _uses_absolute_addr(false) {}
51
52 template <typename OopOrHandle>
53 inline ValuePayload::StorageImpl<OopOrHandle>::StorageImpl(OopOrHandle container,
54 ptrdiff_t offset,
55 InlineKlass* klass,
56 LayoutKind layout_kind)
57 : _container(container),
58 _offset(offset),
59 _klass(klass),
60 _layout_kind(layout_kind),
61 _uses_absolute_addr(false) {}
62
63 template <typename OopOrHandle>
64 inline ValuePayload::StorageImpl<OopOrHandle>::StorageImpl(address absolute_addr,
65 InlineKlass* klass,
66 LayoutKind layout_kind)
67 : _absolute_addr(absolute_addr),
68 _klass(klass),
69 _layout_kind(layout_kind),
70 _uses_absolute_addr(true) {}
71
72 template <typename OopOrHandle>
73 inline ValuePayload::StorageImpl<OopOrHandle>::~StorageImpl() {
74 #ifdef CHECK_UNHANDLED_OOPS
75 if (!_uses_absolute_addr) {
76 _container.~OopOrHandle();
77 }
78 #else // CHECK_UNHANDLED_OOPS
79 static_assert(std::is_trivially_destructible_v<OopOrHandle>);
80 #endif // CHECK_UNHANDLED_OOPS
81 }
82
83 template <typename OopOrHandle>
84 inline ValuePayload::StorageImpl<OopOrHandle>::StorageImpl(const StorageImpl& other)
85 : _klass(other._klass),
86 _layout_kind(other._layout_kind),
87 _uses_absolute_addr(other._uses_absolute_addr) {
88 if (_uses_absolute_addr) {
89 _absolute_addr = other._absolute_addr;
90 } else {
91 _container = other._container;
92 _offset = other._offset;
93 }
94 }
95
96 template <typename OopOrHandle>
97 inline ValuePayload::StorageImpl<OopOrHandle>&
98 ValuePayload::StorageImpl<OopOrHandle>::operator=(const StorageImpl& other) {
99 if (&other != this) {
100 _klass = other._klass;
101 _layout_kind = other._layout_kind;
102 _uses_absolute_addr = other._uses_absolute_addr;
103 if (_uses_absolute_addr) {
104 _absolute_addr = other._absolute_addr;
105 } else {
106 _container = other._container;
107 _offset = other._offset;
108 }
109 }
110 return *this;
111 }
112
113 template <typename OopOrHandle>
114 inline OopOrHandle& ValuePayload::StorageImpl<OopOrHandle>::container() {
115 precond(!_uses_absolute_addr);
116 return _container;
117 }
118
119 template <typename OopOrHandle>
120 inline OopOrHandle ValuePayload::StorageImpl<OopOrHandle>::container() const {
121 precond(!_uses_absolute_addr);
122 return _container;
123 }
124
125 template <typename OopOrHandle>
126 inline ptrdiff_t& ValuePayload::StorageImpl<OopOrHandle>::offset() {
127 precond(!_uses_absolute_addr);
128 return _offset;
129 }
130
131 template <typename OopOrHandle>
132 inline ptrdiff_t ValuePayload::StorageImpl<OopOrHandle>::offset() const {
133 precond(!_uses_absolute_addr);
134 return _offset;
135 }
136
137 template <typename OopOrHandle>
138 inline address& ValuePayload::StorageImpl<OopOrHandle>::absolute_addr() {
139 precond(_uses_absolute_addr);
140 return _absolute_addr;
141 }
142
143 template <typename OopOrHandle>
144 inline address ValuePayload::StorageImpl<OopOrHandle>::absolute_addr() const {
145 precond(_uses_absolute_addr);
146 return _absolute_addr;
147
148 }
149
150 template <typename OopOrHandle>
151 inline InlineKlass* ValuePayload::StorageImpl<OopOrHandle>::klass() const {
152 return _klass;
153 }
154
155 template <typename OopOrHandle>
156 inline LayoutKind ValuePayload::StorageImpl<OopOrHandle>::layout_kind() const {
157 return _layout_kind;
158 }
159
160 template <typename OopOrHandle>
161 inline bool ValuePayload::StorageImpl<OopOrHandle>::uses_absolute_addr() const {
162 return _uses_absolute_addr;
163 }
164
165 inline ValuePayload::ValuePayload(oop container,
166 ptrdiff_t offset,
167 InlineKlass* klass,
168 LayoutKind layout_kind)
169 : _storage{container, offset, klass, layout_kind} {
170 assert_post_construction_invariants();
171 }
172
173 inline ValuePayload::ValuePayload(address absolute_addr,
174 InlineKlass* klass,
175 LayoutKind layout_kind)
176 : _storage{absolute_addr, klass, layout_kind} {
177 assert_post_construction_invariants();
178 }
179
180 inline void ValuePayload::set_offset(ptrdiff_t offset) {
181 _storage.offset() = offset;
182 }
183
184 inline void ValuePayload::copy(const ValuePayload& src,
185 const ValuePayload& dst,
186 LayoutKind copy_layout_kind) {
187 assert_pre_copy_invariants(src, dst, copy_layout_kind);
188
189 InlineKlass* const klass = src.klass();
190
191 switch (copy_layout_kind) {
192 case LayoutKind::NULLABLE_ATOMIC_FLAT:
193 case LayoutKind::NULLABLE_NON_ATOMIC_FLAT: {
194 if (src.is_payload_null()) {
195 HeapAccess<>::value_store_null(dst);
196 } else {
197 HeapAccess<>::value_copy(src, dst);
198 }
199 } break;
200 case LayoutKind::BUFFERED:
201 case LayoutKind::NULL_FREE_ATOMIC_FLAT:
202 case LayoutKind::NULL_FREE_NON_ATOMIC_FLAT: {
203 if (!klass->is_empty_inline_type()) {
204 HeapAccess<>::value_copy(src, dst);
205 }
206 } break;
207 default:
208 ShouldNotReachHere();
209 }
210 }
211
212 inline void ValuePayload::mark_as_non_null() {
213 precond(has_null_marker());
214 klass()->mark_payload_as_non_null(addr());
215 }
216
217 inline void ValuePayload::mark_as_null() {
218 precond(has_null_marker());
219 klass()->mark_payload_as_null(addr());
220 }
221
222 inline bool ValuePayload::uses_absolute_addr() const {
223 return _storage.uses_absolute_addr();
224 }
225
226 inline oop& ValuePayload::container() {
227 return _storage.container();
228 }
229
230 inline oop ValuePayload::container() const {
231 return _storage.container();
232 }
233
234 #ifdef ASSERT
235
236 inline void ValuePayload::print_on(outputStream* st) const {
237 if (uses_absolute_addr()) {
238 st->print_cr("--- absolute_addr ---");
239 StreamIndentor si(st);
240 st->print_cr("_absolute_addr: " PTR_FORMAT, p2i(_storage.absolute_addr()));
241 } else {
242 {
243 oop container = _storage.container();
244 st->print_cr("--- container ---");
245 StreamIndentor si(st);
246 st->print_cr("_container: " PTR_FORMAT, p2i(container));
247 if (container != nullptr) {
248 container->print_on(st);
249 st->cr();
250 }
251 }
252 {
253 st->print_cr("--- offset ---");
254 StreamIndentor si(st);
255 st->print_cr("_offset: %zd", _storage.offset());
256 }
257 }
258 {
259 InlineKlass* const klass = _storage.klass();
260 st->print_cr("--- klass ---");
261 StreamIndentor si(st);
262 st->print_cr("_klass: " PTR_FORMAT, p2i(klass));
263 if (klass != nullptr) {
264 klass->print_on(st);
265 st->cr();
266 }
267 }
268 {
269 const LayoutKind layout_kind = _storage.layout_kind();
270 st->print_cr("--- layout_kind ---");
271 StreamIndentor si(st);
272 st->print_cr("_layout_kind: %u", (uint32_t)layout_kind);
273 LayoutKindHelper::print_on(layout_kind, st);
274 st->cr();
275 }
276 }
277
278 inline void ValuePayload::assert_post_construction_invariants() const {
279 OnVMError on_assertion_failure([&](outputStream* st) {
280 st->print_cr("=== assert_post_construction_invariants failure ===");
281 StreamIndentor si(st);
282 print_on(st);
283 st->cr();
284 });
285
286 postcond(uses_absolute_addr() || container() != nullptr);
287 postcond(layout_kind() != LayoutKind::REFERENCE);
288 postcond(layout_kind() != LayoutKind::UNKNOWN);
289 postcond(klass()->is_layout_supported(layout_kind()));
290 postcond(uses_absolute_addr() || (container()->klass() == klass()) ==
291 (layout_kind() == LayoutKind::BUFFERED));
292 }
293
294 inline void ValuePayload::assert_pre_copy_invariants(const ValuePayload& src,
295 const ValuePayload& dst,
296 LayoutKind copy_layout_kind) {
297 OnVMError on_assertion_failuire([&](outputStream* st) {
298 st->print_cr("=== assert_post_construction_invariants failure ===");
299 StreamIndentor si(st);
300 {
301 st->print_cr("--- src payload ---");
302 StreamIndentor si(st);
303 src.print_on(st);
304 st->cr();
305 }
306 {
307 st->print_cr("--- dst payload ---");
308 StreamIndentor si(st);
309 dst.print_on(st);
310 st->cr();
311 }
312 {
313 st->print_cr("--- copy layout kind ---");
314 StreamIndentor si(st);
315 LayoutKindHelper::print_on(copy_layout_kind, st);
316 st->cr();
317 }
318 });
319
320 const InlineKlass* const src_klass = src.klass();
321 const InlineKlass* const dst_klass = dst.klass();
322
323 precond(src_klass == dst_klass);
324
325 const bool src_is_buffered = src.layout_kind() == LayoutKind::BUFFERED;
326 const bool dst_is_buffered = dst.layout_kind() == LayoutKind::BUFFERED;
327 const bool src_and_dst_same_layout_kind = src.layout_kind() == dst.layout_kind();
328 const bool src_has_copy_layout = src.layout_kind() == copy_layout_kind;
329 const bool dst_has_copy_layout = dst.layout_kind() == copy_layout_kind;
330
331 precond(src_is_buffered || dst_is_buffered || src_and_dst_same_layout_kind);
332 precond(src_has_copy_layout || dst_has_copy_layout);
333
334 if (src_is_buffered) {
335 oop container = src.uses_absolute_addr()
336 ? cast_to_oop(src.addr() - src_klass->payload_offset())
337 : src.container();
338
339 precond(container != src_klass->null_reset_value());
340 }
341
342 const int src_layout_size_in_bytes = src_klass->layout_size_in_bytes(src.layout_kind());
343 const int dst_layout_size_in_bytes = dst_klass->layout_size_in_bytes(dst.layout_kind());
344 const int copy_layout_size_in_bytes =
345 src_has_copy_layout
346 ? src_layout_size_in_bytes
347 : dst_layout_size_in_bytes;
348
349 precond(copy_layout_size_in_bytes <= src_layout_size_in_bytes);
350 precond(copy_layout_size_in_bytes <= dst_layout_size_in_bytes);
351 precond(LayoutKindHelper::get_copy_layout(src.layout_kind(),
352 dst.layout_kind()) == copy_layout_kind);
353 }
354
355 #endif // ASSERT
356
357 inline InlineKlass* ValuePayload::klass() const {
358 return _storage.klass();
359 }
360
361 inline ptrdiff_t ValuePayload::offset() const {
362 precond(_storage.offset() != BAD_OFFSET);
363 return _storage.offset();
364 }
365
366 inline LayoutKind ValuePayload::layout_kind() const {
367 return _storage.layout_kind();
368 }
369
370 inline address ValuePayload::addr() const {
371 return uses_absolute_addr()
372 ? _storage.absolute_addr()
373 : (cast_from_oop<address>(container()) + offset());
374 }
375
376 inline bool ValuePayload::has_null_marker() const {
377 return klass()->layout_has_null_marker(layout_kind());
378 }
379
380 inline bool ValuePayload::is_payload_null() const {
381 return has_null_marker() && klass()->is_payload_marked_as_null(addr());
382 }
383
384 inline ValuePayload ValuePayload::construct_from_parts(address absolute_addr,
385 InlineKlass* klass,
386 LayoutKind layout_kind) {
387 return ValuePayload(absolute_addr, klass, layout_kind);
388 }
389
390 inline BufferedValuePayload::BufferedValuePayload(inlineOop container,
391 ptrdiff_t offset,
392 InlineKlass* klass,
393 LayoutKind layout_kind)
394 : ValuePayload(container, offset, klass, layout_kind) {}
395
396 inline BufferedValuePayload::BufferedValuePayload(inlineOop buffer)
397 : BufferedValuePayload(buffer, InlineKlass::cast(buffer->klass())) {}
398
399 inline BufferedValuePayload::BufferedValuePayload(inlineOop buffer,
400 InlineKlass* klass)
401 : ValuePayload(buffer, klass->payload_offset(), klass, LayoutKind::BUFFERED) {}
402
403 inline inlineOop BufferedValuePayload::container() const {
404 return inlineOop(ValuePayload::container());
405 }
406
407 inline void BufferedValuePayload::copy_to(const BufferedValuePayload& dst) {
408 copy(*this, dst, LayoutKind::BUFFERED);
409 }
410
411 inline FlatValuePayload::FlatValuePayload(oop container,
412 ptrdiff_t offset,
413 InlineKlass* klass,
414 LayoutKind layout_kind)
415 : ValuePayload(container, offset, klass, layout_kind) {}
416
417 inline inlineOop FlatValuePayload::allocate_instance(TRAPS) {
418 // Preserve the container oop across the instance allocation.
419 oop& container = this->container();
420 ::Handle container_handle(THREAD, container);
421 inlineOop res = klass()->allocate_instance(THREAD);
422 container = container_handle();
423 return res;
424 }
425
426 inline bool FlatValuePayload::copy_to(BufferedValuePayload& dst) {
427 // Copy from FLAT to BUFFERED, null marker fix may be required.
428
429 // Copy the payload to the buffered object.
430 copy(*this, dst, layout_kind());
431
432 if (!has_null_marker() && dst.has_null_marker()) {
433 // We must fix the null marker if the src does not have a null marker but
434 // the buffered object does.
435 dst.mark_as_non_null();
436
437 // The buffered object was just marked non null.
438 return true;
439 }
440
441 if (dst.is_payload_null()) {
442 // A null payload is not a valid payload for a buffered value.
443 return false;
444 }
445
446 return true;
447 }
448
449 inline void FlatValuePayload::copy_from(BufferedValuePayload& src) {
450 // Copy from BUFFERED to FLAT, null marker fix may be required.
451
452 if (has_null_marker()) {
453 // The FLAT payload has a null mark. So make sure that buffered is marked as
454 // non null. It is the callers responsibility to ensure that this is a
455 // valid non null value.
456 src.mark_as_non_null();
457 }
458 copy(src, *this, layout_kind());
459 }
460
461 inline void FlatValuePayload::copy_to(const FlatValuePayload& dst) {
462 copy(*this, dst, layout_kind());
463 }
464
465 inline inlineOop FlatValuePayload::read(TRAPS) {
466 switch (layout_kind()) {
467 case LayoutKind::NULLABLE_ATOMIC_FLAT:
468 case LayoutKind::NULLABLE_NON_ATOMIC_FLAT: {
469 if (is_payload_null()) {
470 return nullptr;
471 }
472 } // Fallthrough
473 case LayoutKind::NULL_FREE_ATOMIC_FLAT:
474 case LayoutKind::NULL_FREE_NON_ATOMIC_FLAT: {
475 inlineOop res = allocate_instance(CHECK_NULL);
476 BufferedValuePayload dst(res, klass());
477 if (!copy_to(dst)) {
478 // copy_to may fail if the payload has been updated with a null value
479 // between our is_payload_null() check above and the copy.
480 // In this case we have copied a null value into the buffer the payload.
481 return nullptr;
482 }
483 return res;
484 } break;
485 default:
486 ShouldNotReachHere();
487 }
488 }
489
490 inline void FlatValuePayload::write_without_nullability_check(inlineOop obj) {
491 if (obj == nullptr) {
492 assert(has_null_marker(), "Payload must support null values");
493 HeapAccess<>::value_store_null(*this);
494 } else {
495 // Copy the obj payload
496 BufferedValuePayload obj_payload(obj);
497 copy_from(obj_payload);
498 }
499 }
500
501 inline void FlatValuePayload::write(inlineOop obj, TRAPS) {
502 if (obj == nullptr && !has_null_marker()) {
503 // This payload does not have a null marker and cannot represent a null
504 // value.
505 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Value is null");
506 }
507 write_without_nullability_check(obj);
508 }
509
510 inline FlatValuePayload FlatValuePayload::construct_from_parts(oop container,
511 ptrdiff_t offset,
512 InlineKlass* klass,
513 LayoutKind layout_kind) {
514 return FlatValuePayload(container, offset, klass, layout_kind);
515 }
516
517 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
518 ptrdiff_t offset,
519 InlineKlass* klass,
520 LayoutKind layout_kind)
521 : FlatValuePayload(container, offset, klass, layout_kind) {}
522
523 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
524 ptrdiff_t offset,
525 InlineLayoutInfo* inline_layout_info)
526 : FlatValuePayload(container, offset, inline_layout_info->klass(), inline_layout_info->kind()) {}
527
528 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
529 fieldDescriptor* field_descriptor)
530 : FlatFieldPayload(container, field_descriptor,
531 InstanceKlass::cast(container->klass())) {}
532
533 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
534 fieldDescriptor* field_descriptor,
535 InstanceKlass* klass)
536 : FlatFieldPayload(container,
537 field_descriptor->offset(),
538 klass->inline_layout_info_adr(field_descriptor->index())) {
539 postcond(container->klass() == klass);
540 }
541
542 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
543 ResolvedFieldEntry* resolved_field_entry)
544 : FlatFieldPayload(container,
545 resolved_field_entry,
546 resolved_field_entry->field_holder()) {}
547
548 inline FlatFieldPayload::FlatFieldPayload(instanceOop container,
549 ResolvedFieldEntry* resolved_field_entry,
550 InstanceKlass* klass)
551 : FlatFieldPayload(container,
552 resolved_field_entry->field_offset(),
553 klass->inline_layout_info_adr(resolved_field_entry->field_index())) {
554 postcond(container->klass()->is_subclass_of(klass));
555 }
556
557 inline instanceOop FlatFieldPayload::container() const {
558 return instanceOop(ValuePayload::container());
559 }
560
561 inline FlatArrayPayload::FlatArrayPayload(flatArrayOop container,
562 ptrdiff_t offset,
563 InlineKlass* klass,
564 LayoutKind layout_kind,
565 jint layout_helper,
566 int element_size)
567 : FlatValuePayload(container, offset, klass, layout_kind),
568 _storage{layout_helper, element_size} {}
569
570 inline FlatArrayPayload::FlatArrayPayload(flatArrayOop container)
571 : FlatArrayPayload(container, FlatArrayKlass::cast(container->klass())) {}
572
573 inline FlatArrayPayload::FlatArrayPayload(flatArrayOop container, FlatArrayKlass* klass)
574 : FlatArrayPayload(container,
575 BAD_OFFSET,
576 klass->element_klass(),
577 klass->layout_kind(),
578 klass->layout_helper(),
579 klass->element_byte_size()) {
580 postcond(container->klass() == klass);
581 }
582
583 inline FlatArrayPayload::FlatArrayPayload(flatArrayOop container, int index)
584 : FlatArrayPayload(container, index, FlatArrayKlass::cast(container->klass())) {}
585
586 inline FlatArrayPayload::FlatArrayPayload(flatArrayOop container,
587 int index,
588 FlatArrayKlass* klass)
589 : FlatArrayPayload(container,
590 (ptrdiff_t)container->value_offset(index, klass->layout_helper()),
591 klass->element_klass(),
592 klass->layout_kind(),
593 klass->layout_helper(),
594 klass->element_byte_size()) {
595 postcond(container->klass() == klass);
596 }
597
598 inline flatArrayOop FlatArrayPayload::container() const {
599 return flatArrayOop(ValuePayload::container());
600 }
601
602 inline void FlatArrayPayload::set_index(int index) {
603 set_offset((ptrdiff_t)container()->value_offset(index, _storage._layout_helper));
604 }
605
606 inline void FlatArrayPayload::advance_index(int delta) {
607 set_offset(this->offset() + delta * _storage._element_size);
608 }
609
610 inline void FlatArrayPayload::next_element() {
611 advance_index(1);
612 }
613
614 inline void FlatArrayPayload::previous_element() {
615 advance_index(-1);
616 }
617
618 inline void FlatArrayPayload::set_offset(ptrdiff_t offset) {
619 #if defined(ASSERT) && defined(_LP64)
620 // For ease of use as iterators we allow the offset to point one element size
621 // beyond the first and last element. If there are no elements only the base
622 // offset is allowed. However we treat these as terminal states, and set the
623 // offset to a BAD_OFFSET in debug builds.
624
625 const ptrdiff_t element_size = _storage._element_size;
626 const ptrdiff_t length = container()->length();
627 const ptrdiff_t base_offset = (ptrdiff_t)flatArrayOopDesc::base_offset_in_bytes();
628
629 const ptrdiff_t min_offset = base_offset - (length == 0 ? 0 : element_size);
630 const ptrdiff_t max_offset = base_offset + length * element_size;
631 assert(min_offset <= offset && offset <= max_offset,
632 "Offset out-ouf-bounds: %zd <= %zd <= %zd", min_offset, offset, max_offset);
633
634 if (offset == min_offset || offset == max_offset) {
635 // Terminal state of iteration, set a bad value.
636 ValuePayload::set_offset(BAD_OFFSET);
637 } else {
638 ValuePayload::set_offset(offset);
639 }
640 #else // ASSERT
641 ValuePayload::set_offset(offset);
642 #endif // ASSERT
643 }
644
645 inline ValuePayload::Handle::Handle(const ValuePayload& payload, JavaThread* thread)
646 : _storage{::Handle(thread, payload.container()),
647 payload.offset(),
648 payload.klass(),
649 payload.layout_kind()} {}
650
651 inline oop ValuePayload::Handle::container() const {
652 return _storage.container()();
653 }
654
655 inline InlineKlass* ValuePayload::Handle::klass() const {
656 return _storage.klass();
657 }
658
659 inline ptrdiff_t ValuePayload::Handle::offset() const {
660 return _storage.offset();
661 }
662
663 inline LayoutKind ValuePayload::Handle::layout_kind() const {
664 return _storage.layout_kind();
665 }
666
667 inline ValuePayload::OopHandle::OopHandle(const ValuePayload& payload, OopStorage* storage)
668 : _storage{::OopHandle(storage, payload.container()),
669 payload.offset(),
670 payload.klass(),
671 payload.layout_kind()} {}
672
673 inline oop ValuePayload::OopHandle::container() const {
674 return _storage.container().resolve();
675 }
676
677 inline void ValuePayload::OopHandle::release(OopStorage* storage) {
678 return _storage.container().release(storage);
679 }
680
681 inline InlineKlass* ValuePayload::OopHandle::klass() const {
682 return _storage.klass();
683 }
684
685 inline ptrdiff_t ValuePayload::OopHandle::offset() const {
686 return _storage.offset();
687 }
688
689 inline LayoutKind ValuePayload::OopHandle::layout_kind() const {
690 return _storage.layout_kind();
691 }
692
693 inline BufferedValuePayload::Handle::Handle(const BufferedValuePayload& payload, JavaThread* thread)
694 : ValuePayload::Handle(payload, thread) {}
695
696 inline BufferedValuePayload BufferedValuePayload::Handle::operator()() const {
697 return BufferedValuePayload(container(), offset(), klass(), layout_kind());
698 }
699
700 inline inlineOop BufferedValuePayload::Handle::container() const {
701 return inlineOop(ValuePayload::Handle::container());
702 }
703
704 inline BufferedValuePayload::Handle BufferedValuePayload::make_handle(JavaThread* thread) const {
705 return Handle(*this, thread);
706 }
707
708 inline BufferedValuePayload::OopHandle::OopHandle(const BufferedValuePayload& payload,
709 OopStorage* storage)
710 : ValuePayload::OopHandle(payload, storage) {}
711
712 inline BufferedValuePayload BufferedValuePayload::OopHandle::operator()() const {
713 return BufferedValuePayload(container(), offset(), klass(), layout_kind());
714 }
715
716 inline inlineOop BufferedValuePayload::OopHandle::container() const {
717 return inlineOop(ValuePayload::OopHandle::container());
718 }
719
720 inline BufferedValuePayload::OopHandle BufferedValuePayload::make_oop_handle(OopStorage* storage) const {
721 return OopHandle(*this, storage);
722 }
723
724 inline FlatValuePayload::Handle::Handle(const FlatValuePayload& payload, JavaThread* thread)
725 : ValuePayload::Handle(payload, thread) {}
726
727 inline FlatValuePayload FlatValuePayload::Handle::operator()() const {
728 return FlatValuePayload(container(), offset(), klass(), layout_kind());
729 }
730
731 inline FlatValuePayload::Handle FlatValuePayload::make_handle(JavaThread* thread) const {
732 return Handle(*this, thread);
733 }
734
735 inline FlatValuePayload::OopHandle::OopHandle(const FlatValuePayload& payload, OopStorage* storage)
736 : ValuePayload::OopHandle(payload, storage) {}
737
738 inline FlatValuePayload FlatValuePayload::OopHandle::operator()() const {
739 return FlatValuePayload(container(), offset(), klass(), layout_kind());
740 }
741
742 inline FlatValuePayload::OopHandle FlatValuePayload::make_oop_handle(OopStorage* storage) const {
743 return OopHandle(*this, storage);
744 }
745
746 inline FlatFieldPayload::Handle::Handle(const FlatFieldPayload& payload, JavaThread* thread)
747 : FlatValuePayload::Handle(payload, thread) {}
748
749 inline FlatFieldPayload FlatFieldPayload::Handle::operator()() const {
750 return FlatFieldPayload(container(), offset(), klass(), layout_kind());
751 }
752
753 inline instanceOop FlatFieldPayload::Handle::container() const {
754 return instanceOop(ValuePayload::Handle::container());
755 }
756
757 inline FlatFieldPayload::Handle FlatFieldPayload::make_handle(JavaThread* thread) const {
758 return Handle(*this, thread);
759 }
760
761 inline FlatFieldPayload::OopHandle::OopHandle(const FlatFieldPayload& payload, OopStorage* storage)
762 : FlatValuePayload::OopHandle(payload, storage) {}
763
764 inline FlatFieldPayload FlatFieldPayload::OopHandle::operator()() const {
765 return FlatFieldPayload(container(), offset(), klass(), layout_kind());
766 }
767
768 inline instanceOop FlatFieldPayload::OopHandle::container() const {
769 return instanceOop(ValuePayload::OopHandle::container());
770 }
771
772 inline FlatFieldPayload::OopHandle FlatFieldPayload::make_oop_handle(OopStorage* storage) const {
773 return OopHandle(*this, storage);
774 }
775
776 inline FlatArrayPayload::Handle::Handle(const FlatArrayPayload& payload, JavaThread* thread)
777 : FlatValuePayload::Handle(payload, thread), _storage(payload._storage) {}
778
779 inline FlatArrayPayload FlatArrayPayload::Handle::operator()() const {
780 return FlatArrayPayload(container(),
781 offset(),
782 klass(),
783 layout_kind(),
784 _storage._layout_helper,
785 _storage._element_size);
786 }
787
788 inline flatArrayOop FlatArrayPayload::Handle::container() const {
789 return flatArrayOop(ValuePayload::Handle::container());
790 }
791
792 inline FlatArrayPayload::Handle FlatArrayPayload::make_handle(JavaThread* thread) const {
793 return Handle(*this, thread);
794 }
795
796 inline FlatArrayPayload::OopHandle::OopHandle(const FlatArrayPayload& payload, OopStorage* storage)
797 : FlatValuePayload::OopHandle(payload, storage),
798 _storage(payload._storage) {}
799
800 inline FlatArrayPayload FlatArrayPayload::OopHandle::operator()() const {
801 return FlatArrayPayload(container(),
802 offset(),
803 klass(),
804 layout_kind(),
805 _storage._layout_helper,
806 _storage._element_size);
807 }
808
809 inline flatArrayOop FlatArrayPayload::OopHandle::container() const {
810 return flatArrayOop(ValuePayload::OopHandle::container());
811 }
812
813 inline FlatArrayPayload::OopHandle FlatArrayPayload::make_oop_handle(OopStorage* storage) const {
814 return OopHandle(*this, storage);
815 }
816
817 #endif // SHARE_VM_OOPS_VALUEPAYLOAD_INLINE_HPP