• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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