1 #include "snapshot_builder.h"
2 #include <iostream>
3 #include <sstream>
4 #include "node_internals.h"
5 #include "node_main_instance.h"
6 #include "node_v8_platform-inl.h"
7
8 namespace node {
9
10 using v8::Context;
11 using v8::HandleScope;
12 using v8::Isolate;
13 using v8::SnapshotCreator;
14 using v8::StartupData;
15
16 template <typename T>
WriteVector(std::stringstream * ss,const T * vec,size_t size)17 void WriteVector(std::stringstream* ss, const T* vec, size_t size) {
18 for (size_t i = 0; i < size; i++) {
19 *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ',');
20 }
21 }
22
FormatBlob(v8::StartupData * blob,const std::vector<size_t> & isolate_data_indexes)23 std::string FormatBlob(v8::StartupData* blob,
24 const std::vector<size_t>& isolate_data_indexes) {
25 std::stringstream ss;
26
27 ss << R"(#include <cstddef>
28 #include "node_main_instance.h"
29 #include "v8.h"
30
31 // This file is generated by tools/snapshot. Do not edit.
32
33 namespace node {
34
35 static const char blob_data[] = {
36 )";
37 WriteVector(&ss, blob->data, blob->raw_size);
38 ss << R"(};
39
40 static const int blob_size = )"
41 << blob->raw_size << R"(;
42 static v8::StartupData blob = { blob_data, blob_size };
43 )";
44
45 ss << R"(v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() {
46 return &blob;
47 }
48
49 static const std::vector<size_t> isolate_data_indexes {
50 )";
51 WriteVector(&ss, isolate_data_indexes.data(), isolate_data_indexes.size());
52 ss << R"(};
53
54 const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndexes() {
55 return &isolate_data_indexes;
56 }
57 } // namespace node
58 )";
59
60 return ss.str();
61 }
62
Generate(const std::vector<std::string> args,const std::vector<std::string> exec_args)63 std::string SnapshotBuilder::Generate(
64 const std::vector<std::string> args,
65 const std::vector<std::string> exec_args) {
66 // TODO(joyeecheung): collect external references and set it in
67 // params.external_references.
68 std::vector<intptr_t> external_references = {
69 reinterpret_cast<intptr_t>(nullptr)};
70 Isolate* isolate = Isolate::Allocate();
71 per_process::v8_platform.Platform()->RegisterIsolate(isolate,
72 uv_default_loop());
73 std::unique_ptr<NodeMainInstance> main_instance;
74 std::string result;
75
76 {
77 std::vector<size_t> isolate_data_indexes;
78 SnapshotCreator creator(isolate, external_references.data());
79 {
80 main_instance =
81 NodeMainInstance::Create(isolate,
82 uv_default_loop(),
83 per_process::v8_platform.Platform(),
84 args,
85 exec_args);
86 HandleScope scope(isolate);
87 creator.SetDefaultContext(Context::New(isolate));
88 isolate_data_indexes = main_instance->isolate_data()->Serialize(&creator);
89
90 size_t index = creator.AddContext(NewContext(isolate));
91 CHECK_EQ(index, NodeMainInstance::kNodeContextIndex);
92 }
93
94 // Must be out of HandleScope
95 StartupData blob =
96 creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kClear);
97 CHECK(blob.CanBeRehashed());
98 // Must be done while the snapshot creator isolate is entered i.e. the
99 // creator is still alive.
100 main_instance->Dispose();
101 result = FormatBlob(&blob, isolate_data_indexes);
102 delete[] blob.data;
103 }
104
105 per_process::v8_platform.Platform()->UnregisterIsolate(isolate);
106 return result;
107 }
108 } // namespace node
109