11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_HEAP_CPPGC_HEAP_OBJECT_HEADER_H_
61cb0ef41Sopenharmony_ci#define V8_HEAP_CPPGC_HEAP_OBJECT_HEADER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <stdint.h>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <atomic>
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "include/cppgc/allocation.h"
131cb0ef41Sopenharmony_ci#include "include/cppgc/internal/gc-info.h"
141cb0ef41Sopenharmony_ci#include "include/cppgc/internal/name-trait.h"
151cb0ef41Sopenharmony_ci#include "src/base/atomic-utils.h"
161cb0ef41Sopenharmony_ci#include "src/base/bit-field.h"
171cb0ef41Sopenharmony_ci#include "src/base/logging.h"
181cb0ef41Sopenharmony_ci#include "src/base/macros.h"
191cb0ef41Sopenharmony_ci#include "src/heap/cppgc/gc-info-table.h"
201cb0ef41Sopenharmony_ci#include "src/heap/cppgc/globals.h"
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP)
231cb0ef41Sopenharmony_ci#include "src/heap/cppgc/caged-heap.h"
241cb0ef41Sopenharmony_ci#endif  // defined(CPPGC_CAGED_HEAP)
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace cppgc {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciclass Visitor;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_cinamespace internal {
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci// HeapObjectHeader contains meta data per object and is prepended to each
331cb0ef41Sopenharmony_ci// object.
341cb0ef41Sopenharmony_ci//
351cb0ef41Sopenharmony_ci// +-----------------+------+------------------------------------------+
361cb0ef41Sopenharmony_ci// | name            | bits |                                          |
371cb0ef41Sopenharmony_ci// +-----------------+------+------------------------------------------+
381cb0ef41Sopenharmony_ci// | padding         |   32 | Only present on 64-bit platform.         |
391cb0ef41Sopenharmony_ci// +-----------------+------+------------------------------------------+
401cb0ef41Sopenharmony_ci// | GCInfoIndex     |   14 |                                          |
411cb0ef41Sopenharmony_ci// | unused          |    1 |                                          |
421cb0ef41Sopenharmony_ci// | in construction |    1 | In construction encoded as |false|.      |
431cb0ef41Sopenharmony_ci// +-----------------+------+------------------------------------------+
441cb0ef41Sopenharmony_ci// | size            |   15 | 17 bits because allocations are aligned. |
451cb0ef41Sopenharmony_ci// | mark bit        |    1 |                                          |
461cb0ef41Sopenharmony_ci// +-----------------+------+------------------------------------------+
471cb0ef41Sopenharmony_ci//
481cb0ef41Sopenharmony_ci// Notes:
491cb0ef41Sopenharmony_ci// - See |GCInfoTable| for constraints on GCInfoIndex.
501cb0ef41Sopenharmony_ci// - |size| for regular objects is encoded with 15 bits but can actually
511cb0ef41Sopenharmony_ci//   represent sizes up to |kBlinkPageSize| (2^17) because allocations are
521cb0ef41Sopenharmony_ci//   always 4 byte aligned (see kAllocationGranularity) on 32bit. 64bit uses
531cb0ef41Sopenharmony_ci//   8 byte aligned allocations which leaves 1 bit unused.
541cb0ef41Sopenharmony_ci// - |size| for large objects is encoded as 0. The size of a large object is
551cb0ef41Sopenharmony_ci//   stored in |LargeObjectPage::PayloadSize()|.
561cb0ef41Sopenharmony_ci// - |mark bit| and |in construction| bits are located in separate 16-bit halves
571cb0ef41Sopenharmony_ci//    to allow potentially accessing them non-atomically.
581cb0ef41Sopenharmony_ciclass HeapObjectHeader {
591cb0ef41Sopenharmony_ci public:
601cb0ef41Sopenharmony_ci  static constexpr size_t kSizeLog2 = 17;
611cb0ef41Sopenharmony_ci  static constexpr size_t kMaxSize = (size_t{1} << kSizeLog2) - 1;
621cb0ef41Sopenharmony_ci  static constexpr uint16_t kLargeObjectSizeInHeader = 0;
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  inline static HeapObjectHeader& FromObject(void* address);
651cb0ef41Sopenharmony_ci  inline static const HeapObjectHeader& FromObject(const void* address);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  inline HeapObjectHeader(size_t size, GCInfoIndex gc_info_index);
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  // The object starts directly after the HeapObjectHeader.
701cb0ef41Sopenharmony_ci  inline Address ObjectStart() const;
711cb0ef41Sopenharmony_ci  template <AccessMode mode = AccessMode::kNonAtomic>
721cb0ef41Sopenharmony_ci  inline Address ObjectEnd() const;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  template <AccessMode mode = AccessMode::kNonAtomic>
751cb0ef41Sopenharmony_ci  inline GCInfoIndex GetGCInfoIndex() const;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  template <AccessMode mode = AccessMode::kNonAtomic>
781cb0ef41Sopenharmony_ci  inline size_t AllocatedSize() const;
791cb0ef41Sopenharmony_ci  inline void SetAllocatedSize(size_t size);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  template <AccessMode mode = AccessMode::kNonAtomic>
821cb0ef41Sopenharmony_ci  inline size_t ObjectSize() const;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  template <AccessMode mode = AccessMode::kNonAtomic>
851cb0ef41Sopenharmony_ci  inline bool IsLargeObject() const;
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
881cb0ef41Sopenharmony_ci  bool IsInConstruction() const;
891cb0ef41Sopenharmony_ci  inline void MarkAsFullyConstructed();
901cb0ef41Sopenharmony_ci  // Use MarkObjectAsFullyConstructed() to mark an object as being constructed.
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
931cb0ef41Sopenharmony_ci  bool IsMarked() const;
941cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
951cb0ef41Sopenharmony_ci  void Unmark();
961cb0ef41Sopenharmony_ci  inline bool TryMarkAtomic();
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  inline void MarkNonAtomic();
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
1011cb0ef41Sopenharmony_ci  bool IsYoung() const;
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
1041cb0ef41Sopenharmony_ci  bool IsFree() const;
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  inline bool IsFinalizable() const;
1071cb0ef41Sopenharmony_ci  void Finalize();
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP)
1101cb0ef41Sopenharmony_ci  inline void SetNextUnfinalized(HeapObjectHeader* next);
1111cb0ef41Sopenharmony_ci  inline HeapObjectHeader* GetNextUnfinalized(uintptr_t cage_base) const;
1121cb0ef41Sopenharmony_ci#endif  // defined(CPPGC_CAGED_HEAP)
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE HeapObjectName GetName() const;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  template <AccessMode = AccessMode::kNonAtomic>
1171cb0ef41Sopenharmony_ci  void Trace(Visitor*) const;
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci private:
1201cb0ef41Sopenharmony_ci  enum class EncodedHalf : uint8_t { kLow, kHigh };
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  // Used in |encoded_high_|.
1231cb0ef41Sopenharmony_ci  using FullyConstructedField = v8::base::BitField16<bool, 0, 1>;
1241cb0ef41Sopenharmony_ci  using UnusedField1 = FullyConstructedField::Next<bool, 1>;
1251cb0ef41Sopenharmony_ci  using GCInfoIndexField = UnusedField1::Next<GCInfoIndex, 14>;
1261cb0ef41Sopenharmony_ci  // Used in |encoded_low_|.
1271cb0ef41Sopenharmony_ci  using MarkBitField = v8::base::BitField16<bool, 0, 1>;
1281cb0ef41Sopenharmony_ci  using SizeField =
1291cb0ef41Sopenharmony_ci      MarkBitField::Next<size_t, 15>;  // Use EncodeSize/DecodeSize instead.
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  static constexpr size_t DecodeSize(uint16_t encoded) {
1321cb0ef41Sopenharmony_ci    // Essentially, gets optimized to << 1.
1331cb0ef41Sopenharmony_ci    return SizeField::decode(encoded) * kAllocationGranularity;
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  static constexpr uint16_t EncodeSize(size_t size) {
1371cb0ef41Sopenharmony_ci    // Essentially, gets optimized to >> 1.
1381cb0ef41Sopenharmony_ci    return SizeField::encode(size / kAllocationGranularity);
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE void CheckApiConstants();
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  template <AccessMode, EncodedHalf part,
1441cb0ef41Sopenharmony_ci            std::memory_order memory_order = std::memory_order_seq_cst>
1451cb0ef41Sopenharmony_ci  inline uint16_t LoadEncoded() const;
1461cb0ef41Sopenharmony_ci  template <AccessMode mode, EncodedHalf part,
1471cb0ef41Sopenharmony_ci            std::memory_order memory_order = std::memory_order_seq_cst>
1481cb0ef41Sopenharmony_ci  inline void StoreEncoded(uint16_t bits, uint16_t mask);
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_64_BIT)
1511cb0ef41Sopenharmony_ci  // If cage is enabled, to save on space required by sweeper metadata, we store
1521cb0ef41Sopenharmony_ci  // the list of to-be-finalized objects inlined in HeapObjectHeader.
1531cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP)
1541cb0ef41Sopenharmony_ci  uint32_t next_unfinalized_ = 0;
1551cb0ef41Sopenharmony_ci#else   // !defined(CPPGC_CAGED_HEAP)
1561cb0ef41Sopenharmony_ci  uint32_t padding_ = 0;
1571cb0ef41Sopenharmony_ci#endif  // !defined(CPPGC_CAGED_HEAP)
1581cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_ARCH_64_BIT)
1591cb0ef41Sopenharmony_ci  uint16_t encoded_high_;
1601cb0ef41Sopenharmony_ci  uint16_t encoded_low_;
1611cb0ef41Sopenharmony_ci};
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_cistatic_assert(kAllocationGranularity == sizeof(HeapObjectHeader),
1641cb0ef41Sopenharmony_ci              "sizeof(HeapObjectHeader) must match allocation granularity to "
1651cb0ef41Sopenharmony_ci              "guarantee alignment");
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci// static
1681cb0ef41Sopenharmony_ciHeapObjectHeader& HeapObjectHeader::FromObject(void* object) {
1691cb0ef41Sopenharmony_ci  return *reinterpret_cast<HeapObjectHeader*>(static_cast<Address>(object) -
1701cb0ef41Sopenharmony_ci                                              sizeof(HeapObjectHeader));
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci// static
1741cb0ef41Sopenharmony_ciconst HeapObjectHeader& HeapObjectHeader::FromObject(const void* object) {
1751cb0ef41Sopenharmony_ci  return *reinterpret_cast<const HeapObjectHeader*>(
1761cb0ef41Sopenharmony_ci      static_cast<ConstAddress>(object) - sizeof(HeapObjectHeader));
1771cb0ef41Sopenharmony_ci}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ciHeapObjectHeader::HeapObjectHeader(size_t size, GCInfoIndex gc_info_index) {
1801cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_64_BIT) && !defined(CPPGC_CAGED_HEAP)
1811cb0ef41Sopenharmony_ci  USE(padding_);
1821cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_ARCH_64_BIT) && !defined(CPPGC_CAGED_HEAP)
1831cb0ef41Sopenharmony_ci  DCHECK_LT(gc_info_index, GCInfoTable::kMaxIndex);
1841cb0ef41Sopenharmony_ci  DCHECK_EQ(0u, size & (sizeof(HeapObjectHeader) - 1));
1851cb0ef41Sopenharmony_ci  DCHECK_GE(kMaxSize, size);
1861cb0ef41Sopenharmony_ci  encoded_low_ = EncodeSize(size);
1871cb0ef41Sopenharmony_ci  // Objects may get published to the marker without any other synchronization
1881cb0ef41Sopenharmony_ci  // (e.g., write barrier) in which case the in-construction bit is read
1891cb0ef41Sopenharmony_ci  // concurrently which requires reading encoded_high_ atomically. It is ok if
1901cb0ef41Sopenharmony_ci  // this write is not observed by the marker, since the sweeper  sets the
1911cb0ef41Sopenharmony_ci  // in-construction bit to 0 and we can rely on that to guarantee a correct
1921cb0ef41Sopenharmony_ci  // answer when checking if objects are in-construction.
1931cb0ef41Sopenharmony_ci  v8::base::AsAtomicPtr(&encoded_high_)
1941cb0ef41Sopenharmony_ci      ->store(GCInfoIndexField::encode(gc_info_index),
1951cb0ef41Sopenharmony_ci              std::memory_order_relaxed);
1961cb0ef41Sopenharmony_ci  DCHECK(IsInConstruction());
1971cb0ef41Sopenharmony_ci#ifdef DEBUG
1981cb0ef41Sopenharmony_ci  CheckApiConstants();
1991cb0ef41Sopenharmony_ci#endif  // DEBUG
2001cb0ef41Sopenharmony_ci}
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ciAddress HeapObjectHeader::ObjectStart() const {
2031cb0ef41Sopenharmony_ci  return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) +
2041cb0ef41Sopenharmony_ci         sizeof(HeapObjectHeader);
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_citemplate <AccessMode mode>
2081cb0ef41Sopenharmony_ciAddress HeapObjectHeader::ObjectEnd() const {
2091cb0ef41Sopenharmony_ci  DCHECK(!IsLargeObject());
2101cb0ef41Sopenharmony_ci  return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) +
2111cb0ef41Sopenharmony_ci         AllocatedSize<mode>();
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_citemplate <AccessMode mode>
2151cb0ef41Sopenharmony_ciGCInfoIndex HeapObjectHeader::GetGCInfoIndex() const {
2161cb0ef41Sopenharmony_ci  const uint16_t encoded =
2171cb0ef41Sopenharmony_ci      LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>();
2181cb0ef41Sopenharmony_ci  return GCInfoIndexField::decode(encoded);
2191cb0ef41Sopenharmony_ci}
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_citemplate <AccessMode mode>
2221cb0ef41Sopenharmony_cisize_t HeapObjectHeader::AllocatedSize() const {
2231cb0ef41Sopenharmony_ci  // Size is immutable after construction while either marking or sweeping
2241cb0ef41Sopenharmony_ci  // is running so relaxed load (if mode == kAtomic) is enough.
2251cb0ef41Sopenharmony_ci  uint16_t encoded_low_value =
2261cb0ef41Sopenharmony_ci      LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>();
2271cb0ef41Sopenharmony_ci  const size_t size = DecodeSize(encoded_low_value);
2281cb0ef41Sopenharmony_ci  return size;
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_civoid HeapObjectHeader::SetAllocatedSize(size_t size) {
2321cb0ef41Sopenharmony_ci#if !defined(CPPGC_YOUNG_GENERATION)
2331cb0ef41Sopenharmony_ci  // With sticky bits, marked objects correspond to old objects.
2341cb0ef41Sopenharmony_ci  // TODO(bikineev:1029379): Consider disallowing old/marked objects to be
2351cb0ef41Sopenharmony_ci  // resized.
2361cb0ef41Sopenharmony_ci  DCHECK(!IsMarked());
2371cb0ef41Sopenharmony_ci#endif
2381cb0ef41Sopenharmony_ci  // The object may be marked (i.e. old, in case young generation is enabled).
2391cb0ef41Sopenharmony_ci  // Make sure to not overwrite the mark bit.
2401cb0ef41Sopenharmony_ci  encoded_low_ &= ~SizeField::encode(SizeField::kMax);
2411cb0ef41Sopenharmony_ci  encoded_low_ |= EncodeSize(size);
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_citemplate <AccessMode mode>
2451cb0ef41Sopenharmony_cisize_t HeapObjectHeader::ObjectSize() const {
2461cb0ef41Sopenharmony_ci  // The following DCHECK also fails for large objects.
2471cb0ef41Sopenharmony_ci  DCHECK_GT(AllocatedSize<mode>(), sizeof(HeapObjectHeader));
2481cb0ef41Sopenharmony_ci  return AllocatedSize<mode>() - sizeof(HeapObjectHeader);
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_citemplate <AccessMode mode>
2521cb0ef41Sopenharmony_cibool HeapObjectHeader::IsLargeObject() const {
2531cb0ef41Sopenharmony_ci  return AllocatedSize<mode>() == kLargeObjectSizeInHeader;
2541cb0ef41Sopenharmony_ci}
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_citemplate <AccessMode mode>
2571cb0ef41Sopenharmony_cibool HeapObjectHeader::IsInConstruction() const {
2581cb0ef41Sopenharmony_ci  const uint16_t encoded =
2591cb0ef41Sopenharmony_ci      LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>();
2601cb0ef41Sopenharmony_ci  return !FullyConstructedField::decode(encoded);
2611cb0ef41Sopenharmony_ci}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_civoid HeapObjectHeader::MarkAsFullyConstructed() {
2641cb0ef41Sopenharmony_ci  MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
2651cb0ef41Sopenharmony_ci      ObjectStart());
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_citemplate <AccessMode mode>
2691cb0ef41Sopenharmony_cibool HeapObjectHeader::IsMarked() const {
2701cb0ef41Sopenharmony_ci  const uint16_t encoded =
2711cb0ef41Sopenharmony_ci      LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>();
2721cb0ef41Sopenharmony_ci  return MarkBitField::decode(encoded);
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_citemplate <AccessMode mode>
2761cb0ef41Sopenharmony_civoid HeapObjectHeader::Unmark() {
2771cb0ef41Sopenharmony_ci  DCHECK(IsMarked<mode>());
2781cb0ef41Sopenharmony_ci  StoreEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>(
2791cb0ef41Sopenharmony_ci      MarkBitField::encode(false), MarkBitField::kMask);
2801cb0ef41Sopenharmony_ci}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_cibool HeapObjectHeader::TryMarkAtomic() {
2831cb0ef41Sopenharmony_ci  auto* atomic_encoded = v8::base::AsAtomicPtr(&encoded_low_);
2841cb0ef41Sopenharmony_ci  uint16_t old_value = atomic_encoded->load(std::memory_order_relaxed);
2851cb0ef41Sopenharmony_ci  const uint16_t new_value = old_value | MarkBitField::encode(true);
2861cb0ef41Sopenharmony_ci  if (new_value == old_value) {
2871cb0ef41Sopenharmony_ci    return false;
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci  return atomic_encoded->compare_exchange_strong(old_value, new_value,
2901cb0ef41Sopenharmony_ci                                                 std::memory_order_relaxed);
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_civoid HeapObjectHeader::MarkNonAtomic() {
2941cb0ef41Sopenharmony_ci  DCHECK(!IsMarked<AccessMode::kNonAtomic>());
2951cb0ef41Sopenharmony_ci  encoded_low_ |= MarkBitField::encode(true);
2961cb0ef41Sopenharmony_ci}
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_citemplate <AccessMode mode>
2991cb0ef41Sopenharmony_cibool HeapObjectHeader::IsYoung() const {
3001cb0ef41Sopenharmony_ci  return !IsMarked<mode>();
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_citemplate <AccessMode mode>
3041cb0ef41Sopenharmony_cibool HeapObjectHeader::IsFree() const {
3051cb0ef41Sopenharmony_ci  return GetGCInfoIndex<mode>() == kFreeListGCInfoIndex;
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_cibool HeapObjectHeader::IsFinalizable() const {
3091cb0ef41Sopenharmony_ci  const GCInfo& gc_info = GlobalGCInfoTable::GCInfoFromIndex(GetGCInfoIndex());
3101cb0ef41Sopenharmony_ci  return gc_info.finalize;
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP)
3141cb0ef41Sopenharmony_civoid HeapObjectHeader::SetNextUnfinalized(HeapObjectHeader* next) {
3151cb0ef41Sopenharmony_ci  next_unfinalized_ = CagedHeap::OffsetFromAddress<uint32_t>(next);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ciHeapObjectHeader* HeapObjectHeader::GetNextUnfinalized(
3191cb0ef41Sopenharmony_ci    uintptr_t cage_base) const {
3201cb0ef41Sopenharmony_ci  DCHECK(cage_base);
3211cb0ef41Sopenharmony_ci  DCHECK_EQ(0u,
3221cb0ef41Sopenharmony_ci            CagedHeap::OffsetFromAddress(reinterpret_cast<void*>(cage_base)));
3231cb0ef41Sopenharmony_ci  return next_unfinalized_ ? reinterpret_cast<HeapObjectHeader*>(
3241cb0ef41Sopenharmony_ci                                 cage_base + next_unfinalized_)
3251cb0ef41Sopenharmony_ci                           : nullptr;
3261cb0ef41Sopenharmony_ci}
3271cb0ef41Sopenharmony_ci#endif  // defined(CPPGC_CAGED_HEAP)
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_citemplate <AccessMode mode>
3301cb0ef41Sopenharmony_civoid HeapObjectHeader::Trace(Visitor* visitor) const {
3311cb0ef41Sopenharmony_ci  const GCInfo& gc_info =
3321cb0ef41Sopenharmony_ci      GlobalGCInfoTable::GCInfoFromIndex(GetGCInfoIndex<mode>());
3331cb0ef41Sopenharmony_ci  return gc_info.trace(visitor, ObjectStart());
3341cb0ef41Sopenharmony_ci}
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_citemplate <AccessMode mode, HeapObjectHeader::EncodedHalf part,
3371cb0ef41Sopenharmony_ci          std::memory_order memory_order>
3381cb0ef41Sopenharmony_ciuint16_t HeapObjectHeader::LoadEncoded() const {
3391cb0ef41Sopenharmony_ci  const uint16_t& half =
3401cb0ef41Sopenharmony_ci      part == EncodedHalf::kLow ? encoded_low_ : encoded_high_;
3411cb0ef41Sopenharmony_ci  if (mode == AccessMode::kNonAtomic) return half;
3421cb0ef41Sopenharmony_ci  return v8::base::AsAtomicPtr(&half)->load(memory_order);
3431cb0ef41Sopenharmony_ci}
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_citemplate <AccessMode mode, HeapObjectHeader::EncodedHalf part,
3461cb0ef41Sopenharmony_ci          std::memory_order memory_order>
3471cb0ef41Sopenharmony_civoid HeapObjectHeader::StoreEncoded(uint16_t bits, uint16_t mask) {
3481cb0ef41Sopenharmony_ci  // Caveat: Not all changes to HeapObjectHeader's bitfields go through
3491cb0ef41Sopenharmony_ci  // StoreEncoded. The following have their own implementations and need to be
3501cb0ef41Sopenharmony_ci  // kept in sync:
3511cb0ef41Sopenharmony_ci  // - HeapObjectHeader::TryMarkAtomic
3521cb0ef41Sopenharmony_ci  // - MarkObjectAsFullyConstructed (API)
3531cb0ef41Sopenharmony_ci  DCHECK_EQ(0u, bits & ~mask);
3541cb0ef41Sopenharmony_ci  uint16_t& half = part == EncodedHalf::kLow ? encoded_low_ : encoded_high_;
3551cb0ef41Sopenharmony_ci  if (mode == AccessMode::kNonAtomic) {
3561cb0ef41Sopenharmony_ci    half = (half & ~mask) | bits;
3571cb0ef41Sopenharmony_ci    return;
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci  // We don't perform CAS loop here assuming that only none of the info that
3601cb0ef41Sopenharmony_ci  // shares the same encoded halfs change at the same time.
3611cb0ef41Sopenharmony_ci  auto* atomic_encoded = v8::base::AsAtomicPtr(&half);
3621cb0ef41Sopenharmony_ci  uint16_t value = atomic_encoded->load(std::memory_order_relaxed);
3631cb0ef41Sopenharmony_ci  value = (value & ~mask) | bits;
3641cb0ef41Sopenharmony_ci  atomic_encoded->store(value, memory_order);
3651cb0ef41Sopenharmony_ci}
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci}  // namespace internal
3681cb0ef41Sopenharmony_ci}  // namespace cppgc
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci#endif  // V8_HEAP_CPPGC_HEAP_OBJECT_HEADER_H_
371