summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--node.gyp42
-rw-r--r--tools/snapshot/node_mksnapshot.cc51
-rw-r--r--tools/snapshot/snapshot_builder.cc122
-rw-r--r--tools/snapshot/snapshot_builder.h15
5 files changed, 231 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index d04aac3515..d41bf1601f 100644
--- a/Makefile
+++ b/Makefile
@@ -1226,6 +1226,8 @@ LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \
tools/icu/*.h \
tools/code_cache/*.cc \
tools/code_cache/*.h \
+ tools/snapshot/*.cc \
+ tools/snapshot/*.h \
))
# Code blocks don't have newline at the end,
diff --git a/node.gyp b/node.gyp
index 7f534d8208..8019a16599 100644
--- a/node.gyp
+++ b/node.gyp
@@ -1156,7 +1156,47 @@
}],
],
}, # mkcodecache
- ], # end targets
+ {
+ 'target_name': 'node_mksnapshot',
+ 'type': 'executable',
+
+ 'dependencies': [
+ '<(node_lib_target_name)',
+ 'deps/histogram/histogram.gyp:histogram',
+ ],
+
+ 'includes': [
+ 'node.gypi'
+ ],
+
+ 'include_dirs': [
+ 'src',
+ 'tools/msvs/genfiles',
+ 'deps/v8/include',
+ 'deps/cares/include',
+ 'deps/uv/include',
+ ],
+
+ 'defines': [ 'NODE_WANT_INTERNALS=1' ],
+
+ 'sources': [
+ 'src/node_code_cache_stub.cc',
+ 'tools/snapshot/node_mksnapshot.cc',
+ 'tools/snapshot/snapshot_builder.cc',
+ 'tools/snapshot/snapshot_builder.h',
+ ],
+
+ 'conditions': [
+ [ 'node_report=="true"', {
+ 'conditions': [
+ ['OS=="win"', {
+ 'libraries': [ 'Ws2_32' ],
+ }],
+ ],
+ }],
+ ],
+ }, # node_mksnapshot
+ ], # end targets
'conditions': [
['OS=="aix" and node_shared=="true"', {
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_