|
1 | 1 |
|
2 | 2 | #include "node_snapshotable.h"
|
| 3 | +#include <iostream> |
| 4 | +#include <sstream> |
3 | 5 | #include "base_object-inl.h"
|
4 | 6 | #include "debug_utils-inl.h"
|
| 7 | +#include "env-inl.h" |
| 8 | +#include "node_errors.h" |
| 9 | +#include "node_external_reference.h" |
5 | 10 | #include "node_file.h"
|
| 11 | +#include "node_internals.h" |
| 12 | +#include "node_main_instance.h" |
6 | 13 | #include "node_v8.h"
|
| 14 | +#include "node_v8_platform-inl.h" |
7 | 15 |
|
8 | 16 | namespace node {
|
9 | 17 |
|
| 18 | +using v8::Context; |
| 19 | +using v8::HandleScope; |
| 20 | +using v8::Isolate; |
10 | 21 | using v8::Local;
|
11 | 22 | using v8::Object;
|
12 | 23 | using v8::SnapshotCreator;
|
13 | 24 | using v8::StartupData;
|
| 25 | +using v8::TryCatch; |
| 26 | +using v8::Value; |
| 27 | + |
| 28 | +template <typename T> |
| 29 | +void WriteVector(std::ostringstream* ss, const T* vec, size_t size) { |
| 30 | + for (size_t i = 0; i < size; i++) { |
| 31 | + *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ','); |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +std::string FormatBlob(SnapshotData* data) { |
| 36 | + std::ostringstream ss; |
| 37 | + |
| 38 | + ss << R"(#include <cstddef> |
| 39 | +#include "env.h" |
| 40 | +#include "node_main_instance.h" |
| 41 | +#include "v8.h" |
| 42 | +
|
| 43 | +// This file is generated by tools/snapshot. Do not edit. |
| 44 | +
|
| 45 | +namespace node { |
| 46 | +
|
| 47 | +static const char blob_data[] = { |
| 48 | +)"; |
| 49 | + WriteVector(&ss, data->blob.data, data->blob.raw_size); |
| 50 | + ss << R"(}; |
| 51 | +
|
| 52 | +static const int blob_size = )" |
| 53 | + << data->blob.raw_size << R"(; |
| 54 | +static v8::StartupData blob = { blob_data, blob_size }; |
| 55 | +)"; |
| 56 | + |
| 57 | + ss << R"(v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() { |
| 58 | + return &blob; |
| 59 | +} |
| 60 | +
|
| 61 | +static const std::vector<size_t> isolate_data_indices { |
| 62 | +)"; |
| 63 | + WriteVector(&ss, |
| 64 | + data->isolate_data_indices.data(), |
| 65 | + data->isolate_data_indices.size()); |
| 66 | + ss << R"(}; |
| 67 | +
|
| 68 | +const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndices() { |
| 69 | + return &isolate_data_indices; |
| 70 | +} |
| 71 | +
|
| 72 | +static const EnvSerializeInfo env_info )" |
| 73 | + << data->env_info << R"(; |
| 74 | +
|
| 75 | +const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() { |
| 76 | + return &env_info; |
| 77 | +} |
| 78 | +
|
| 79 | +} // namespace node |
| 80 | +)"; |
| 81 | + |
| 82 | + return ss.str(); |
| 83 | +} |
| 84 | + |
| 85 | +void SnapshotBuilder::Generate(SnapshotData* out, |
| 86 | + const std::vector<std::string> args, |
| 87 | + const std::vector<std::string> exec_args) { |
| 88 | + Isolate* isolate = Isolate::Allocate(); |
| 89 | + isolate->SetCaptureStackTraceForUncaughtExceptions( |
| 90 | + true, 10, v8::StackTrace::StackTraceOptions::kDetailed); |
| 91 | + per_process::v8_platform.Platform()->RegisterIsolate(isolate, |
| 92 | + uv_default_loop()); |
| 93 | + std::unique_ptr<NodeMainInstance> main_instance; |
| 94 | + std::string result; |
| 95 | + |
| 96 | + { |
| 97 | + const std::vector<intptr_t>& external_references = |
| 98 | + NodeMainInstance::CollectExternalReferences(); |
| 99 | + SnapshotCreator creator(isolate, external_references.data()); |
| 100 | + Environment* env; |
| 101 | + { |
| 102 | + main_instance = |
| 103 | + NodeMainInstance::Create(isolate, |
| 104 | + uv_default_loop(), |
| 105 | + per_process::v8_platform.Platform(), |
| 106 | + args, |
| 107 | + exec_args); |
| 108 | + |
| 109 | + HandleScope scope(isolate); |
| 110 | + creator.SetDefaultContext(Context::New(isolate)); |
| 111 | + out->isolate_data_indices = |
| 112 | + main_instance->isolate_data()->Serialize(&creator); |
| 113 | + |
| 114 | + // Run the per-context scripts |
| 115 | + Local<Context> context; |
| 116 | + { |
| 117 | + TryCatch bootstrapCatch(isolate); |
| 118 | + context = NewContext(isolate); |
| 119 | + if (bootstrapCatch.HasCaught()) { |
| 120 | + PrintCaughtException(isolate, context, bootstrapCatch); |
| 121 | + abort(); |
| 122 | + } |
| 123 | + } |
| 124 | + Context::Scope context_scope(context); |
| 125 | + |
| 126 | + // Create the environment |
| 127 | + env = new Environment(main_instance->isolate_data(), |
| 128 | + context, |
| 129 | + args, |
| 130 | + exec_args, |
| 131 | + nullptr, |
| 132 | + node::EnvironmentFlags::kDefaultFlags, |
| 133 | + {}); |
| 134 | + // Run scripts in lib/internal/bootstrap/ |
| 135 | + { |
| 136 | + TryCatch bootstrapCatch(isolate); |
| 137 | + v8::MaybeLocal<Value> result = env->RunBootstrapping(); |
| 138 | + if (bootstrapCatch.HasCaught()) { |
| 139 | + PrintCaughtException(isolate, context, bootstrapCatch); |
| 140 | + } |
| 141 | + result.ToLocalChecked(); |
| 142 | + } |
| 143 | + |
| 144 | + if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { |
| 145 | + env->PrintAllBaseObjects(); |
| 146 | + printf("Environment = %p\n", env); |
| 147 | + } |
| 148 | + |
| 149 | + // Serialize the native states |
| 150 | + out->env_info = env->Serialize(&creator); |
| 151 | + // Serialize the context |
| 152 | + size_t index = creator.AddContext( |
| 153 | + context, {SerializeNodeContextInternalFields, env}); |
| 154 | + CHECK_EQ(index, NodeMainInstance::kNodeContextIndex); |
| 155 | + } |
| 156 | + |
| 157 | + // Must be out of HandleScope |
| 158 | + out->blob = |
| 159 | + creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kClear); |
| 160 | + CHECK(out->blob.CanBeRehashed()); |
| 161 | + // Must be done while the snapshot creator isolate is entered i.e. the |
| 162 | + // creator is still alive. |
| 163 | + FreeEnvironment(env); |
| 164 | + main_instance->Dispose(); |
| 165 | + } |
| 166 | + |
| 167 | + per_process::v8_platform.Platform()->UnregisterIsolate(isolate); |
| 168 | +} |
| 169 | + |
| 170 | +std::string SnapshotBuilder::Generate( |
| 171 | + const std::vector<std::string> args, |
| 172 | + const std::vector<std::string> exec_args) { |
| 173 | + SnapshotData data; |
| 174 | + Generate(&data, args, exec_args); |
| 175 | + std::string result = FormatBlob(&data); |
| 176 | + delete[] data.blob.data; |
| 177 | + return result; |
| 178 | +} |
14 | 179 |
|
15 | 180 | SnapshotableObject::SnapshotableObject(Environment* env,
|
16 | 181 | Local<Object> wrap,
|
|
0 commit comments