Commit a3a2284e authored by wenqin.yang's avatar wenqin.yang Committed by V8 LUCI CQ

[pku][heap] Support PKUs for V8 heap

This CL adds PKU support for V8 heap, but we will not enable
PKU by default before adding bots that are able to test the
PKU machinery.

Bug: v8:13023
Change-Id: I0465604d56900536ad63311f119ea0324ebe4f2f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3793944Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Wenqin Yang <wenqin.yang@intel.com>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82965}
parent 3f9f1eee
......@@ -54,7 +54,7 @@ pkey_mprotect_t pkey_mprotect = nullptr;
pkey_get_t pkey_get = nullptr;
pkey_set_t pkey_set = nullptr;
#ifdef DEBUG
#if DEBUG
bool pkey_api_initialized = false;
#endif
......@@ -169,38 +169,31 @@ bool MemoryProtectionKey::SetPermissionsAndKey(
v8::PageAllocator* page_allocator, base::AddressRegion region,
v8::PageAllocator::Permission page_permissions, int key) {
DCHECK(pkey_api_initialized);
DCHECK_NE(key, kNoMemoryProtectionKey);
CHECK_NOT_NULL(pkey_mprotect);
void* address = reinterpret_cast<void*>(region.begin());
size_t size = region.size();
if (pkey_mprotect) {
// Copied with slight modifications from base/platform/platform-posix.cc
// {OS::SetPermissions()}.
// TODO(dlehmann): Move this block into its own function at the right
// abstraction boundary (likely some static method in platform.h {OS})
// once the whole PKU code is moved into base/platform/.
DCHECK_EQ(0, region.begin() % page_allocator->CommitPageSize());
DCHECK_EQ(0, size % page_allocator->CommitPageSize());
// Copied with slight modifications from base/platform/platform-posix.cc
// {OS::SetPermissions()}.
// TODO(dlehmann): Move this block into its own function at the right
// abstraction boundary (likely some static method in platform.h {OS})
// once the whole PKU code is moved into base/platform/.
DCHECK_EQ(0, region.begin() % page_allocator->CommitPageSize());
DCHECK_EQ(0, size % page_allocator->CommitPageSize());
int protection = GetProtectionFromMemoryPermission(page_permissions);
int protection = GetProtectionFromMemoryPermission(page_permissions);
int ret = pkey_mprotect(address, size, protection, key);
int ret = pkey_mprotect(address, size, protection, key);
if (ret == 0 && page_permissions == PageAllocator::kNoAccess) {
// Similar to {OS::SetPermissions}, also discard the pages after switching
// to no access. This is advisory; ignore errors and continue execution.
USE(page_allocator->DiscardSystemPages(address, size));
}
return ret == /* success */ 0;
if (ret == 0 && page_permissions == PageAllocator::kNoAccess) {
// Similar to {OS::SetPermissions}, also discard the pages after switching
// to no access. This is advisory; ignore errors and continue execution.
USE(page_allocator->DiscardSystemPages(address, size));
}
// If there is no runtime support for {pkey_mprotect()}, no key should have
// been allocated in the first place.
DCHECK_EQ(kNoMemoryProtectionKey, key);
// Without PKU support, fallback to regular {mprotect()}.
return page_allocator->SetPermissions(address, size, page_permissions);
return ret == /* success */ 0;
}
// static
......
......@@ -161,6 +161,7 @@ class ConcurrentBaselineCompiler {
outgoing_queue_(outcoming_queue) {}
void Run(JobDelegate* delegate) override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_isolate);
LocalHandleScope handle_scope(&local_isolate);
......
......@@ -1766,6 +1766,7 @@ class MergeAssumptionChecker final : public ObjectVisitor {
} // namespace
void BackgroundCompileTask::Run() {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
DCHECK_NE(ThreadId::Current(), isolate_for_local_isolate_->thread_id());
LocalIsolate isolate(isolate_for_local_isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&isolate);
......@@ -2264,6 +2265,7 @@ BackgroundDeserializeTask::BackgroundDeserializeTask(
}
void BackgroundDeserializeTask::Run() {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
LocalIsolate isolate(isolate_for_local_isolate_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&isolate);
LocalHandleScope handle_scope(&isolate);
......
......@@ -15,6 +15,7 @@ namespace v8 {
namespace internal {
RwxMemoryWriteScope::RwxMemoryWriteScope(const char* comment) {
DCHECK(is_key_permissions_initialized_for_current_thread());
if (!FLAG_jitless) {
SetWritable();
}
......
......@@ -16,8 +16,15 @@ int RwxMemoryWriteScope::memory_protection_key_ =
base::MemoryProtectionKey::kNoMemoryProtectionKey;
#if DEBUG
thread_local bool
RwxMemoryWriteScope::is_key_permissions_initialized_for_current_thread_ =
false;
bool RwxMemoryWriteScope::pkey_initialized = false;
#endif
bool RwxMemoryWriteScope::is_key_permissions_initialized_for_current_thread() {
return is_key_permissions_initialized_for_current_thread_;
}
#endif // DEBUG
void RwxMemoryWriteScope::InitializeMemoryProtectionKey() {
// Flip {pkey_initialized} (in debug mode) and check the new value.
......@@ -36,23 +43,55 @@ bool RwxMemoryWriteScope::IsPKUWritable() {
ResetPKUPermissionsForThreadSpawning::ResetPKUPermissionsForThreadSpawning() {
if (!RwxMemoryWriteScope::IsSupported()) return;
int pkey = RwxMemoryWriteScope::memory_protection_key();
was_writable_ = base::MemoryProtectionKey::GetKeyPermission(pkey) ==
base::MemoryProtectionKey::kNoRestrictions;
was_writable_ = RwxMemoryWriteScope::IsPKUWritable();
if (was_writable_) {
base::MemoryProtectionKey::SetPermissionsForKey(
pkey, base::MemoryProtectionKey::kDisableWrite);
RwxMemoryWriteScope::memory_protection_key(),
base::MemoryProtectionKey::kDisableWrite);
}
}
ResetPKUPermissionsForThreadSpawning::~ResetPKUPermissionsForThreadSpawning() {
if (!RwxMemoryWriteScope::IsSupported()) return;
int pkey = RwxMemoryWriteScope::memory_protection_key();
if (was_writable_) {
base::MemoryProtectionKey::SetPermissionsForKey(
pkey, base::MemoryProtectionKey::kNoRestrictions);
RwxMemoryWriteScope::memory_protection_key(),
base::MemoryProtectionKey::kNoRestrictions);
}
}
void RwxMemoryWriteScope::SetDefaultPermissionsForNewThread() {
// TODO(v8:13023): consider initializing the permissions only once per thread
// if the SetPermissionsForKey() call is too heavy.
if (RwxMemoryWriteScope::IsSupported() &&
base::MemoryProtectionKey::GetKeyPermission(
RwxMemoryWriteScope::memory_protection_key()) ==
base::MemoryProtectionKey::kDisableAccess) {
base::MemoryProtectionKey::SetPermissionsForKey(
RwxMemoryWriteScope::memory_protection_key(),
base::MemoryProtectionKey::kDisableWrite);
}
#if DEBUG
is_key_permissions_initialized_for_current_thread_ = true;
#endif
}
void RwxMemoryWriteScope::SetDefaultPermissionsForSignalHandler() {
DCHECK(pkey_initialized);
DCHECK(is_key_permissions_initialized_for_current_thread_);
if (!RwxMemoryWriteScope::IsSupported()) return;
base::MemoryProtectionKey::SetPermissionsForKey(
memory_protection_key_, base::MemoryProtectionKey::kDisableWrite);
}
#else // !V8_HAS_PKU_JIT_WRITE_PROTECT
void RwxMemoryWriteScope::SetDefaultPermissionsForNewThread() {}
#if DEBUG
bool RwxMemoryWriteScope::is_key_permissions_initialized_for_current_thread() {
return true;
}
#endif // DEBUG
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
RwxMemoryWriteScopeForTesting::RwxMemoryWriteScopeForTesting()
......
......@@ -57,12 +57,25 @@ class V8_NODISCARD RwxMemoryWriteScope {
// executable pages.
V8_INLINE static bool IsSupported();
// Sets key's permissions to default state (kDisableWrite) for current thread
// if it wasn't done before. V8 doesn't have control of the worker threads
// used by v8::TaskRunner and thus it's not guaranteed that a thread executing
// a V8 task has the right permissions for the key. V8 tasks that access code
// page bodies must call this function to ensure that they have at least read
// access.
V8_EXPORT_PRIVATE static void SetDefaultPermissionsForNewThread();
#if V8_HAS_PKU_JIT_WRITE_PROTECT
static int memory_protection_key() { return memory_protection_key_; }
static void InitializeMemoryProtectionKey();
static bool IsPKUWritable();
// Linux resets key's permissions to kDisableAccess before executing signal
// handlers. If the handler requires access to code page bodies it should take
// care of changing permissions to the default state (kDisableWrite).
static void SetDefaultPermissionsForSignalHandler();
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
private:
......@@ -85,10 +98,22 @@ class V8_NODISCARD RwxMemoryWriteScope {
#if V8_HAS_PKU_JIT_WRITE_PROTECT
static int memory_protection_key_;
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
#if DEBUG
V8_EXPORT_PRIVATE static bool
is_key_permissions_initialized_for_current_thread();
#if V8_HAS_PKU_JIT_WRITE_PROTECT
// The state of the PKU key permissions are inherited from the parent
// thread when a new thread is created. Since we don't always control
// the parent thread, we ensure that the new thread resets their key's
// permissions to the default kDisableWrite state.
// This flag is used for checking that threads have initialized the
// permissions.
static thread_local bool is_key_permissions_initialized_for_current_thread_;
static bool pkey_initialized;
#endif
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
#endif // DEBUG
};
// This class is a no-op version of the RwxMemoryWriteScope class above.
......@@ -111,8 +136,8 @@ class V8_NODISCARD NopRwxMemoryWriteScope final {
class V8_NODISCARD ResetPKUPermissionsForThreadSpawning {
public:
#if V8_HAS_PKU_JIT_WRITE_PROTECT
ResetPKUPermissionsForThreadSpawning();
~ResetPKUPermissionsForThreadSpawning();
V8_EXPORT_PRIVATE ResetPKUPermissionsForThreadSpawning();
V8_EXPORT_PRIVATE ~ResetPKUPermissionsForThreadSpawning();
private:
bool was_writable_;
......
......@@ -284,6 +284,14 @@ using CodeT = Code;
#define V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT false
#endif
// TODO(v8:13023): enable PKU support when we have a test coverage
#if V8_HAS_PKU_JIT_WRITE_PROTECT && \
!(defined(V8_COMPRESS_POINTERS) && !defined(V8_EXTERNAL_CODE_SPACE))
#define V8_HEAP_USE_PKU_JIT_WRITE_PROTECT false
#else
#define V8_HEAP_USE_PKU_JIT_WRITE_PROTECT false
#endif
// Determine whether tagged pointers are 8 bytes (used in Torque layouts for
// choosing where to insert padding).
#if V8_TARGET_ARCH_64_BIT && !defined(V8_COMPRESS_POINTERS)
......
......@@ -58,6 +58,10 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
dispatcher_->recompilation_delay_));
}
// This task doesn't modify code objects but it needs a read access to the
// code space in order to be able to get a bytecode array from a baseline
// code. See SharedFunctionInfo::GetActiveBytecodeArray() for details.
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
dispatcher_->CompileNext(dispatcher_->NextInput(&local_isolate),
&local_isolate);
}
......
......@@ -4118,6 +4118,8 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
DCHECK_EQ(create_heap_objects, startup_snapshot_data == nullptr);
DCHECK_EQ(create_heap_objects, shared_heap_snapshot_data == nullptr);
// Code space setup requires the permissions to be set to default state.
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
base::ElapsedTimer timer;
if (create_heap_objects && FLAG_profile_deserialization) timer.Start();
......@@ -4487,6 +4489,7 @@ void Isolate::Enter() {
}
}
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
DCHECK_NOT_NULL(data);
DCHECK(data->isolate_ == this);
......
......@@ -669,6 +669,7 @@ void ConcurrentMarking::RunMajor(JobDelegate* delegate,
base::EnumSet<CodeFlushMode> code_flush_mode,
unsigned mark_compact_epoch,
bool should_keep_ages_unchanged) {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
size_t kBytesUntilInterruptCheck = 64 * KB;
int kObjectsUntilInterruptCheck = 1000;
uint8_t task_id = delegate->GetTaskId() + 1;
......
......@@ -616,7 +616,7 @@ AlwaysAllocateScopeForTesting::AlwaysAllocateScopeForTesting(Heap* heap)
CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* heap)
:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
rwx_write_scope_("A part of CodeSpaceMemoryModificationScope"),
#endif
heap_(heap) {
......@@ -679,7 +679,7 @@ CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() {
CodePageCollectionMemoryModificationScope::
CodePageCollectionMemoryModificationScope(Heap* heap)
:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
rwx_write_scope_("A part of CodePageCollectionMemoryModificationScope"),
#endif
heap_(heap) {
......@@ -700,7 +700,7 @@ CodePageCollectionMemoryModificationScope::
#ifdef V8_ENABLE_THIRD_PARTY_HEAP
CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code)
:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
rwx_write_scope_("A part of CodePageMemoryModificationScope"),
#endif
chunk_(nullptr),
......@@ -714,7 +714,7 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code)
CodePageMemoryModificationScope::CodePageMemoryModificationScope(
BasicMemoryChunk* chunk)
:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
rwx_write_scope_("A part of CodePageMemoryModificationScope"),
#endif
chunk_(chunk),
......
......@@ -5532,6 +5532,13 @@ void Heap::SetUpSpaces(LinearAllocationArea& new_allocation_info,
}
write_protect_code_memory_ = FLAG_write_protect_code_memory;
#if V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
if (RwxMemoryWriteScope::IsSupported()) {
// If PKU machinery is available then use it instead of conventional
// mprotect.
write_protect_code_memory_ = false;
}
#endif // V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
if (isolate()->shared_isolate()) {
Heap* shared_heap = isolate()->shared_isolate()->heap();
......
......@@ -2582,7 +2582,7 @@ class V8_NODISCARD CodeSpaceMemoryModificationScope {
inline ~CodeSpaceMemoryModificationScope();
private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
Heap* heap_;
......@@ -2596,7 +2596,7 @@ class V8_NODISCARD CodePageCollectionMemoryModificationScope {
inline ~CodePageCollectionMemoryModificationScope();
private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
Heap* heap_;
......@@ -2661,7 +2661,7 @@ class V8_NODISCARD CodePageMemoryModificationScope {
inline ~CodePageMemoryModificationScope();
private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT || V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
BasicMemoryChunk* chunk_;
......
......@@ -4244,9 +4244,9 @@ void FullEvacuator::RawEvacuatePage(MemoryChunk* chunk, intptr_t* live_bytes) {
marking_state->live_bytes(chunk));
break;
case kObjectsOldToOld: {
CodePageHeaderModificationScope rwx_write_scope(
"Clearing of markbits in Code spaces requires write access to "
"Code page headers");
RwxMemoryWriteScope rwx_write_scope(
"Evacuation of objects in Code space requires write access for the "
"current worker thread.");
const bool success = LiveObjectVisitor::VisitBlackObjects(
chunk, marking_state, &old_space_visitor_,
LiveObjectVisitor::kClearMarkbits, &failed_object);
......@@ -4277,6 +4277,7 @@ class PageEvacuationJob : public v8::JobTask {
tracer_(isolate->heap()->tracer()) {}
void Run(JobDelegate* delegate) override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
Evacuator* evacuator = (*evacuators_)[delegate->GetTaskId()].get();
if (delegate->IsJoiningThread()) {
TRACE_GC(tracer_, evacuator->GetTracingScope());
......@@ -4650,6 +4651,7 @@ class PointersUpdatingJob : public v8::JobTask {
background_scope_(background_scope) {}
void Run(JobDelegate* delegate) override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
if (delegate->IsJoiningThread()) {
TRACE_GC(tracer_, scope_);
UpdatePointers(delegate);
......
......@@ -734,10 +734,24 @@ bool MemoryAllocator::SetPermissionsOnExecutableMemoryChunk(VirtualMemory* vm,
if (vm->SetPermissions(pre_guard_page, page_size,
PageAllocator::kNoAccess)) {
// Commit the executable code body.
if (vm->SetPermissions(
code_area, area_size,
jitless ? PageAllocator::kReadWrite
: MemoryChunk::GetCodeModificationPermission())) {
bool set_permission_successed = false;
#if V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
if (!jitless && RwxMemoryWriteScope::IsSupported()) {
base::AddressRegion region(code_area, area_size);
set_permission_successed =
base::MemoryProtectionKey::SetPermissionsAndKey(
code_page_allocator_, region,
PageAllocator::kReadWriteExecute,
RwxMemoryWriteScope::memory_protection_key());
} else
#endif
{
set_permission_successed = vm->SetPermissions(
code_area, area_size,
jitless ? PageAllocator::kReadWrite
: MemoryChunk::GetCodeModificationPermission());
}
if (set_permission_successed) {
// Create the post-code guard page.
if (vm->SetPermissions(post_guard_page, page_size,
PageAllocator::kNoAccess)) {
......
......@@ -199,6 +199,9 @@ ScavengerCollector::JobTask::JobTask(
promotion_list_(promotion_list) {}
void ScavengerCollector::JobTask::Run(JobDelegate* delegate) {
// The task accesses code pages and thus the permissions must be set to
// default state.
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
DCHECK_LT(delegate->GetTaskId(), scavengers_->size());
Scavenger* scavenger = (*scavengers_)[delegate->GetTaskId()].get();
if (delegate->IsJoiningThread()) {
......
......@@ -68,6 +68,7 @@ class Sweeper::SweeperJob final : public JobTask {
SweeperJob& operator=(const SweeperJob&) = delete;
void Run(JobDelegate* delegate) final {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
if (delegate->IsJoiningThread()) {
TRACE_GC(tracer_, GCTracer::Scope::MC_SWEEP);
RunImpl(delegate);
......
......@@ -1039,6 +1039,9 @@ class Ticker : public sampler::Sampler {
perThreadData_->thread_id()) ||
perThreadData_->thread_state() != nullptr))
return;
#if V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
i::RwxMemoryWriteScope::SetDefaultPermissionsForSignalHandler();
#endif
TickSample sample;
sample.Init(isolate, state, TickSample::kIncludeCEntryFrame, true);
profiler_->Insert(&sample);
......
......@@ -48,6 +48,9 @@ class CpuSampler : public sampler::Sampler {
ProfilerStats::Reason::kIsolateNotLocked);
return;
}
#if V8_HEAP_USE_PKU_JIT_WRITE_PROTECT
i::RwxMemoryWriteScope::SetDefaultPermissionsForSignalHandler();
#endif
TickSample* sample = processor_->StartTickSample();
if (sample == nullptr) {
ProfilerStats::Instance()->AddReason(
......
......@@ -2178,16 +2178,6 @@ bool WasmCodeManager::MemoryProtectionKeyWritable() {
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
}
// static
void WasmCodeManager::InitializeMemoryProtectionKeyPermissionsIfSupported() {
if (!HasMemoryProtectionKeySupport()) return;
// The default permission is {kDisableAccess}. Switch from that to
// {kDisableWrite}. Leave other permissions untouched, as the thread did
// already use the memory protection key in that case.
RwxMemoryWriteScope initialize_permission_scope(
"For initialization if PKU is in kNoAccess permission case.");
}
base::AddressRegion WasmCodeManager::AllocateAssemblerBufferSpace(int size) {
#if V8_HAS_PKU_JIT_WRITE_PROTECT
if (MemoryProtectionKeysEnabled()) {
......
......@@ -1108,10 +1108,6 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
// Can only be called if {HasMemoryProtectionKeySupport()} is {true}.
static bool MemoryProtectionKeyWritable();
// Initialize the current thread's permissions for the memory protection key,
// if we have support.
static void InitializeMemoryProtectionKeyPermissionsIfSupported();
// Allocate new memory for assembler buffers, potentially protected by PKU.
base::AddressRegion AllocateAssemblerBufferSpace(int size);
......
......@@ -1006,12 +1006,6 @@ void WasmEngine::AddIsolate(Isolate* isolate) {
DCHECK_EQ(0, isolates_.count(isolate));
isolates_.emplace(isolate, std::make_unique<IsolateInfo>(isolate));
// The isolate might access existing (cached) code without ever compiling any.
// In that case, the current thread might still have the default permissions
// for the memory protection key (== no access). Thus initialize the
// permissions now.
WasmCodeManager::InitializeMemoryProtectionKeyPermissionsIfSupported();
// Install sampling GC callback.
// TODO(v8:7424): For now we sample module sizes in a GC callback. This will
// bias samples towards apps with high memory pressure. We should switch to
......
......@@ -72,6 +72,7 @@ class ConcurrentAllocationThread final : public v8::base::Thread {
pending_(pending) {}
void Run() override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
LocalHeap local_heap(heap_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_heap);
AllocateSomeObjects(&local_heap);
......@@ -450,6 +451,7 @@ class ConcurrentRecordRelocSlotThread final : public v8::base::Thread {
value_(value) {}
void Run() override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
LocalHeap local_heap(heap_, ThreadKind::kBackground);
UnparkedScope unparked_scope(&local_heap);
// Modification of Code object requires write access.
......@@ -514,6 +516,10 @@ UNINITIALIZED_TEST(ConcurrentRecordRelocSlot) {
CHECK(heap->incremental_marking()->marking_state()->IsWhite(value));
{
// TODO(v8:13023): remove ResetPKUPermissionsForThreadSpawning in the
// future when RwxMemoryWriteScope::SetDefaultPermissionsForNewThread() is
// stable.
ResetPKUPermissionsForThreadSpawning thread_scope;
auto thread =
std::make_unique<ConcurrentRecordRelocSlotThread>(heap, code, value);
CHECK(thread->Start());
......
......@@ -202,6 +202,7 @@ class JumpTablePatcher : public v8::base::Thread {
jump_table_mutex_(jump_table_mutex) {}
void Run() override {
RwxMemoryWriteScope::SetDefaultPermissionsForNewThread();
TRACE("Patcher %p is starting ...\n", this);
RwxMemoryWriteScopeForTesting rwx_write_scope;
Address slot_address =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment