v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
emulated-virtual-address-subspace.cc
Go to the documentation of this file.
1// Copyright 2021 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 "src/base/bits.h"
9
10namespace v8 {
11namespace base {
12
14 VirtualAddressSpace* parent_space, Address base, size_t mapped_size,
15 size_t total_size)
16 : VirtualAddressSpace(parent_space->page_size(),
17 parent_space->allocation_granularity(), base,
18 total_size, parent_space->max_page_permissions()),
19 mapped_size_(mapped_size),
20 parent_space_(parent_space),
21 region_allocator_(base, mapped_size, parent_space_->page_size()) {
22 // For simplicity, we currently require both the mapped and total size to be
23 // a power of two. This simplifies some things later on, for example, random
24 // addresses can be generated with a simply bitmask, and will then be inside
25 // the unmapped space with a probability >= 50% (mapped size == unmapped
26 // size) or never (mapped size == total size).
29}
30
34
36 MutexGuard guard(&mutex_);
37 rng_.SetSeed(seed);
38}
39
41 MutexGuard guard(&mutex_);
42 Address addr = base() + (static_cast<uint64_t>(rng_.NextInt64()) % size());
43 return RoundDown(addr, allocation_granularity());
44}
45
47 Address hint, size_t size, size_t alignment, PagePermissions permissions) {
48 if (hint == kNoHint || MappedRegionContains(hint, size)) {
49 MutexGuard guard(&mutex_);
50
51 // Attempt to find a region in the mapped region.
52 Address address = region_allocator_.AllocateRegion(hint, size, alignment);
54 // Success. Only need to adjust the page permissions.
55 if (parent_space_->SetPagePermissions(address, size, permissions)) {
56 return address;
57 }
58 // Probably ran out of memory, but still try to allocate in the unmapped
59 // space.
61 }
62 }
63
64 // No luck or hint is outside of the mapped region. Try to allocate pages in
65 // the unmapped space using page allocation hints instead.
67
68 static constexpr int kMaxAttempts = 10;
69 for (int i = 0; i < kMaxAttempts; i++) {
70 // If an unmapped region exists, it must cover at least 50% of the whole
71 // space (unmapped + mapped region). Since we limit the size of allocation
72 // to 50% of the unmapped region (see IsUsableSizeForUnmappedRegion), a
73 // random page address has at least a 25% chance of being a usable base. As
74 // such, this loop should usually terminate quickly.
76 while (!UnmappedRegionContains(hint, size)) {
77 hint = RandomPageAddress();
78 }
79 hint = RoundDown(hint, alignment);
80
81 const Address result =
82 parent_space_->AllocatePages(hint, size, alignment, permissions);
83 if (UnmappedRegionContains(result, size)) {
84 return result;
85 } else if (result) {
87 }
88
89 // Retry at a different address.
90 hint = RandomPageAddress();
91 }
92
93 return kNullAddress;
94}
95
97 if (MappedRegionContains(address, size)) {
98 MutexGuard guard(&mutex_);
100 CHECK(parent_space_->DecommitPages(address, size));
101 } else {
102 DCHECK(UnmappedRegionContains(address, size));
103 parent_space_->FreePages(address, size);
104 }
105}
106
108 Address hint, size_t size, PagePermissions permissions,
109 PlatformSharedMemoryHandle handle, uint64_t offset) {
110 // Can only allocate shared pages in the unmapped region.
112
113 static constexpr int kMaxAttempts = 10;
114 for (int i = 0; i < kMaxAttempts; i++) {
115 // See AllocatePages() for why this loop usually terminates quickly.
117 while (!UnmappedRegionContains(hint, size)) {
118 hint = RandomPageAddress();
119 }
120
121 Address region = parent_space_->AllocateSharedPages(hint, size, permissions,
122 handle, offset);
123 if (UnmappedRegionContains(region, size)) {
124 return region;
125 } else if (region) {
126 parent_space_->FreeSharedPages(region, size);
127 }
128
129 hint = RandomPageAddress();
130 }
131
132 return kNullAddress;
133}
134
136 size_t size) {
137 DCHECK(UnmappedRegionContains(address, size));
138 parent_space_->FreeSharedPages(address, size);
139}
140
142 Address address, size_t size, PagePermissions permissions) {
143 DCHECK(Contains(address, size));
144 return parent_space_->SetPagePermissions(address, size, permissions);
145}
146
148 size_t size) {
149 if (MappedRegionContains(address, size)) {
150 MutexGuard guard(&mutex_);
151 return region_allocator_.AllocateRegionAt(address, size);
152 }
153 if (!UnmappedRegionContains(address, size)) return false;
154 return parent_space_->AllocateGuardRegion(address, size);
155}
156
158 size_t size) {
159 if (MappedRegionContains(address, size)) {
160 MutexGuard guard(&mutex_);
161 CHECK_EQ(size, region_allocator_.FreeRegion(address));
162 } else {
163 DCHECK(UnmappedRegionContains(address, size));
164 parent_space_->FreeGuardRegion(address, size);
165 }
166}
167
169 // This is not supported, mostly because it's not (yet) needed in practice.
170 return false;
171}
172
173std::unique_ptr<v8::VirtualAddressSpace>
175 Address hint, size_t size, size_t alignment,
176 PagePermissions max_page_permissions) {
177 UNREACHABLE();
178}
179
181 Address address, size_t size, PagePermissions permissions) {
182 DCHECK(Contains(address, size));
183 return parent_space_->RecommitPages(address, size, permissions);
184}
185
187 size_t size) {
188 DCHECK(Contains(address, size));
189 return parent_space_->DiscardSystemPages(address, size);
190}
191
193 size_t size) {
194 DCHECK(Contains(address, size));
195 return parent_space_->DecommitPages(address, size);
196}
197
198} // namespace base
199} // namespace v8
virtual V8_WARN_UNUSED_RESULT bool DiscardSystemPages(Address address, size_t size)
virtual void FreePages(Address address, size_t size)=0
virtual V8_WARN_UNUSED_RESULT bool AllocateGuardRegion(Address address, size_t size)=0
virtual V8_WARN_UNUSED_RESULT bool RecommitPages(Address address, size_t size, PagePermissions permissions)=0
virtual V8_WARN_UNUSED_RESULT Address AllocatePages(Address hint, size_t size, size_t alignment, PagePermissions permissions)=0
virtual void FreeSharedPages(Address address, size_t size)=0
virtual void FreeGuardRegion(Address address, size_t size)=0
virtual V8_WARN_UNUSED_RESULT bool SetPagePermissions(Address address, size_t size, PagePermissions permissions)=0
virtual V8_WARN_UNUSED_RESULT Address AllocateSharedPages(Address hint, size_t size, PagePermissions permissions, PlatformSharedMemoryHandle handle, uint64_t offset)=0
virtual V8_WARN_UNUSED_RESULT bool DecommitPages(Address address, size_t size)=0
void FreeSharedPages(Address address, size_t size) override
bool AllocateGuardRegion(Address address, size_t size) override
bool DiscardSystemPages(Address address, size_t size) override
bool RecommitPages(Address address, size_t size, PagePermissions permissions) override
bool SetPagePermissions(Address address, size_t size, PagePermissions permissions) override
Address AllocatePages(Address hint, size_t size, size_t alignment, PagePermissions permissions) override
bool Contains(Address outer_start, size_t outer_size, Address inner_start, size_t inner_size) const
Address AllocateSharedPages(Address hint, size_t size, PagePermissions permissions, PlatformSharedMemoryHandle handle, uint64_t offset) override
std::unique_ptr< v8::VirtualAddressSpace > AllocateSubspace(Address hint, size_t size, size_t alignment, PagePermissions max_page_permissions) override
void FreeGuardRegion(Address address, size_t size) override
bool DecommitPages(Address address, size_t size) override
bool UnmappedRegionContains(Address addr, size_t length) const
void FreePages(Address address, size_t size) override
EmulatedVirtualAddressSubspace(v8::VirtualAddressSpace *parent_space, Address base, size_t mapped_size, size_t total_size)
bool MappedRegionContains(Address addr, size_t length) const
int64_t NextInt64() V8_WARN_UNUSED_RESULT
Address AllocateRegion(size_t size)
bool AllocateRegionAt(Address requested_address, size_t size, RegionState region_state=RegionState::kAllocated)
size_t FreeRegion(Address address)
static constexpr Address kAllocationFailure
int32_t offset
ZoneVector< RpoNumber > & result
constexpr bool IsPowerOfTwo(T value)
Definition bits.h:187
uintptr_t Address
Definition memory.h:13
constexpr Address kNullAddress
intptr_t PlatformSharedMemoryHandle
PagePermissions
#define UNREACHABLE()
Definition logging.h:67
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
constexpr T RoundDown(T x, intptr_t m)
Definition macros.h:371