Skip to content

Commit 958686c

Browse files
Bertrand PreslesBertrand Presles
Bertrand Presles
authored and
Bertrand Presles
committed
Backported PR nodejs#35986
1 parent f5c706e commit 958686c

14 files changed

+137
-10
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
# Reset this number to 0 on major V8 upgrades.
3636
# Increment by one for each non-official patch applied to deps/v8.
37-
'v8_embedder_string': '-node.45',
37+
'v8_embedder_string': '-node.49 ',
3838

3939
##### V8 defaults for Node.js #####
4040

deps/v8/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,7 @@ v8_source_set("v8_base_without_compiler") {
29072907
"src/wasm/baseline/liftoff-compiler.cc",
29082908
"src/wasm/baseline/liftoff-compiler.h",
29092909
"src/wasm/baseline/liftoff-register.h",
2910+
"src/wasm/code-space-access.h",
29102911
"src/wasm/compilation-environment.h",
29112912
"src/wasm/decoder.h",
29122913
"src/wasm/function-body-decoder-impl.h",

deps/v8/include/v8-platform.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,13 @@ class PageAllocator {
240240
kReadWrite,
241241
// TODO(hpayer): Remove this flag. Memory should never be rwx.
242242
kReadWriteExecute,
243-
kReadExecute
243+
kReadExecute,
244+
// Set this when reserving memory that will later require kReadWriteExecute
245+
// permissions. The resulting behavior is platform-specific, currently
246+
// this is used to set the MAP_JIT flag on Apple Silicon.
247+
// TODO(jkummerow): Remove this when Wasm has a platform-independent
248+
// w^x implementation.
249+
kNoAccessWillJitLater
244250
};
245251

246252
/**

deps/v8/src/base/page-allocator.cc

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
#include "src/base/platform/platform.h"
88

9+
#if V8_OS_MACOSX
10+
#include <sys/mman.h> // For MAP_JIT.
11+
#endif
12+
913
namespace v8 {
1014
namespace base {
1115

@@ -21,6 +25,8 @@ STATIC_ASSERT_ENUM(PageAllocator::kReadWriteExecute,
2125
base::OS::MemoryPermission::kReadWriteExecute);
2226
STATIC_ASSERT_ENUM(PageAllocator::kReadExecute,
2327
base::OS::MemoryPermission::kReadExecute);
28+
STATIC_ASSERT_ENUM(PageAllocator::kNoAccessWillJitLater,
29+
base::OS::MemoryPermission::kNoAccessWillJitLater);
2430

2531
#undef STATIC_ASSERT_ENUM
2632

@@ -38,6 +44,14 @@ void* PageAllocator::GetRandomMmapAddr() {
3844

3945
void* PageAllocator::AllocatePages(void* hint, size_t size, size_t alignment,
4046
PageAllocator::Permission access) {
47+
#if !(V8_OS_MACOSX && V8_HOST_ARCH_ARM64 && defined(MAP_JIT))
48+
// kNoAccessWillJitLater is only used on Apple Silicon. Map it to regular
49+
// kNoAccess on other platforms, so code doesn't have to handle both enum
50+
// values.
51+
if (access == PageAllocator::kNoAccessWillJitLater) {
52+
access = PageAllocator::kNoAccess;
53+
}
54+
#endif
4155
return base::OS::Allocate(hint, size, alignment,
4256
static_cast<base::OS::MemoryPermission>(access));
4357
}

deps/v8/src/base/platform/platform-cygwin.cc

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace {
3333
DWORD GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
3434
switch (access) {
3535
case OS::MemoryPermission::kNoAccess:
36+
case OS::MemoryPermission::kNoAccessWillJitLater:
3637
return PAGE_NOACCESS;
3738
case OS::MemoryPermission::kRead:
3839
return PAGE_READONLY;

deps/v8/src/base/platform/platform-fuchsia.cc

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace {
1818
uint32_t GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
1919
switch (access) {
2020
case OS::MemoryPermission::kNoAccess:
21+
case OS::MemoryPermission::kNoAccessWillJitLater:
2122
return 0; // no permissions
2223
case OS::MemoryPermission::kRead:
2324
return ZX_VM_PERM_READ;

deps/v8/src/base/platform/platform-posix.cc

+6
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ const int kMmapFdOffset = 0;
111111
int GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
112112
switch (access) {
113113
case OS::MemoryPermission::kNoAccess:
114+
case OS::MemoryPermission::kNoAccessWillJitLater:
114115
return PROT_NONE;
115116
case OS::MemoryPermission::kRead:
116117
return PROT_READ;
@@ -134,6 +135,11 @@ int GetFlagsForMemoryPermission(OS::MemoryPermission access) {
134135
flags |= MAP_LAZY;
135136
#endif // V8_OS_QNX
136137
}
138+
#if V8_OS_MACOSX && V8_HOST_ARCH_ARM64 && defined(MAP_JIT)
139+
if (access == OS::MemoryPermission::kNoAccessWillJitLater) {
140+
flags |= MAP_JIT;
141+
}
142+
#endif
137143
return flags;
138144
}
139145

deps/v8/src/base/platform/platform-win32.cc

+1
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ namespace {
753753
DWORD GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
754754
switch (access) {
755755
case OS::MemoryPermission::kNoAccess:
756+
case OS::MemoryPermission::kNoAccessWillJitLater:
756757
return PAGE_NOACCESS;
757758
case OS::MemoryPermission::kRead:
758759
return PAGE_READONLY;

deps/v8/src/base/platform/platform.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ class V8_BASE_EXPORT OS {
163163
kReadWrite,
164164
// TODO(hpayer): Remove this flag. Memory should never be rwx.
165165
kReadWriteExecute,
166-
kReadExecute
166+
kReadExecute,
167+
// TODO(jkummerow): Remove this when Wasm has a platform-independent
168+
// w^x implementation.
169+
kNoAccessWillJitLater
167170
};
168171

169172
static bool HasLazyCommits();

deps/v8/src/utils/allocation.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,17 @@ bool OnCriticalMemoryPressure(size_t length) {
207207
}
208208

209209
VirtualMemory::VirtualMemory(v8::PageAllocator* page_allocator, size_t size,
210-
void* hint, size_t alignment)
210+
void* hint, size_t alignment, JitPermission jit)
211211
: page_allocator_(page_allocator) {
212212
DCHECK_NOT_NULL(page_allocator);
213213
DCHECK(IsAligned(size, page_allocator_->CommitPageSize()));
214214
size_t page_size = page_allocator_->AllocatePageSize();
215215
alignment = RoundUp(alignment, page_size);
216-
Address address = reinterpret_cast<Address>(
217-
AllocatePages(page_allocator_, hint, RoundUp(size, page_size), alignment,
218-
PageAllocator::kNoAccess));
216+
PageAllocator::Permission permissions =
217+
jit == kMapAsJittable ? PageAllocator::kNoAccessWillJitLater
218+
: PageAllocator::kNoAccess;
219+
Address address = reinterpret_cast<Address>(AllocatePages(
220+
page_allocator_, hint, RoundUp(size, page_size), alignment, permissions));
219221
if (address != kNullAddress) {
220222
DCHECK(IsAligned(address, alignment));
221223
region_ = base::AddressRegion(address, size);

deps/v8/src/utils/allocation.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,18 @@ V8_EXPORT_PRIVATE bool OnCriticalMemoryPressure(size_t length);
150150
// Represents and controls an area of reserved memory.
151151
class V8_EXPORT_PRIVATE VirtualMemory final {
152152
public:
153+
enum JitPermission { kNoJit, kMapAsJittable };
154+
153155
// Empty VirtualMemory object, controlling no reserved memory.
154156
VirtualMemory() = default;
155157

156158
// Reserves virtual memory containing an area of the given size that is
157159
// aligned per |alignment| rounded up to the |page_allocator|'s allocate page
158160
// size. The |size| must be aligned with |page_allocator|'s commit page size.
159161
// This may not be at the position returned by address().
160-
VirtualMemory(v8::PageAllocator* page_allocator, size_t size, void* hint,
161-
size_t alignment = 1);
162+
VirtualMemory(v8::PageAllocator* page_allocator,
163+
size_t size, void* hint, size_t alignment = 1,
164+
JitPermission jit = kNoJit);
162165

163166
// Construct a virtual memory by assigning it some already mapped address
164167
// and size.

deps/v8/src/wasm/code-space-access.h

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
5+
#ifndef V8_WASM_CODE_SPACE_ACCESS_H_
6+
#define V8_WASM_CODE_SPACE_ACCESS_H_
7+
8+
#include "src/base/build_config.h"
9+
#include "src/base/macros.h"
10+
#include "src/common/globals.h"
11+
12+
namespace v8 {
13+
namespace internal {
14+
15+
#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64)
16+
17+
// Ignoring this warning is considered better than relying on
18+
// __builtin_available.
19+
#pragma clang diagnostic push
20+
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
21+
inline void SwitchMemoryPermissionsToWritable() {
22+
pthread_jit_write_protect_np(0);
23+
}
24+
inline void SwitchMemoryPermissionsToExecutable() {
25+
pthread_jit_write_protect_np(1);
26+
}
27+
#pragma clang diagnostic pop
28+
29+
namespace wasm {
30+
31+
class CodeSpaceWriteScope {
32+
public:
33+
// TODO(jkummerow): Background threads could permanently stay in
34+
// writable mode; only the main thread has to switch back and forth.
35+
CodeSpaceWriteScope() {
36+
if (code_space_write_nesting_level_ == 0) {
37+
SwitchMemoryPermissionsToWritable();
38+
}
39+
code_space_write_nesting_level_++;
40+
}
41+
~CodeSpaceWriteScope() {
42+
code_space_write_nesting_level_--;
43+
if (code_space_write_nesting_level_ == 0) {
44+
SwitchMemoryPermissionsToExecutable();
45+
}
46+
}
47+
48+
private:
49+
static thread_local int code_space_write_nesting_level_;
50+
};
51+
52+
#define CODE_SPACE_WRITE_SCOPE CodeSpaceWriteScope _write_access_;
53+
54+
} // namespace wasm
55+
56+
#else // Not Mac-on-arm64.
57+
58+
// Nothing to do, we map code memory with rwx permissions.
59+
inline void SwitchMemoryPermissionsToWritable() {}
60+
inline void SwitchMemoryPermissionsToExecutable() {}
61+
62+
#define CODE_SPACE_WRITE_SCOPE
63+
64+
#endif // V8_OS_MACOSX && V8_HOST_ARCH_ARM64
65+
66+
} // namespace internal
67+
} // namespace v8
68+
69+
#endif // V8_WASM_CODE_SPACE_ACCESS_H_

deps/v8/src/wasm/wasm-code-manager.cc

+19-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <iomanip>
88

9+
#include "src/base/build_config.h"
910
#include "src/base/adapters.h"
1011
#include "src/base/macros.h"
1112
#include "src/base/platform/platform.h"
@@ -21,6 +22,7 @@
2122
#include "src/snapshot/embedded/embedded-data.h"
2223
#include "src/utils/ostreams.h"
2324
#include "src/utils/vector.h"
25+
#include "src/wasm/code-space-access.h"
2426
#include "src/wasm/compilation-environment.h"
2527
#include "src/wasm/function-compiler.h"
2628
#include "src/wasm/jump-table-assembler.h"
@@ -45,6 +47,10 @@ namespace wasm {
4547

4648
using trap_handler::ProtectedInstructionData;
4749

50+
#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64)
51+
thread_local int CodeSpaceWriteScope::code_space_write_nesting_level_ = 0;
52+
#endif
53+
4854
base::AddressRegion DisjointAllocationPool::Merge(base::AddressRegion region) {
4955
auto dest_it = regions_.begin();
5056
auto dest_end = regions_.end();
@@ -626,6 +632,7 @@ void WasmCodeAllocator::FreeCode(Vector<WasmCode* const> codes) {
626632
// Zap code area and collect freed code regions.
627633
DisjointAllocationPool freed_regions;
628634
size_t code_size = 0;
635+
CODE_SPACE_WRITE_SCOPE
629636
for (WasmCode* code : codes) {
630637
ZapCode(code->instruction_start(), code->instructions().size());
631638
FlushInstructionCache(code->instruction_start(),
@@ -731,6 +738,7 @@ CompilationEnv NativeModule::CreateCompilationEnv() const {
731738
}
732739

733740
WasmCode* NativeModule::AddCodeForTesting(Handle<Code> code) {
741+
CODE_SPACE_WRITE_SCOPE
734742
return AddAndPublishAnonymousCode(code, WasmCode::kFunction);
735743
}
736744

@@ -742,6 +750,7 @@ void NativeModule::UseLazyStub(uint32_t func_index) {
742750
if (!lazy_compile_table_) {
743751
uint32_t num_slots = module_->num_declared_functions;
744752
WasmCodeRefScope code_ref_scope;
753+
CODE_SPACE_WRITE_SCOPE
745754
DCHECK_EQ(1, code_space_data_.size());
746755
lazy_compile_table_ = CreateEmptyJumpTableInRegion(
747756
JumpTableAssembler::SizeForNumberOfLazyFunctions(num_slots),
@@ -924,6 +933,7 @@ std::unique_ptr<WasmCode> NativeModule::AddCodeWithCodeSpace(
924933
OwnedVector<byte> reloc_info;
925934
if (desc.reloc_size > 0) {
926935
reloc_info = OwnedVector<byte>::New(desc.reloc_size);
936+
CODE_SPACE_WRITE_SCOPE
927937
memcpy(reloc_info.start(), desc.buffer + desc.buffer_size - desc.reloc_size,
928938
desc.reloc_size);
929939
}
@@ -1070,6 +1080,7 @@ WasmCode* NativeModule::AddDeserializedCode(
10701080
OwnedVector<const byte> reloc_info,
10711081
OwnedVector<const byte> source_position_table, WasmCode::Kind kind,
10721082
ExecutionTier tier) {
1083+
// CodeSpaceWriteScope is provided by the caller.
10731084
Vector<uint8_t> dst_code_bytes =
10741085
code_allocator_.AllocateForCode(this, instructions.size());
10751086
memcpy(dst_code_bytes.begin(), instructions.begin(), instructions.size());
@@ -1126,6 +1137,7 @@ WasmCode* NativeModule::CreateEmptyJumpTableInRegion(
11261137
Vector<uint8_t> code_space =
11271138
code_allocator_.AllocateForCodeInRegion(this, jump_table_size, region);
11281139
DCHECK(!code_space.empty());
1140+
CODE_SPACE_WRITE_SCOPE
11291141
ZapCode(reinterpret_cast<Address>(code_space.begin()), code_space.size());
11301142
std::unique_ptr<WasmCode> code{new WasmCode{
11311143
this, // native_module
@@ -1171,6 +1183,7 @@ void NativeModule::AddCodeSpace(base::AddressRegion region) {
11711183
#endif // V8_OS_WIN64
11721184

11731185
WasmCodeRefScope code_ref_scope;
1186+
CODE_SPACE_WRITE_SCOPE
11741187
WasmCode* jump_table = nullptr;
11751188
const uint32_t num_wasm_functions = module_->num_declared_functions;
11761189
const bool has_functions = num_wasm_functions > 0;
@@ -1353,7 +1366,11 @@ VirtualMemory WasmCodeManager::TryAllocate(size_t size, void* hint) {
13531366
if (!memory_tracker_->ReserveAddressSpace(size)) return {};
13541367
if (hint == nullptr) hint = page_allocator->GetRandomMmapAddr();
13551368

1356-
VirtualMemory mem(page_allocator, size, hint, allocate_page_size);
1369+
// When we start exposing Wasm in jitless mode, then the jitless flag
1370+
// will have to determine whether we set kMapAsJittable or not.
1371+
DCHECK(!FLAG_jitless);
1372+
VirtualMemory mem(page_allocator, size, hint, allocate_page_size,
1373+
VirtualMemory::kMapAsJittable);
13571374
if (!mem.IsReserved()) {
13581375
memory_tracker_->ReleaseReservation(size);
13591376
return {};
@@ -1513,6 +1530,7 @@ std::vector<WasmCode*> NativeModule::AddCompiledCode(
15131530
DCHECK(!results.empty());
15141531
// First, allocate code space for all the results.
15151532
size_t total_code_space = 0;
1533+
CODE_SPACE_WRITE_SCOPE
15161534
for (auto& result : results) {
15171535
DCHECK(result.succeeded());
15181536
total_code_space += RoundUp<kCodeAlignment>(result.code_desc.instr_size);

deps/v8/src/wasm/wasm-serialization.cc

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "src/utils/ostreams.h"
1515
#include "src/utils/utils.h"
1616
#include "src/utils/version.h"
17+
#include "src/wasm/code-space-access.h"
1718
#include "src/wasm/function-compiler.h"
1819
#include "src/wasm/module-compiler.h"
1920
#include "src/wasm/module-decoder.h"
@@ -537,6 +538,7 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
537538
protected_instructions_size);
538539
reader->ReadVector(Vector<byte>::cast(protected_instructions.as_vector()));
539540

541+
CODE_SPACE_WRITE_SCOPE
540542
WasmCode* code = native_module_->AddDeserializedCode(
541543
fn_index, code_buffer, stack_slot_count, tagged_parameter_slots,
542544
safepoint_table_offset, handler_table_offset, constant_pool_offset,

0 commit comments

Comments
 (0)