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 INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <array> 91cb0ef41Sopenharmony_ci#include <cstddef> 101cb0ef41Sopenharmony_ci#include <cstdint> 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "cppgc/internal/api-constants.h" 131cb0ef41Sopenharmony_ci#include "cppgc/internal/caged-heap.h" 141cb0ef41Sopenharmony_ci#include "cppgc/internal/logging.h" 151cb0ef41Sopenharmony_ci#include "cppgc/platform.h" 161cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#if __cpp_lib_bitopts 191cb0ef41Sopenharmony_ci#include <bit> 201cb0ef41Sopenharmony_ci#endif // __cpp_lib_bitopts 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_cinamespace cppgc { 251cb0ef41Sopenharmony_cinamespace internal { 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciclass HeapBase; 281cb0ef41Sopenharmony_ciclass HeapBaseHandle; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// AgeTable is the bytemap needed for the fast generation check in the write 331cb0ef41Sopenharmony_ci// barrier. AgeTable contains entries that correspond to 4096 bytes memory 341cb0ef41Sopenharmony_ci// regions (cards). Each entry in the table represents generation of the objects 351cb0ef41Sopenharmony_ci// that reside on the corresponding card (young, old or mixed). 361cb0ef41Sopenharmony_ciclass V8_EXPORT AgeTable final { 371cb0ef41Sopenharmony_ci static constexpr size_t kRequiredSize = 1 * api_constants::kMB; 381cb0ef41Sopenharmony_ci static constexpr size_t kAllocationGranularity = 391cb0ef41Sopenharmony_ci api_constants::kAllocationGranularity; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci public: 421cb0ef41Sopenharmony_ci // Represents age of the objects living on a single card. 431cb0ef41Sopenharmony_ci enum class Age : uint8_t { kOld, kYoung, kMixed }; 441cb0ef41Sopenharmony_ci // When setting age for a range, consider or ignore ages of the adjacent 451cb0ef41Sopenharmony_ci // cards. 461cb0ef41Sopenharmony_ci enum class AdjacentCardsPolicy : uint8_t { kConsider, kIgnore }; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci static constexpr size_t kCardSizeInBytes = 491cb0ef41Sopenharmony_ci api_constants::kCagedHeapReservationSize / kRequiredSize; 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci void SetAge(uintptr_t cage_offset, Age age) { 521cb0ef41Sopenharmony_ci table_[card(cage_offset)] = age; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci V8_INLINE Age GetAge(uintptr_t cage_offset) const { 561cb0ef41Sopenharmony_ci return table_[card(cage_offset)]; 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci void SetAgeForRange(uintptr_t cage_offset_begin, uintptr_t cage_offset_end, 601cb0ef41Sopenharmony_ci Age age, AdjacentCardsPolicy adjacent_cards_policy); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci Age GetAgeForRange(uintptr_t cage_offset_begin, 631cb0ef41Sopenharmony_ci uintptr_t cage_offset_end) const; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci void ResetForTesting(); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci private: 681cb0ef41Sopenharmony_ci V8_INLINE size_t card(uintptr_t offset) const { 691cb0ef41Sopenharmony_ci constexpr size_t kGranularityBits = 701cb0ef41Sopenharmony_ci#if __cpp_lib_bitopts 711cb0ef41Sopenharmony_ci std::countr_zero(static_cast<uint32_t>(kCardSizeInBytes)); 721cb0ef41Sopenharmony_ci#elif V8_HAS_BUILTIN_CTZ 731cb0ef41Sopenharmony_ci __builtin_ctz(static_cast<uint32_t>(kCardSizeInBytes)); 741cb0ef41Sopenharmony_ci#else //! V8_HAS_BUILTIN_CTZ 751cb0ef41Sopenharmony_ci // Hardcode and check with assert. 761cb0ef41Sopenharmony_ci#if defined(CPPGC_2GB_CAGE) 771cb0ef41Sopenharmony_ci 11; 781cb0ef41Sopenharmony_ci#else // !defined(CPPGC_2GB_CAGE) 791cb0ef41Sopenharmony_ci 12; 801cb0ef41Sopenharmony_ci#endif // !defined(CPPGC_2GB_CAGE) 811cb0ef41Sopenharmony_ci#endif // !V8_HAS_BUILTIN_CTZ 821cb0ef41Sopenharmony_ci static_assert((1 << kGranularityBits) == kCardSizeInBytes); 831cb0ef41Sopenharmony_ci const size_t entry = offset >> kGranularityBits; 841cb0ef41Sopenharmony_ci CPPGC_DCHECK(table_.size() > entry); 851cb0ef41Sopenharmony_ci return entry; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci std::array<Age, kRequiredSize> table_; 891cb0ef41Sopenharmony_ci}; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_cistatic_assert(sizeof(AgeTable) == 1 * api_constants::kMB, 921cb0ef41Sopenharmony_ci "Size of AgeTable is 1MB"); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci#endif // CPPGC_YOUNG_GENERATION 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_cistruct CagedHeapLocalData final { 971cb0ef41Sopenharmony_ci V8_INLINE static CagedHeapLocalData& Get() { 981cb0ef41Sopenharmony_ci return *reinterpret_cast<CagedHeapLocalData*>(CagedHeapBase::GetBase()); 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 1021cb0ef41Sopenharmony_ci AgeTable age_table; 1031cb0ef41Sopenharmony_ci#endif 1041cb0ef41Sopenharmony_ci}; 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci} // namespace internal 1071cb0ef41Sopenharmony_ci} // namespace cppgc 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci#endif // defined(CPPGC_CAGED_HEAP) 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci#endif // INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_ 112