Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2021-05-26 19:42:00 +0300
committerJoyee Cheung <joyeec9h3@gmail.com>2021-06-10 09:17:49 +0300
commit30e8b5e2a2638d26939eb6cb00c1ffb77fdba6f7 (patch)
treee131e2ad4cc707355cbe4c40db7ff94d2a9a77c8 /src/node_snapshotable.cc
parentf461158febdffe8eaa6468b1b716f2dbe40fd056 (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.cc165
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,