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