From f0745d2f27611654b6b7810e0e422a2148ee90ee Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 10 Aug 2023 19:01:14 +0200 Subject: [PATCH 1/2] bootstrap: build code cache from deserialized isolate V8 now requires the code cache to be compiled with a finalized read-only space, so we need to serialize the snapshot to get a finalized read-only space first, then deserialize it to compile the code cache. --- src/node_snapshotable.cc | 91 ++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index e2d98eb3139740..1398ea3f370982 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -901,7 +901,7 @@ void SnapshotBuilder::InitializeIsolateParams(const SnapshotData* data, const_cast(&(data->v8_snapshot_blob_data)); } -ExitCode SnapshotBuilder::Generate( +ExitCode BuildSnapshotWithoutCodeCache( SnapshotData* out, const std::vector& args, const std::vector& exec_args, @@ -923,8 +923,8 @@ ExitCode SnapshotBuilder::Generate( fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str()); return ExitCode::kBootstrapFailure; } - Isolate* isolate = setup->isolate(); + Isolate* isolate = setup->isolate(); { HandleScope scope(isolate); TryCatch bootstrapCatch(isolate); @@ -958,7 +958,77 @@ ExitCode SnapshotBuilder::Generate( } } - return CreateSnapshot(out, setup.get(), static_cast(snapshot_type)); + return SnapshotBuilder::CreateSnapshot( + out, setup.get(), static_cast(snapshot_type)); +} + +ExitCode BuildCodeCacheFromSnapshot(SnapshotData* out, + const std::vector& args, + const std::vector& exec_args) { + std::vector errors; + auto data_wrapper = out->AsEmbedderWrapper(); + auto setup = CommonEnvironmentSetup::CreateFromSnapshot( + per_process::v8_platform.Platform(), + &errors, + data_wrapper.get(), + args, + exec_args); + if (!setup) { + for (const std::string& err : errors) + fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str()); + return ExitCode::kBootstrapFailure; + } + + Isolate* isolate = setup->isolate(); + v8::Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + HandleScope handle_scope(isolate); + TryCatch bootstrapCatch(isolate); + + auto print_Exception = OnScopeLeave([&]() { + if (bootstrapCatch.HasCaught()) { + PrintCaughtException( + isolate, isolate->GetCurrentContext(), bootstrapCatch); + } + }); + + Environment* env = setup->env(); + // Regenerate all the code cache. + if (!env->builtin_loader()->CompileAllBuiltins(setup->context())) { + return ExitCode::kGenericUserError; + } + env->builtin_loader()->CopyCodeCache(&(out->code_cache)); + if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { + for (const auto& item : out->code_cache) { + std::string size_str = FormatSize(item.data.length); + per_process::Debug(DebugCategory::MKSNAPSHOT, + "Generated code cache for %d: %s\n", + item.id.c_str(), + size_str.c_str()); + } + } + return ExitCode::kNoFailure; +} + +ExitCode SnapshotBuilder::Generate( + SnapshotData* out, + const std::vector& args, + const std::vector& exec_args, + std::optional main_script) { + ExitCode code = + BuildSnapshotWithoutCodeCache(out, args, exec_args, main_script); + if (code != ExitCode::kNoFailure) { + return code; + } + +#ifdef NODE_USE_NODE_CODE_CACHE + // Deserialize the snapshot to recompile code cache. We need to do this in the + // second pass because V8 requires the code cache to be compiled with a + // finalized read-only space. + return BuildCodeCacheFromSnapshot(out, args, exec_args); +#else + return ExitCode::kNoFailure; +#endif } ExitCode SnapshotBuilder::CreateSnapshot(SnapshotData* out, @@ -1011,21 +1081,6 @@ ExitCode SnapshotBuilder::CreateSnapshot(SnapshotData* out, out->isolate_data_info = setup->isolate_data()->Serialize(creator); out->env_info = env->Serialize(creator); -#ifdef NODE_USE_NODE_CODE_CACHE - // Regenerate all the code cache. - if (!env->builtin_loader()->CompileAllBuiltins(main_context)) { - return ExitCode::kGenericUserError; - } - env->builtin_loader()->CopyCodeCache(&(out->code_cache)); - for (const auto& item : out->code_cache) { - std::string size_str = FormatSize(item.data.length); - per_process::Debug(DebugCategory::MKSNAPSHOT, - "Generated code cache for %d: %s\n", - item.id.c_str(), - size_str.c_str()); - } -#endif - ResetContextSettingsBeforeSnapshot(main_context); } From 577b8a9a2f333f0611a9159f3ac6fa1248806c7e Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 16 Aug 2023 19:16:38 +0200 Subject: [PATCH 2/2] fixup! bootstrap: build code cache from deserialized isolate Co-authored-by: Yagiz Nizipli --- src/node_snapshotable.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 1398ea3f370982..f388227891d303 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -974,7 +974,7 @@ ExitCode BuildCodeCacheFromSnapshot(SnapshotData* out, args, exec_args); if (!setup) { - for (const std::string& err : errors) + for (const auto& err : errors) fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str()); return ExitCode::kBootstrapFailure; }