GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../tools/snapshot/snapshot_builder.cc Lines: 54 75 72.0 %
Date: 2021-05-26 04:16:18 Branches: 15 26 57.7 %

Line Branch Exec Source
1
#include "snapshot_builder.h"
2
#include <iostream>
3
#include <sstream>
4
#include "debug_utils-inl.h"
5
#include "env-inl.h"
6
#include "node_external_reference.h"
7
#include "node_internals.h"
8
#include "node_main_instance.h"
9
#include "node_snapshotable.h"
10
#include "node_v8_platform-inl.h"
11
12
namespace node {
13
14
using v8::Context;
15
using v8::HandleScope;
16
using v8::Isolate;
17
using v8::Local;
18
using v8::Object;
19
using v8::SnapshotCreator;
20
using v8::StartupData;
21
using v8::String;
22
using v8::TryCatch;
23
using v8::Value;
24
25
template <typename T>
26
16
void WriteVector(std::stringstream* ss, const T* vec, size_t size) {
27

3882738
  for (size_t i = 0; i < size; i++) {
28

3882722
    *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ',');
29
  }
30
16
}
31
32
8
std::string FormatBlob(StartupData* blob,
33
                       const std::vector<size_t>& isolate_data_indexes,
34
                       const EnvSerializeInfo& env_info) {
35
16
  std::stringstream ss;
36
37
  ss << R"(#include <cstddef>
38
#include "env.h"
39
#include "node_main_instance.h"
40
#include "v8.h"
41
42
// This file is generated by tools/snapshot. Do not edit.
43
44
namespace node {
45
46
static const char blob_data[] = {
47
8
)";
48
8
  WriteVector(&ss, blob->data, blob->raw_size);
49
8
  ss << R"(};
50
51
static const int blob_size = )"
52
16
     << blob->raw_size << R"(;
53
static v8::StartupData blob = { blob_data, blob_size };
54
8
)";
55
56
  ss << R"(v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() {
57
  return &blob;
58
}
59
60
static const std::vector<size_t> isolate_data_indexes {
61
8
)";
62
8
  WriteVector(&ss, isolate_data_indexes.data(), isolate_data_indexes.size());
63
8
  ss << R"(};
64
65
const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndexes() {
66
  return &isolate_data_indexes;
67
}
68
69
static const EnvSerializeInfo env_info )"
70
8
     << env_info << R"(;
71
72
const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() {
73
  return &env_info;
74
}
75
76
}  // namespace node
77
8
)";
78
79
16
  return ss.str();
80
}
81
82
8
std::string SnapshotBuilder::Generate(
83
    const std::vector<std::string> args,
84
    const std::vector<std::string> exec_args) {
85
8
  Isolate* isolate = Isolate::Allocate();
86
  isolate->SetCaptureStackTraceForUncaughtExceptions(
87
    true,
88
    10,
89
8
    v8::StackTrace::StackTraceOptions::kDetailed);
90
16
  per_process::v8_platform.Platform()->RegisterIsolate(isolate,
91
16
                                                       uv_default_loop());
92
16
  std::unique_ptr<NodeMainInstance> main_instance;
93
8
  std::string result;
94
95
  {
96
16
    std::vector<size_t> isolate_data_indexes;
97
16
    EnvSerializeInfo env_info;
98
99
    const std::vector<intptr_t>& external_references =
100
8
        NodeMainInstance::CollectExternalReferences();
101
16
    SnapshotCreator creator(isolate, external_references.data());
102
    Environment* env;
103
    {
104
      main_instance =
105
16
          NodeMainInstance::Create(isolate,
106
                                   uv_default_loop(),
107
8
                                   per_process::v8_platform.Platform(),
108
                                   args,
109
8
                                   exec_args);
110
111
16
      HandleScope scope(isolate);
112
16
      creator.SetDefaultContext(Context::New(isolate));
113
8
      isolate_data_indexes = main_instance->isolate_data()->Serialize(&creator);
114
115
16
      TryCatch bootstrapCatch(isolate);
116
8
      Local<Context> context = NewContext(isolate);
117
8
      if (bootstrapCatch.HasCaught()) {
118
        Local<Object> obj = bootstrapCatch.Exception()->ToObject(context)
119
            .ToLocalChecked();
120
        Local<Value> stack = obj->Get(
121
            context,
122
            FIXED_ONE_BYTE_STRING(isolate, "stack")).ToLocalChecked();
123
        if (stack->IsUndefined()) {
124
          Local<String> str = obj->Get(
125
              context,
126
              FIXED_ONE_BYTE_STRING(isolate, "name"))
127
            .ToLocalChecked()->ToString(context).ToLocalChecked();
128
          str = String::Concat(
129
            isolate,
130
            str,
131
            FIXED_ONE_BYTE_STRING(isolate, ": "));
132
          stack = String::Concat(
133
            isolate,
134
            str,
135
            obj->Get(
136
                context,
137
                FIXED_ONE_BYTE_STRING(isolate, "message"))
138
              .ToLocalChecked()->ToString(context).ToLocalChecked());
139
        }
140
        v8::String::Utf8Value utf8_value(isolate, stack);
141
        if (*utf8_value != nullptr) {
142
          std::string out(*utf8_value, utf8_value.length());
143
          fprintf(stderr, "Had Exception: %s\n", out.c_str());
144
        } else {
145
          fprintf(stderr, "Unknown JS Exception\n");
146
        }
147
        abort();
148
      }
149
      Context::Scope context_scope(context);
150
151
16
      env = new Environment(main_instance->isolate_data(),
152
                            context,
153
                            args,
154
                            exec_args,
155
                            nullptr,
156
                            node::EnvironmentFlags::kDefaultFlags,
157
16
                            {});
158
16
      env->RunBootstrapping().ToLocalChecked();
159
8
      if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) {
160
        env->PrintAllBaseObjects();
161
        printf("Environment = %p\n", env);
162
      }
163
8
      env_info = env->Serialize(&creator);
164
16
      size_t index = creator.AddContext(
165
8
          context, {SerializeNodeContextInternalFields, env});
166
8
      CHECK_EQ(index, NodeMainInstance::kNodeContextIndex);
167
    }
168
169
    // Must be out of HandleScope
170
    StartupData blob =
171
8
        creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kClear);
172
8
    CHECK(blob.CanBeRehashed());
173
    // Must be done while the snapshot creator isolate is entered i.e. the
174
    // creator is still alive.
175
8
    FreeEnvironment(env);
176
8
    main_instance->Dispose();
177
8
    result = FormatBlob(&blob, isolate_data_indexes, env_info);
178
8
    delete[] blob.data;
179
  }
180
181
8
  per_process::v8_platform.Platform()->UnregisterIsolate(isolate);
182
16
  return result;
183
}
184

24
}  // namespace node