diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2021-05-26 19:42:00 +0300 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2021-06-10 09:17:49 +0300 |
commit | 30e8b5e2a2638d26939eb6cb00c1ffb77fdba6f7 (patch) | |
tree | e131e2ad4cc707355cbe4c40db7ff94d2a9a77c8 /src/node_snapshotable.cc | |
parent | f461158febdffe8eaa6468b1b716f2dbe40fd056 (diff) |
tools: refactor snapshot builder
This patch:
- Moves the snapshot building code to src/ so that we can reuse it
later when generating custom snapshots from an entry point accepted
by the node binary.
- Create a SnapshotData struct that incorporates all the data useful
for a snapshot blob, including both the V8 data and the Node.js
data.
PR-URL: https://github.com/nodejs/node/pull/38902
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Diffstat (limited to 'src/node_snapshotable.cc')
-rw-r--r-- | src/node_snapshotable.cc | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 216a0a9a725..1871cef443f 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -1,16 +1,181 @@ #include "node_snapshotable.h" +#include <iostream> +#include <sstream> #include "base_object-inl.h" #include "debug_utils-inl.h" +#include "env-inl.h" +#include "node_errors.h" +#include "node_external_reference.h" #include "node_file.h" +#include "node_internals.h" +#include "node_main_instance.h" #include "node_v8.h" +#include "node_v8_platform-inl.h" namespace node { +using v8::Context; +using v8::HandleScope; +using v8::Isolate; using v8::Local; using v8::Object; using v8::SnapshotCreator; using v8::StartupData; +using v8::TryCatch; +using v8::Value; + +template <typename T> +void WriteVector(std::ostringstream* ss, const T* vec, size_t size) { + for (size_t i = 0; i < size; i++) { + *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ','); + } +} + +std::string FormatBlob(SnapshotData* data) { + std::ostringstream ss; + + ss << R"(#include <cstddef> +#include "env.h" +#include "node_main_instance.h" +#include "v8.h" + +// This file is generated by tools/snapshot. Do not edit. + +namespace node { + +static const char blob_data[] = { +)"; + WriteVector(&ss, data->blob.data, data->blob.raw_size); + ss << R"(}; + +static const int blob_size = )" + << data->blob.raw_size << R"(; +static v8::StartupData blob = { blob_data, blob_size }; +)"; + + ss << R"(v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() { + return &blob; +} + +static const std::vector<size_t> isolate_data_indices { +)"; + WriteVector(&ss, + data->isolate_data_indices.data(), + data->isolate_data_indices.size()); + ss << R"(}; + +const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndices() { + return &isolate_data_indices; +} + +static const EnvSerializeInfo env_info )" + << data->env_info << R"(; + +const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() { + return &env_info; +} + +} // namespace node +)"; + + return ss.str(); +} + +void SnapshotBuilder::Generate(SnapshotData* out, + const std::vector<std::string> args, + const std::vector<std::string> exec_args) { + Isolate* isolate = Isolate::Allocate(); + isolate->SetCaptureStackTraceForUncaughtExceptions( + true, 10, v8::StackTrace::StackTraceOptions::kDetailed); + per_process::v8_platform.Platform()->RegisterIsolate(isolate, + uv_default_loop()); + std::unique_ptr<NodeMainInstance> main_instance; + std::string result; + + { + const std::vector<intptr_t>& external_references = + NodeMainInstance::CollectExternalReferences(); + SnapshotCreator creator(isolate, external_references.data()); + Environment* env; + { + main_instance = + NodeMainInstance::Create(isolate, + uv_default_loop(), + per_process::v8_platform.Platform(), + args, + exec_args); + + HandleScope scope(isolate); + creator.SetDefaultContext(Context::New(isolate)); + out->isolate_data_indices = + main_instance->isolate_data()->Serialize(&creator); + + // Run the per-context scripts + Local<Context> context; + { + TryCatch bootstrapCatch(isolate); + context = NewContext(isolate); + if (bootstrapCatch.HasCaught()) { + PrintCaughtException(isolate, context, bootstrapCatch); + abort(); + } + } + Context::Scope context_scope(context); + + // Create the environment + env = new Environment(main_instance->isolate_data(), + context, + args, + exec_args, + nullptr, + node::EnvironmentFlags::kDefaultFlags, + {}); + // Run scripts in lib/internal/bootstrap/ + { + TryCatch bootstrapCatch(isolate); + v8::MaybeLocal<Value> result = env->RunBootstrapping(); + if (bootstrapCatch.HasCaught()) { + PrintCaughtException(isolate, context, bootstrapCatch); + } + result.ToLocalChecked(); + } + + if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { + env->PrintAllBaseObjects(); + printf("Environment = %p\n", env); + } + + // Serialize the native states + out->env_info = env->Serialize(&creator); + // Serialize the context + size_t index = creator.AddContext( + context, {SerializeNodeContextInternalFields, env}); + CHECK_EQ(index, NodeMainInstance::kNodeContextIndex); + } + + // Must be out of HandleScope + out->blob = + creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kClear); + CHECK(out->blob.CanBeRehashed()); + // Must be done while the snapshot creator isolate is entered i.e. the + // creator is still alive. + FreeEnvironment(env); + main_instance->Dispose(); + } + + per_process::v8_platform.Platform()->UnregisterIsolate(isolate); +} + +std::string SnapshotBuilder::Generate( + const std::vector<std::string> args, + const std::vector<std::string> exec_args) { + SnapshotData data; + Generate(&data, args, exec_args); + std::string result = FormatBlob(&data); + delete[] data.blob.data; + return result; +} SnapshotableObject::SnapshotableObject(Environment* env, Local<Object> wrap, |