diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2019-04-18 16:26:48 +0800 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2019-04-23 11:26:01 +0800 |
commit | d7016679509cd7f2d50612369509e8797d8157b0 (patch) | |
tree | e9d77bbe56e71b6c5ddb3b86547362f550ea2148 /tools/snapshot | |
parent | ffcc949f1cb72c19e4c7db6704ae02d0f7dac232 (diff) | |
download | android-node-v8-d7016679509cd7f2d50612369509e8797d8157b0.tar.gz android-node-v8-d7016679509cd7f2d50612369509e8797d8157b0.tar.bz2 android-node-v8-d7016679509cd7f2d50612369509e8797d8157b0.zip |
tools: implement node_mksnapshot
Implements a node_mksnapshot target that generates a snapshot blob
from a Node.js main instance's isolate, and serializes the data blob
with other additional data into a C++ file that can be embedded into
the Node.js binary.
PR-URL: https://github.com/nodejs/node/pull/27321
Refs: https://github.com/nodejs/node/issues/17058
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'tools/snapshot')
-rw-r--r-- | tools/snapshot/node_mksnapshot.cc | 51 | ||||
-rw-r--r-- | tools/snapshot/snapshot_builder.cc | 122 | ||||
-rw-r--r-- | tools/snapshot/snapshot_builder.h | 15 |
3 files changed, 188 insertions, 0 deletions
diff --git a/tools/snapshot/node_mksnapshot.cc b/tools/snapshot/node_mksnapshot.cc new file mode 100644 index 0000000000..c273ba20b6 --- /dev/null +++ b/tools/snapshot/node_mksnapshot.cc @@ -0,0 +1,51 @@ +#include <cstdio> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <vector> + +#include "libplatform/libplatform.h" +#include "node_internals.h" +#include "snapshot_builder.h" +#include "v8.h" + +#ifdef _WIN32 +#include <windows.h> + +int wmain(int argc, wchar_t* argv[]) { +#else // UNIX +int main(int argc, char* argv[]) { +#endif // _WIN32 + + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " <path/to/output.cc>\n"; + return 1; + } + + std::ofstream out; + out.open(argv[1], std::ios::out | std::ios::binary); + if (!out.is_open()) { + std::cerr << "Cannot open " << argv[1] << "\n"; + return 1; + } + + int node_argc = 1; + char argv0[] = "node"; + char* node_argv[] = {argv0, nullptr}; + + node::InitializationResult result = + node::InitializeOncePerProcess(node_argc, node_argv); + CHECK(!result.early_return); + CHECK_EQ(result.exit_code, 0); + + { + std::string snapshot = + node::SnapshotBuilder::Generate(result.args, result.exec_args); + out << snapshot; + out.close(); + } + + node::TearDownOncePerProcess(); + return 0; +} diff --git a/tools/snapshot/snapshot_builder.cc b/tools/snapshot/snapshot_builder.cc new file mode 100644 index 0000000000..d1ec17e302 --- /dev/null +++ b/tools/snapshot/snapshot_builder.cc @@ -0,0 +1,122 @@ +#include "snapshot_builder.h" +#include <iostream> +#include <sstream> +#include "env-inl.h" +#include "node_internals.h" +#include "node_main_instance.h" +#include "node_v8_platform-inl.h" + +namespace node { + +using v8::Context; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Locker; +using v8::SnapshotCreator; +using v8::StartupData; + +std::string FormatBlob(v8::StartupData* blob, + const std::vector<size_t>& isolate_data_indexes) { + std::stringstream ss; + size_t isolate_data_indexes_size = isolate_data_indexes.size(); + + ss << R"(#include <cstddef> +#include "node_main_instance.h" +#include "v8.h" + +// This file is generated by tools/snapshot. Do not edit. + +namespace node { + +static const uint8_t blob_data[] = { +)"; + + for (int i = 0; i < blob->raw_size; i++) { + uint8_t ch = blob->data[i]; + ss << std::to_string(ch) << ((i == blob->raw_size - 1) ? '\n' : ','); + } + + ss << R"(}; + +static const int blob_size = )" + << blob->raw_size << R"(; +static v8::StartupData blob = { + reinterpret_cast<const char*>(blob_data), + blob_size +}; +)"; + + ss << R"(v8::StartupData* +NodeMainInstance::GetEmbeddedSnapshotBlob() { + return &blob; +} + +static const size_t isolate_data_indexes_raw[] = { +)"; + for (size_t i = 0; i < isolate_data_indexes_size; i++) { + ss << std::to_string(isolate_data_indexes[i]) + << ((i == isolate_data_indexes_size - 1) ? '\n' : ','); + } + ss << "};\n\n"; + + ss << "static const size_t isolate_data_indexes_size = " + << isolate_data_indexes_size << R"(; + +NodeMainInstance::IndexArray isolate_data_indexes { + isolate_data_indexes_raw, + isolate_data_indexes_size +}; + +const NodeMainInstance::IndexArray* +NodeMainInstance::GetIsolateDataIndexes() { + return &isolate_data_indexes; +} +} // namespace node +)"; + + return ss.str(); +} + +std::string SnapshotBuilder::Generate( + const std::vector<std::string> args, + const std::vector<std::string> exec_args) { + // TODO(joyeecheung): collect external references and set it in + // params.external_references. + std::vector<intptr_t> external_references = { + reinterpret_cast<intptr_t>(nullptr)}; + Isolate* isolate = Isolate::Allocate(); + per_process::v8_platform.Platform()->RegisterIsolate(isolate, + uv_default_loop()); + NodeMainInstance* main_instance = nullptr; + std::string result; + + { + std::vector<size_t> isolate_data_indexes; + SnapshotCreator creator(isolate, external_references.data()); + { + main_instance = + NodeMainInstance::Create(isolate, + uv_default_loop(), + per_process::v8_platform.Platform(), + args, + exec_args); + HandleScope scope(isolate); + creator.SetDefaultContext(Context::New(isolate)); + isolate_data_indexes = main_instance->isolate_data()->Serialize(&creator); + } + + // Must be out of HandleScope + StartupData blob = + creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kClear); + // Must be done while the snapshot creator isolate is entered i.e. the + // creator is still alive. + main_instance->Dispose(); + result = FormatBlob(&blob, isolate_data_indexes); + delete blob.data; + } + + per_process::v8_platform.Platform()->UnregisterIsolate(isolate); + return result; +} +} // namespace node diff --git a/tools/snapshot/snapshot_builder.h b/tools/snapshot/snapshot_builder.h new file mode 100644 index 0000000000..2e587d078b --- /dev/null +++ b/tools/snapshot/snapshot_builder.h @@ -0,0 +1,15 @@ +#ifndef TOOLS_SNAPSHOT_SNAPSHOT_BUILDER_H_ +#define TOOLS_SNAPSHOT_SNAPSHOT_BUILDER_H_ + +#include <string> +#include <vector> + +namespace node { +class SnapshotBuilder { + public: + static std::string Generate(const std::vector<std::string> args, + const std::vector<std::string> exec_args); +}; +} // namespace node + +#endif // TOOLS_SNAPSHOT_SNAPSHOT_BUILDER_H_ |