v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
caged-heap.cc
Go to the documentation of this file.
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
6
7#include <map>
8
10#include "v8config.h" // NOLINT(build/include_directory)
11
12#if !defined(CPPGC_CAGED_HEAP)
13#error "Must be compiled with caged heap enabled"
14#endif
15
22#include "src/base/logging.h"
29
30namespace cppgc {
31namespace internal {
32
33uintptr_t CagedHeapBase::g_heap_base_ = 0u;
34size_t CagedHeapBase::g_age_table_size_ = 0u;
35
36CagedHeap* CagedHeap::instance_ = nullptr;
37
38namespace {
39
40VirtualMemory ReserveCagedHeap(PageAllocator& platform_allocator) {
41 DCHECK_EQ(0u, api_constants::kCagedHeapMaxReservationSize %
42 platform_allocator.AllocatePageSize());
43
44 static constexpr size_t kAllocationTries = 4;
45 for (size_t i = 0; i < kAllocationTries; ++i) {
46#if defined(CPPGC_POINTER_COMPRESSION)
47 // We want compressed pointers to have the most significant bit set to 1.
48 // That way, on decompression the bit will be sign-extended. This saves us a
49 // branch and 'or' operation during compression.
50 //
51 // We achieve this by over-reserving the cage and selecting a sub-region
52 // from the upper half of the reservation that has the bit pattern we need.
53 // Examples:
54 // - For a 4GB cage with 1 bit of pointer compression shift, reserve 8GB and
55 // use the upper 4GB.
56 // - For an 8GB cage with 3 bits of pointer compression shift, reserve 32GB
57 // and use the first 8GB of the upper 16 GB.
58 //
59 // TODO(chromium:1325007): Provide API in PageAllocator to left trim
60 // allocations and return unused portions of the reservation back to the OS.
61 static constexpr size_t kTryReserveSize =
62 2 * api_constants::kCagedHeapMaxReservationSize;
63 static constexpr size_t kTryReserveAlignment =
64 2 * api_constants::kCagedHeapReservationAlignment;
65#else // !defined(CPPGC_POINTER_COMPRESSION)
66 static constexpr size_t kTryReserveSize =
67 api_constants::kCagedHeapMaxReservationSize;
68 static constexpr size_t kTryReserveAlignment =
69 api_constants::kCagedHeapReservationAlignment;
70#endif // !defined(CPPGC_POINTER_COMPRESSION)
71 void* hint = reinterpret_cast<void*>(RoundDown(
72 reinterpret_cast<uintptr_t>(platform_allocator.GetRandomMmapAddr()),
73 kTryReserveAlignment));
74
75 VirtualMemory memory(&platform_allocator, kTryReserveSize,
76 kTryReserveAlignment, hint);
77 if (memory.IsReserved()) return memory;
78 }
79
80 GetGlobalOOMHandler()("Oilpan: CagedHeap reservation.");
81}
82
83} // namespace
84
85// static
87 size_t desired_heap_size) {
88 static v8::base::LeakyObject<CagedHeap> caged_heap(platform_allocator,
89 desired_heap_size);
90}
91
92// static
97
99 size_t desired_heap_size)
100 : reserved_area_(ReserveCagedHeap(platform_allocator)) {
101 using CagedAddress = CagedHeap::AllocatorType::Address;
102
103#if defined(CPPGC_POINTER_COMPRESSION)
104 // Pick a base offset according to pointer compression shift. See comment in
105 // ReserveCagedHeap().
106 static constexpr size_t kBaseOffset =
107 api_constants::kCagedHeapMaxReservationSize;
108#else // !defined(CPPGC_POINTER_COMPRESSION)
109 static constexpr size_t kBaseOffset = 0;
110#endif
111
112 void* const cage_start =
113 static_cast<uint8_t*>(reserved_area_.address()) + kBaseOffset;
114
115 CagedHeapBase::g_heap_base_ = reinterpret_cast<uintptr_t>(cage_start);
116
117#if defined(CPPGC_POINTER_COMPRESSION)
118 // With pointer compression only single heap per thread is allowed.
119 CHECK(!CageBaseGlobal::IsSet());
120 CageBaseGlobalUpdater::UpdateCageBase(CagedHeapBase::g_heap_base_);
121#endif // defined(CPPGC_POINTER_COMPRESSION)
122
123 const size_t total_heap_size = std::clamp<size_t>(
124 v8::base::bits::RoundUpToPowerOfTwo64(desired_heap_size),
125 api_constants::kCagedHeapDefaultReservationSize,
126 api_constants::kCagedHeapMaxReservationSize);
127
128 const size_t local_data_size =
129 CagedHeapLocalData::CalculateLocalDataSizeForHeapSize(total_heap_size);
130 const CagedAddress caged_heap_start = RoundUp(
131 reinterpret_cast<CagedAddress>(cage_start) + local_data_size, kPageSize);
132 const size_t local_data_size_with_padding =
133 caged_heap_start - reinterpret_cast<CagedAddress>(cage_start);
134
135 page_bounded_allocator_ = std::make_unique<v8::base::BoundedPageAllocator>(
136 &platform_allocator, caged_heap_start,
137 total_heap_size - local_data_size_with_padding, kPageSize,
140
141 instance_ = this;
142 CagedHeapBase::g_age_table_size_ = AgeTable::CalculateAgeTableSizeForHeapSize(
143 api_constants::kCagedHeapDefaultReservationSize);
144}
145
146void CagedHeap::CommitAgeTable(PageAllocator& platform_allocator) {
147 if (!platform_allocator.SetPermissions(
148 reinterpret_cast<void*>(CagedHeapBase::g_heap_base_),
149 RoundUp(CagedHeapBase::g_age_table_size_,
150 platform_allocator.CommitPageSize()),
152 GetGlobalOOMHandler()("Oilpan: CagedHeap commit CageHeapLocalData.");
153 }
154}
155
156} // namespace internal
157} // namespace cppgc
std::unique_ptr< AllocatorType > page_bounded_allocator_
Definition caged-heap.h:79
CagedHeap(const CagedHeap &)=delete
static void InitializeIfNeeded(PageAllocator &platform_allocator, size_t desired_heap_size)
Definition caged-heap.cc:86
static void CommitAgeTable(PageAllocator &platform_allocator)
static CagedHeap * instance_
Definition caged-heap.h:74
const VirtualMemory reserved_area_
Definition caged-heap.h:76
static CagedHeap & Instance()
Definition caged-heap.cc:93
virtual bool SetPermissions(void *address, size_t length, Permission permissions)=0
virtual size_t CommitPageSize()=0
constexpr size_t kPageSize
Definition globals.h:42
FatalOutOfMemoryHandler & GetGlobalOOMHandler()
Definition platform.cc:73
v8::PageAllocator PageAllocator
Definition platform.h:22
V8_BASE_EXPORT constexpr uint64_t RoundUpToPowerOfTwo64(uint64_t value)
Definition bits.h:235
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
constexpr T RoundUp(T x, intptr_t m)
Definition macros.h:387
constexpr T RoundDown(T x, intptr_t m)
Definition macros.h:371