diff --git a/src/api/embed_helpers.cc b/src/api/embed_helpers.cc index f0f92c690eb63c..cb43e07bf44ff4 100644 --- a/src/api/embed_helpers.cc +++ b/src/api/embed_helpers.cc @@ -1,8 +1,11 @@ #include "node.h" #include "env-inl.h" #include "debug_utils-inl.h" +#include "v8-cppgc.h" using v8::Context; +using v8::CppHeap; +using v8::CppHeapCreateParams; using v8::Function; using v8::Global; using v8::HandleScope; @@ -13,6 +16,7 @@ using v8::Locker; using v8::Maybe; using v8::Nothing; using v8::SealHandleScope; +using v8::WrapperDescriptor; namespace node { @@ -78,6 +82,7 @@ struct CommonEnvironmentSetup::Impl { uv_loop_t loop; std::shared_ptr allocator; Isolate* isolate = nullptr; + std::unique_ptr cpp_heap; DeleteFnPtr isolate_data; DeleteFnPtr env; Global context; @@ -107,6 +112,17 @@ CommonEnvironmentSetup::CommonEnvironmentSetup( impl_->isolate = NewIsolate(impl_->allocator, &impl_->loop, platform); Isolate* isolate = impl_->isolate; + impl_->cpp_heap = CppHeap::Create( + platform, + CppHeapCreateParams { + {}, + WrapperDescriptor( + BaseObject::kEmbedderType, + BaseObject::kSlot, + 0x90df) + }); + isolate->AttachCppHeap(impl_->cpp_heap.get()); + { Locker locker(isolate); Isolate::Scope isolate_scope(isolate); @@ -138,6 +154,9 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() { impl_->isolate_data.reset(); } + isolate->DetachCppHeap(); + impl_->cpp_heap->Terminate(); + bool platform_finished = false; impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) { *static_cast(data) = true; diff --git a/src/node.cc b/src/node.cc index 3da63b5d511531..80ffb91e91a98e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -61,6 +61,8 @@ #endif // NODE_USE_V8_PLATFORM #include "v8-profiler.h" +#include "cppgc/platform.h" + #if HAVE_INSPECTOR #include "inspector/worker_inspector.h" // ParentInspectorHandle #endif @@ -1046,6 +1048,15 @@ InitializeOncePerProcessInternal(const std::vector& args, V8::Initialize(); } + if (!(flags & ProcessInitializationFlags::kNoInitializeCppgc)) { + // V8 falls back to an internal page_allocator if one isn't specified. + v8::PageAllocator *page_allocator = nullptr; + if (!(flags & ProcessInitializationFlags::kNoInitializeNodeV8Platform)) { + page_allocator = per_process::v8_platform.Platform()->GetPageAllocator(); + } + cppgc::InitializeProcess(page_allocator); + } + performance::performance_v8_start = PERFORMANCE_NOW(); per_process::v8_initialized = true; @@ -1065,6 +1076,10 @@ void TearDownOncePerProcess() { ResetSignalHandlers(); } + if (!(flags & ProcessInitializationFlags::kNoInitializeCppgc)) { + cppgc::ShutdownProcess(); + } + per_process::v8_initialized = false; if (!(flags & ProcessInitializationFlags::kNoInitializeV8)) { V8::Dispose(); diff --git a/src/node.h b/src/node.h index 561af155561923..e771f9572e196c 100644 --- a/src/node.h +++ b/src/node.h @@ -260,6 +260,8 @@ enum Flags : uint64_t { kNoUseLargePages = 1 << 11, // Skip printing output for --help, --version, --v8-options. kNoPrintHelpOrVersionOutput = 1 << 12, + // Do not perform cppgc initialization. + kNoInitializeCppgc = 1 << 13, // Emulate the behavior of InitializeNodeWithArgs() when passing // a flags argument to the InitializeOncePerProcess() replacement @@ -268,7 +270,7 @@ enum Flags : uint64_t { kNoStdioInitialization | kNoDefaultSignalHandling | kNoInitializeV8 | kNoInitializeNodeV8Platform | kNoInitOpenSSL | kNoParseGlobalDebugVariables | kNoAdjustResourceLimits | - kNoUseLargePages | kNoPrintHelpOrVersionOutput, + kNoUseLargePages | kNoPrintHelpOrVersionOutput | kNoInitializeCppgc, }; } // namespace ProcessFlags // TODO(addaleax): Make this the canonical name, as it is more descriptive. diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index 3e0167fdddea12..7136e42772d12d 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -13,6 +13,7 @@ #include "node_snapshotable.h" #include "node_v8_platform-inl.h" #include "util-inl.h" +#include "v8-cppgc.h" #if defined(LEAK_SANITIZER) #include #endif @@ -24,10 +25,13 @@ namespace node { using v8::Context; +using v8::CppHeap; +using v8::CppHeapCreateParams; using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Locker; +using v8::WrapperDescriptor; NodeMainInstance::NodeMainInstance(Isolate* isolate, uv_loop_t* event_loop, @@ -84,6 +88,17 @@ NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data, SetIsolateCreateParamsForNode(isolate_params_.get()); Isolate::Initialize(isolate_, *isolate_params_); + cpp_heap_ = CppHeap::Create( + platform, + CppHeapCreateParams { + {}, + WrapperDescriptor( + BaseObject::kEmbedderType, + BaseObject::kSlot, + 0x90df) + }); + isolate_->AttachCppHeap(cpp_heap_.get()); + // If the indexes are not nullptr, we are not deserializing isolate_data_ = std::make_unique( isolate_, @@ -114,6 +129,8 @@ NodeMainInstance::~NodeMainInstance() { return; } // This should only be done on a main instance that owns its isolate. + isolate_->DetachCppHeap(); + cpp_heap_->Terminate(); platform_->UnregisterIsolate(isolate_); isolate_->Dispose(); } diff --git a/src/node_main_instance.h b/src/node_main_instance.h index 43b6a8d64e409f..eadc0d4b7fb5fe 100644 --- a/src/node_main_instance.h +++ b/src/node_main_instance.h @@ -83,6 +83,7 @@ class NodeMainInstance { std::unique_ptr array_buffer_allocator_; v8::Isolate* isolate_; MultiIsolatePlatform* platform_; + std::unique_ptr cpp_heap_; std::unique_ptr isolate_data_; std::unique_ptr isolate_params_; const SnapshotData* snapshot_data_ = nullptr; diff --git a/tools/install.py b/tools/install.py index 4b01d67da54e1f..a4b08b7f66c8bb 100755 --- a/tools/install.py +++ b/tools/install.py @@ -197,15 +197,56 @@ def files(action): def headers(action): def wanted_v8_headers(files_arg, dest): v8_headers = [ + 'deps/v8/include/cppgc/allocation.h', 'deps/v8/include/cppgc/common.h', - 'deps/v8/include/libplatform/libplatform.h', + 'deps/v8/include/cppgc/cross-thread-persistent.h', + 'deps/v8/include/cppgc/custom-space.h', + 'deps/v8/include/cppgc/default-platform.h', + 'deps/v8/include/cppgc/ephemeron-pair.h', + 'deps/v8/include/cppgc/explicit-management.h', + 'deps/v8/include/cppgc/garbage-collected.h', + 'deps/v8/include/cppgc/heap-consistency.h', + 'deps/v8/include/cppgc/heap-handle.h', + 'deps/v8/include/cppgc/heap-state.h', + 'deps/v8/include/cppgc/heap-statistics.h', + 'deps/v8/include/cppgc/heap.h', + 'deps/v8/include/cppgc/internal/api-constants.h', + 'deps/v8/include/cppgc/internal/atomic-entry-flag.h', + 'deps/v8/include/cppgc/internal/base-page-handle.h', + 'deps/v8/include/cppgc/internal/caged-heap-local-data.h', + 'deps/v8/include/cppgc/internal/caged-heap.h', + 'deps/v8/include/cppgc/internal/compiler-specific.h', + 'deps/v8/include/cppgc/internal/finalizer-trait.h', + 'deps/v8/include/cppgc/internal/gc-info.h', + 'deps/v8/include/cppgc/internal/logging.h', + 'deps/v8/include/cppgc/internal/member-storage.h', + 'deps/v8/include/cppgc/internal/name-trait.h', + 'deps/v8/include/cppgc/internal/persistent-node.h', + 'deps/v8/include/cppgc/internal/pointer-policies.h', + 'deps/v8/include/cppgc/internal/write-barrier.h', + 'deps/v8/include/cppgc/liveness-broker.h', + 'deps/v8/include/cppgc/macros.h', + 'deps/v8/include/cppgc/member.h', + 'deps/v8/include/cppgc/name-provider.h', + 'deps/v8/include/cppgc/object-size-trait.h', + 'deps/v8/include/cppgc/persistent.h', + 'deps/v8/include/cppgc/platform.h', + 'deps/v8/include/cppgc/prefinalizer.h', + 'deps/v8/include/cppgc/process-heap-statistics.h', + 'deps/v8/include/cppgc/sentinel-pointer.h', + 'deps/v8/include/cppgc/source-location.h', + 'deps/v8/include/cppgc/testing.h', + 'deps/v8/include/cppgc/trace-trait.h', + 'deps/v8/include/cppgc/type-traits.h', + 'deps/v8/include/cppgc/visitor.h', 'deps/v8/include/libplatform/libplatform-export.h', + 'deps/v8/include/libplatform/libplatform.h', 'deps/v8/include/libplatform/v8-tracing.h', - 'deps/v8/include/v8.h', 'deps/v8/include/v8-array-buffer.h', 'deps/v8/include/v8-callbacks.h', 'deps/v8/include/v8-container.h', 'deps/v8/include/v8-context.h', + 'deps/v8/include/v8-cppgc.h', 'deps/v8/include/v8-data.h', 'deps/v8/include/v8-date.h', 'deps/v8/include/v8-debug.h', @@ -249,6 +290,7 @@ def wanted_v8_headers(files_arg, dest): 'deps/v8/include/v8-version.h', 'deps/v8/include/v8-wasm.h', 'deps/v8/include/v8-weak-callback-info.h', + 'deps/v8/include/v8.h', 'deps/v8/include/v8config.h', ] files_arg = [name for name in files_arg if name in v8_headers]