From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 3 Nov 2020 16:17:38 -0800 Subject: src: allow embedders to provide a custom PageAllocator to NodePlatform For certain embedder use cases there are more complex memory allocation requirements that the default V8 page allocator does not handle, for example using MAP_JIT when running under a hardened runtime environment on macOS. This allows such embedders to provide their own allocator that does handle these cases. diff --git a/src/api/environment.cc b/src/api/environment.cc index c08fe4b32d4155badb572f15529f903c0ec63146..a8cf0d763f78c2752e3aa22479dadd9fa53c222f 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -488,8 +488,9 @@ MultiIsolatePlatform* CreatePlatform( MultiIsolatePlatform* CreatePlatform( int thread_pool_size, - v8::TracingController* tracing_controller) { - return MultiIsolatePlatform::Create(thread_pool_size, tracing_controller) + v8::TracingController* tracing_controller, + v8::PageAllocator* page_allocator) { + return MultiIsolatePlatform::Create(thread_pool_size, tracing_controller, page_allocator) .release(); } @@ -499,8 +500,9 @@ void FreePlatform(MultiIsolatePlatform* platform) { std::unique_ptr MultiIsolatePlatform::Create( int thread_pool_size, - v8::TracingController* tracing_controller) { - return std::make_unique(thread_pool_size, tracing_controller); + v8::TracingController* tracing_controller, + v8::PageAllocator* page_allocator) { + return std::make_unique(thread_pool_size, tracing_controller, page_allocator); } MaybeLocal GetPerContextExports(Local context) { diff --git a/src/node.h b/src/node.h index b646fdda58ebcbf2dd92ee4fc9cb0d9c039174d1..14893ad605b9f8c64b0b8fc28625e235655dcd63 100644 --- a/src/node.h +++ b/src/node.h @@ -333,7 +333,8 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { static std::unique_ptr Create( int thread_pool_size, - v8::TracingController* tracing_controller = nullptr); + v8::TracingController* tracing_controller = nullptr, + v8::PageAllocator* page_allocator = nullptr); }; enum IsolateSettingsFlags { @@ -536,7 +537,8 @@ NODE_DEPRECATED("Use variant taking a v8::TracingController* pointer instead", node::tracing::TracingController* tracing_controller)); NODE_EXTERN MultiIsolatePlatform* CreatePlatform( int thread_pool_size, - v8::TracingController* tracing_controller); + v8::TracingController* tracing_controller, + v8::PageAllocator* = nullptr); NODE_EXTERN void FreePlatform(MultiIsolatePlatform* platform); // Get/set the currently active tracing controller. Using CreatePlatform() diff --git a/src/node_platform.cc b/src/node_platform.cc index aac0682670fcffd235fcf450bc5e2b0d45985b47..96be2281b562c44b276483970c06862250ea8941 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -324,12 +324,16 @@ void PerIsolatePlatformData::DecreaseHandleCount() { } NodePlatform::NodePlatform(int thread_pool_size, - v8::TracingController* tracing_controller) { + v8::TracingController* tracing_controller, + v8::PageAllocator* page_allocator) { if (tracing_controller != nullptr) { tracing_controller_ = tracing_controller; } else { tracing_controller_ = new v8::TracingController(); } + // This being nullptr is acceptable as V8 will default to its built + // in allocator if none is provided + page_allocator_ = page_allocator; // TODO(addaleax): It's a bit icky that we use global state here, but we can't // really do anything about it unless V8 starts exposing a way to access the // current v8::Platform instance. @@ -544,6 +548,10 @@ Platform::StackTracePrinter NodePlatform::GetStackTracePrinter() { }; } +v8::PageAllocator* NodePlatform::GetPageAllocator() { + return page_allocator_; +} + std::unique_ptr NodePlatform::PostJob(v8::TaskPriority priority, std::unique_ptr job_task) { return v8::platform::NewDefaultJobHandle(this, priority, std::move(job_task), 1 /* num_worker_threads */); } diff --git a/src/node_platform.h b/src/node_platform.h index a274be6bbea19a4488bca393712a9ac8b50fe16a..314cf2d1056d30a77ead400d100a4d4c6f844be6 100644 --- a/src/node_platform.h +++ b/src/node_platform.h @@ -138,7 +138,8 @@ class WorkerThreadsTaskRunner { class NodePlatform : public MultiIsolatePlatform { public: NodePlatform(int thread_pool_size, - v8::TracingController* tracing_controller); + v8::TracingController* tracing_controller, + v8::PageAllocator* page_allocator = nullptr); ~NodePlatform() override; void DrainTasks(v8::Isolate* isolate) override; @@ -168,6 +169,7 @@ class NodePlatform : public MultiIsolatePlatform { v8::Isolate* isolate) override; Platform::StackTracePrinter GetStackTracePrinter() override; + v8::PageAllocator* GetPageAllocator() override; private: IsolatePlatformDelegate* ForIsolate(v8::Isolate* isolate); @@ -179,6 +181,7 @@ class NodePlatform : public MultiIsolatePlatform { std::unordered_map per_isolate_; v8::TracingController* tracing_controller_; + v8::PageAllocator* page_allocator_; std::shared_ptr worker_thread_task_runner_; bool has_shut_down_ = false; };