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
path: root/src
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2021-05-26 19:42:00 +0300
committerMichaƫl Zasso <targos@protonmail.com>2021-06-11 08:24:59 +0300
commit9bf9ddb49044762e75ab013f89830d9f65ed8d3f (patch)
tree593cf4fdf21117c420ad18f2660429cb5cd4e5cb /src
parent711916a271f63299bba9f6289ac79a23e0d8ce38 (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')
-rw-r--r--src/env.h7
-rw-r--r--src/node.cc6
-rw-r--r--src/node_main_instance.h2
-rw-r--r--src/node_snapshot_stub.cc2
-rw-r--r--src/node_snapshotable.cc165
-rw-r--r--src/node_snapshotable.h10
6 files changed, 187 insertions, 5 deletions
diff --git a/src/env.h b/src/env.h
index 4a50227ee8d..a3944eab90a 100644
--- a/src/env.h
+++ b/src/env.h
@@ -955,6 +955,13 @@ struct EnvSerializeInfo {
friend std::ostream& operator<<(std::ostream& o, const EnvSerializeInfo& i);
};
+struct SnapshotData {
+ SnapshotData() { blob.data = nullptr; }
+ v8::StartupData blob;
+ std::vector<size_t> isolate_data_indices;
+ EnvSerializeInfo env_info;
+};
+
class Environment : public MemoryRetainer {
public:
Environment(const Environment&) = delete;
diff --git a/src/node.cc b/src/node.cc
index 3ca2a05d8b8..75ad5689fca 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1130,7 +1130,7 @@ int Start(int argc, char** argv) {
{
Isolate::CreateParams params;
- const std::vector<size_t>* indexes = nullptr;
+ const std::vector<size_t>* indices = nullptr;
const EnvSerializeInfo* env_info = nullptr;
bool force_no_snapshot =
per_process::cli_options->per_isolate->no_node_snapshot;
@@ -1138,7 +1138,7 @@ int Start(int argc, char** argv) {
v8::StartupData* blob = NodeMainInstance::GetEmbeddedSnapshotBlob();
if (blob != nullptr) {
params.snapshot_blob = blob;
- indexes = NodeMainInstance::GetIsolateDataIndexes();
+ indices = NodeMainInstance::GetIsolateDataIndices();
env_info = NodeMainInstance::GetEnvSerializeInfo();
}
}
@@ -1149,7 +1149,7 @@ int Start(int argc, char** argv) {
per_process::v8_platform.Platform(),
result.args,
result.exec_args,
- indexes);
+ indices);
result.exit_code = main_instance.Run(env_info);
}
diff --git a/src/node_main_instance.h b/src/node_main_instance.h
index 6e38e95c266..75d4b7eac50 100644
--- a/src/node_main_instance.h
+++ b/src/node_main_instance.h
@@ -67,7 +67,7 @@ class NodeMainInstance {
// If nullptr is returned, the binary is not built with embedded
// snapshot.
- static const std::vector<size_t>* GetIsolateDataIndexes();
+ static const std::vector<size_t>* GetIsolateDataIndices();
static v8::StartupData* GetEmbeddedSnapshotBlob();
static const EnvSerializeInfo* GetEnvSerializeInfo();
static const std::vector<intptr_t>& CollectExternalReferences();
diff --git a/src/node_snapshot_stub.cc b/src/node_snapshot_stub.cc
index 9d7b085994b..7c13d4e8c60 100644
--- a/src/node_snapshot_stub.cc
+++ b/src/node_snapshot_stub.cc
@@ -10,7 +10,7 @@ v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() {
return nullptr;
}
-const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndexes() {
+const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndices() {
return nullptr;
}
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,
diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h
index c3b82c6edc7..38da68f6d28 100644
--- a/src/node_snapshotable.h
+++ b/src/node_snapshotable.h
@@ -11,6 +11,7 @@ namespace node {
class Environment;
struct EnvSerializeInfo;
+struct SnapshotData;
#define SERIALIZABLE_OBJECT_TYPES(V) \
V(fs_binding_data, fs::BindingData) \
@@ -119,6 +120,15 @@ void SerializeBindingData(Environment* env,
EnvSerializeInfo* info);
bool IsSnapshotableType(FastStringKey key);
+
+class SnapshotBuilder {
+ public:
+ static std::string Generate(const std::vector<std::string> args,
+ const std::vector<std::string> exec_args);
+ static void Generate(SnapshotData* out,
+ const std::vector<std::string> args,
+ const std::vector<std::string> exec_args);
+};
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS