1// Copyright 2020 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 6#define INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 7 8#include <array> 9#include <cstddef> 10#include <cstdint> 11 12#include "cppgc/internal/api-constants.h" 13#include "cppgc/internal/caged-heap.h" 14#include "cppgc/internal/logging.h" 15#include "cppgc/platform.h" 16#include "v8config.h" // NOLINT(build/include_directory) 17 18#if __cpp_lib_bitopts 19#include <bit> 20#endif // __cpp_lib_bitopts 21 22#if defined(CPPGC_CAGED_HEAP) 23 24namespace cppgc { 25namespace internal { 26 27class HeapBase; 28class HeapBaseHandle; 29 30#if defined(CPPGC_YOUNG_GENERATION) 31 32// AgeTable is the bytemap needed for the fast generation check in the write 33// barrier. AgeTable contains entries that correspond to 4096 bytes memory 34// regions (cards). Each entry in the table represents generation of the objects 35// that reside on the corresponding card (young, old or mixed). 36class V8_EXPORT AgeTable final { 37 static constexpr size_t kRequiredSize = 1 * api_constants::kMB; 38 static constexpr size_t kAllocationGranularity = 39 api_constants::kAllocationGranularity; 40 41 public: 42 // Represents age of the objects living on a single card. 43 enum class Age : uint8_t { kOld, kYoung, kMixed }; 44 // When setting age for a range, consider or ignore ages of the adjacent 45 // cards. 46 enum class AdjacentCardsPolicy : uint8_t { kConsider, kIgnore }; 47 48 static constexpr size_t kCardSizeInBytes = 49 api_constants::kCagedHeapReservationSize / kRequiredSize; 50 51 void SetAge(uintptr_t cage_offset, Age age) { 52 table_[card(cage_offset)] = age; 53 } 54 55 V8_INLINE Age GetAge(uintptr_t cage_offset) const { 56 return table_[card(cage_offset)]; 57 } 58 59 void SetAgeForRange(uintptr_t cage_offset_begin, uintptr_t cage_offset_end, 60 Age age, AdjacentCardsPolicy adjacent_cards_policy); 61 62 Age GetAgeForRange(uintptr_t cage_offset_begin, 63 uintptr_t cage_offset_end) const; 64 65 void ResetForTesting(); 66 67 private: 68 V8_INLINE size_t card(uintptr_t offset) const { 69 constexpr size_t kGranularityBits = 70#if __cpp_lib_bitopts 71 std::countr_zero(static_cast<uint32_t>(kCardSizeInBytes)); 72#elif V8_HAS_BUILTIN_CTZ 73 __builtin_ctz(static_cast<uint32_t>(kCardSizeInBytes)); 74#else //! V8_HAS_BUILTIN_CTZ 75 // Hardcode and check with assert. 76#if defined(CPPGC_2GB_CAGE) 77 11; 78#else // !defined(CPPGC_2GB_CAGE) 79 12; 80#endif // !defined(CPPGC_2GB_CAGE) 81#endif // !V8_HAS_BUILTIN_CTZ 82 static_assert((1 << kGranularityBits) == kCardSizeInBytes); 83 const size_t entry = offset >> kGranularityBits; 84 CPPGC_DCHECK(table_.size() > entry); 85 return entry; 86 } 87 88 std::array<Age, kRequiredSize> table_; 89}; 90 91static_assert(sizeof(AgeTable) == 1 * api_constants::kMB, 92 "Size of AgeTable is 1MB"); 93 94#endif // CPPGC_YOUNG_GENERATION 95 96struct CagedHeapLocalData final { 97 V8_INLINE static CagedHeapLocalData& Get() { 98 return *reinterpret_cast<CagedHeapLocalData*>(CagedHeapBase::GetBase()); 99 } 100 101#if defined(CPPGC_YOUNG_GENERATION) 102 AgeTable age_table; 103#endif 104}; 105 106} // namespace internal 107} // namespace cppgc 108 109#endif // defined(CPPGC_CAGED_HEAP) 110 111#endif // INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 112