forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathv8_platform_page_allocator.cc
154 lines (135 loc) · 5.82 KB
/
v8_platform_page_allocator.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "v8_platform_page_allocator.h"
#include "base/allocator/partition_allocator/address_space_randomization.h"
#include "base/allocator/partition_allocator/page_allocator_constants.h"
#include "base/allocator/partition_allocator/random.h"
#include "base/check_op.h"
#include "base/cpu.h"
#include "base/memory/page_size.h"
#include "build/build_config.h"
namespace {
// Maps the v8 page permissions into a page configuration from base.
::partition_alloc::PageAccessibilityConfiguration GetPageConfig(
v8::PageAllocator::Permission permission) {
switch (permission) {
case v8::PageAllocator::Permission::kRead:
return ::partition_alloc::PageAccessibilityConfiguration::kRead;
case v8::PageAllocator::Permission::kReadWrite:
return ::partition_alloc::PageAccessibilityConfiguration::kReadWrite;
case v8::PageAllocator::Permission::kReadWriteExecute:
// at the moment bti-protection is not enabled for this path since some
// projects may still be using non-bti compliant code.
return ::partition_alloc::PageAccessibilityConfiguration::
kReadWriteExecute;
case v8::PageAllocator::Permission::kReadExecute:
#if defined(__ARM_FEATURE_BTI_DEFAULT)
return base::CPU::GetInstanceNoAllocation().has_bti()
? ::partition_alloc::PageAccessibilityConfiguration::
kReadExecuteProtected
: ::partition_alloc::PageAccessibilityConfiguration::
kReadExecute;
#else
return ::partition_alloc::PageAccessibilityConfiguration::kReadExecute;
#endif
case v8::PageAllocator::Permission::kNoAccessWillJitLater:
// We could use this information to conditionally set the MAP_JIT flag
// on Mac-arm64; however this permissions value is intended to be a
// short-term solution, so we continue to set MAP_JIT for all V8 pages
// for now.
return ::partition_alloc::PageAccessibilityConfiguration::kInaccessible;
default:
DCHECK_EQ(v8::PageAllocator::Permission::kNoAccess, permission);
return ::partition_alloc::PageAccessibilityConfiguration::kInaccessible;
}
}
} // namespace
namespace gin {
PageAllocator::~PageAllocator() = default;
size_t PageAllocator::AllocatePageSize() {
return partition_alloc::internal::PageAllocationGranularity();
}
size_t PageAllocator::CommitPageSize() {
return base::GetPageSize();
}
void PageAllocator::SetRandomMmapSeed(int64_t seed) {
::partition_alloc::SetMmapSeedForTesting(seed);
}
void* PageAllocator::GetRandomMmapAddr() {
return reinterpret_cast<void*>(::partition_alloc::GetRandomPageBase());
}
void* PageAllocator::AllocatePages(void* address,
size_t length,
size_t alignment,
v8::PageAllocator::Permission permissions) {
base::PageAccessibilityConfiguration config = GetPageConfig(permissions);
return base::AllocPages(address, length, alignment, config,
base::PageTag::kV8);
}
bool PageAllocator::FreePages(void* address, size_t length) {
base::FreePages(address, length);
return true;
}
bool PageAllocator::ReleasePages(void* address,
size_t length,
size_t new_length) {
DCHECK_LT(new_length, length);
uint8_t* release_base = reinterpret_cast<uint8_t*>(address) + new_length;
size_t release_size = length - new_length;
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
// On POSIX, we can unmap the trailing pages.
base::FreePages(release_base, release_size);
#elif BUILDFLAG(IS_WIN)
// On Windows, we can only de-commit the trailing pages. FreePages() will
// still free all pages in the region including the released tail, so it's
// safe to just decommit the tail.
base::DecommitSystemPages(
release_base, release_size,
::partition_alloc::PageAccessibilityDisposition::kRequireUpdate);
#else
#error Unsupported platform
#endif
return true;
}
bool PageAllocator::SetPermissions(void* address,
size_t length,
Permission permissions) {
// If V8 sets permissions to none, we can discard the memory.
if (permissions == v8::PageAllocator::Permission::kNoAccess) {
// Use PageAccessibilityDisposition::kAllowKeepForPerf as an
// optimization, to avoid perf regression (see crrev.com/c/2563038 for
// details). This may cause the memory region to still be accessible on
// certain platforms, but at least the physical pages will be discarded.
base::DecommitSystemPages(
address, length,
::partition_alloc::PageAccessibilityDisposition::kAllowKeepForPerf);
return true;
} else {
return base::TrySetSystemPagesAccess(address, length,
GetPageConfig(permissions));
}
}
bool PageAllocator::RecommitPages(void* address,
size_t length,
Permission permissions) {
base::RecommitSystemPages(
reinterpret_cast<uintptr_t>(address), length, GetPageConfig(permissions),
base::PageAccessibilityDisposition::kAllowKeepForPerf);
return true;
}
bool PageAllocator::DiscardSystemPages(void* address, size_t size) {
base::DiscardSystemPages(address, size);
return true;
}
bool PageAllocator::DecommitPages(void* address, size_t size) {
// V8 expects the pages to be inaccessible and zero-initialized upon next
// access.
base::DecommitAndZeroSystemPages(address, size);
return true;
}
base::PageAccessibilityConfiguration PageAllocator::GetPageConfigForTesting(
v8::PageAllocator::Permission permission) {
return GetPageConfig(permission);
}
} // namespace gin