From cfc2ca9c0a12d99609af7cfdd382986b0832fb37 Mon Sep 17 00:00:00 2001 From: Marcel Laverdet Date: Wed, 6 Nov 2019 11:48:30 -0800 Subject: [PATCH] Break out platform delegate --- src/node.h | 12 ++++++++++ src/node_platform.cc | 57 +++++++++++++++++++++++++++++++------------- src/node_platform.h | 12 ++++++++-- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/node.h b/src/node.h index 872e0a811a608b..de5f9c4dd17234 100644 --- a/src/node.h +++ b/src/node.h @@ -252,6 +252,15 @@ class NODE_EXTERN ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator(); NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator); +class NODE_EXTERN IsolatePlatformDelegate { + public: + virtual std::shared_ptr GetForegroundTaskRunner() = 0; + virtual bool IdleTasksEnabled() = 0; + private: + friend class NodePlatform; + virtual class PerIsolatePlatformData* NodePerIsolate() { return nullptr; } +}; + class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { public: ~MultiIsolatePlatform() override = default; @@ -273,6 +282,9 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { // This function may only be called once per `Isolate`. virtual void RegisterIsolate(v8::Isolate* isolate, struct uv_loop_s* loop) = 0; + virtual void RegisterIsolate( + v8::Isolate* isolate, + std::shared_ptr delegate); // This function may only be called once per `Isolate`, and discard any // pending delayed tasks scheduled for that isolate. diff --git a/src/node_platform.cc b/src/node_platform.cc index 6e3b4abfee7287..8c165fad29a6d9 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -221,6 +221,12 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const { return threads_.size(); } +void MultiIsolatePlatform::RegisterIsolate( + v8::Isolate* isolate, + std::shared_ptr delegate) { + UNREACHABLE(); +} + PerIsolatePlatformData::PerIsolatePlatformData( Isolate* isolate, uv_loop_t* loop) : loop_(loop) { @@ -230,6 +236,11 @@ PerIsolatePlatformData::PerIsolatePlatformData( uv_unref(reinterpret_cast(flush_tasks_)); } +std::shared_ptr +PerIsolatePlatformData::GetForegroundTaskRunner() { + return shared_from_this(); +} + void PerIsolatePlatformData::FlushTasks(uv_async_t* handle) { auto platform_data = static_cast(handle->data); platform_data->FlushForegroundTasksInternal(); @@ -267,7 +278,7 @@ void PerIsolatePlatformData::PostNonNestableDelayedTask( } PerIsolatePlatformData::~PerIsolatePlatformData() { - Shutdown(); + CHECK(!flush_tasks_); } void PerIsolatePlatformData::AddShutdownCallback(void (*callback)(void*), @@ -324,19 +335,27 @@ NodePlatform::NodePlatform(int thread_pool_size, } void NodePlatform::RegisterIsolate(Isolate* isolate, uv_loop_t* loop) { + RegisterIsolate( + isolate, std::make_shared(isolate, loop)); +} + +void NodePlatform::RegisterIsolate( + Isolate* isolate, + std::shared_ptr delegate) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr existing = per_isolate_[isolate]; - CHECK(!existing); - per_isolate_[isolate] = - std::make_shared(isolate, loop); + auto insertion = per_isolate_.emplace(isolate, std::move(delegate)); + CHECK(insertion.second); } void NodePlatform::UnregisterIsolate(Isolate* isolate) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr existing = per_isolate_[isolate]; - CHECK(existing); - existing->Shutdown(); - per_isolate_.erase(isolate); + auto existing_it = per_isolate_.find(isolate); + CHECK_NE(existing_it, per_isolate_.end()); + PerIsolatePlatformData* node_data = existing_it->second->NodePerIsolate(); + if (node_data) { + node_data->Shutdown(); + } + per_isolate_.erase(existing_it); } void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate, @@ -344,11 +363,10 @@ void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate, Mutex::ScopedLock lock(per_isolate_mutex_); auto it = per_isolate_.find(isolate); if (it == per_isolate_.end()) { - CHECK(it->second); cb(data); return; } - it->second->AddShutdownCallback(cb, data); + it->second->NodePerIsolate()->AddShutdownCallback(cb, data); } void NodePlatform::Shutdown() { @@ -394,7 +412,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) { } void NodePlatform::DrainTasks(Isolate* isolate) { - std::shared_ptr per_isolate = ForIsolate(isolate); + std::shared_ptr per_isolate = ForNodeIsolate(isolate); do { // Worker tasks aren't associated with an Isolate. @@ -452,23 +470,30 @@ void NodePlatform::CallDelayedOnWorkerThread(std::unique_ptr task, } -std::shared_ptr +std::shared_ptr NodePlatform::ForIsolate(Isolate* isolate) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr data = per_isolate_[isolate]; + std::shared_ptr data = per_isolate_[isolate]; CHECK(data); return data; } +std::shared_ptr +NodePlatform::ForNodeIsolate(Isolate* isolate) { + std::shared_ptr data = ForIsolate(isolate); + CHECK(data->NodePerIsolate()); + return std::static_pointer_cast(std::move(data)); +} + bool NodePlatform::FlushForegroundTasks(Isolate* isolate) { - return ForIsolate(isolate)->FlushForegroundTasksInternal(); + return ForNodeIsolate(isolate)->FlushForegroundTasksInternal(); } bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; } std::shared_ptr NodePlatform::GetForegroundTaskRunner(Isolate* isolate) { - return ForIsolate(isolate); + return ForIsolate(isolate)->GetForegroundTaskRunner(); } double NodePlatform::MonotonicallyIncreasingTime() { diff --git a/src/node_platform.h b/src/node_platform.h index 24f7b337bb8fd7..c313b13c6770e3 100644 --- a/src/node_platform.h +++ b/src/node_platform.h @@ -52,17 +52,20 @@ struct DelayedTask { // This acts as the foreground task runner for a given Isolate. class PerIsolatePlatformData : + public IsolatePlatformDelegate, public v8::TaskRunner, public std::enable_shared_from_this { public: PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop); ~PerIsolatePlatformData() override; + std::shared_ptr GetForegroundTaskRunner() override; void PostTask(std::unique_ptr task) override; void PostIdleTask(std::unique_ptr task) override; void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override; bool IdleTasksEnabled() override { return false; } + PerIsolatePlatformData* NodePerIsolate() final { return this; } // Non-nestable tasks are treated like regular tasks. bool NonNestableTasksEnabled() const override { return true; } @@ -162,6 +165,10 @@ class NodePlatform : public MultiIsolatePlatform { bool FlushForegroundTasks(v8::Isolate* isolate) override; void RegisterIsolate(v8::Isolate* isolate, uv_loop_t* loop) override; + void RegisterIsolate( + v8::Isolate* isolate, + std::shared_ptr delegate) override; + void UnregisterIsolate(v8::Isolate* isolate) override; void AddIsolateFinishedCallback(v8::Isolate* isolate, void (*callback)(void*), void* data) override; @@ -170,11 +177,12 @@ class NodePlatform : public MultiIsolatePlatform { v8::Isolate* isolate) override; private: - std::shared_ptr ForIsolate(v8::Isolate* isolate); + std::shared_ptr ForIsolate(v8::Isolate* isolate); + std::shared_ptr ForNodeIsolate(v8::Isolate* isolate); Mutex per_isolate_mutex_; std::unordered_map> per_isolate_; + std::shared_ptr> per_isolate_; node::tracing::TracingController* tracing_controller_; std::shared_ptr worker_thread_task_runner_;