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