forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathv8_platform_page_allocator.cc
134 lines (116 loc) · 4.8 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
// 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"
namespace {
// Maps the v8 page permissions into a page configuration from base.
base::PageAccessibilityConfiguration GetPageConfig(
v8::PageAllocator::Permission permission) {
switch (permission) {
case v8::PageAllocator::Permission::kRead:
return base::PageRead;
case v8::PageAllocator::Permission::kReadWrite:
return base::PageReadWrite;
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 base::PageReadWriteExecute;
case v8::PageAllocator::Permission::kReadExecute:
return base::CPU::GetInstanceNoAllocation().has_bti()
? base::PageReadExecuteProtected
: base::PageReadExecute;
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 base::PageInaccessible;
default:
DCHECK_EQ(v8::PageAllocator::Permission::kNoAccess, permission);
return base::PageInaccessible;
}
}
} // namespace
namespace gin {
PageAllocator::~PageAllocator() = default;
size_t PageAllocator::AllocatePageSize() {
return base::PageAllocationGranularity();
}
size_t PageAllocator::CommitPageSize() {
return base::SystemPageSize();
}
void PageAllocator::SetRandomMmapSeed(int64_t seed) {
base::SetMmapSeedForTesting(seed);
}
void* PageAllocator::GetRandomMmapAddr() {
return base::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 defined(OS_POSIX) || defined(OS_FUCHSIA)
// On POSIX, we can unmap the trailing pages.
base::FreePages(release_base, release_size);
#elif defined(OS_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,
base::PageUpdatePermissions);
#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 PageKeepPermissionsIfPossible 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,
base::PageKeepPermissionsIfPossible);
return true;
} else {
return base::TrySetSystemPagesAccess(address, length,
GetPageConfig(permissions));
}
}
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