GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_main_instance.cc Lines: 80 94 85.1 %
Date: 2019-05-05 22:32:45 Branches: 35 62 56.5 %

Line Branch Exec Source
1
#include "node_main_instance.h"
2
#include "node_internals.h"
3
#include "node_options-inl.h"
4
#include "node_v8_platform-inl.h"
5
6
namespace node {
7
8
using v8::Context;
9
using v8::HandleScope;
10
using v8::Isolate;
11
using v8::Local;
12
using v8::Locker;
13
using v8::SealHandleScope;
14
15
NodeMainInstance::NodeMainInstance(Isolate* isolate,
16
                                   uv_loop_t* event_loop,
17
                                   MultiIsolatePlatform* platform,
18
                                   const std::vector<std::string>& args,
19
                                   const std::vector<std::string>& exec_args)
20
    : args_(args),
21
      exec_args_(exec_args),
22
      array_buffer_allocator_(nullptr),
23
      isolate_(isolate),
24
      platform_(platform),
25
      isolate_data_(nullptr),
26
      owns_isolate_(false),
27
      deserialize_mode_(false) {
28
  isolate_data_.reset(new IsolateData(isolate_, event_loop, platform, nullptr));
29
  SetIsolateUpForNode(isolate_, IsolateSettingCategories::kMisc);
30
}
31
32
NodeMainInstance* NodeMainInstance::Create(
33
    Isolate* isolate,
34
    uv_loop_t* event_loop,
35
    MultiIsolatePlatform* platform,
36
    const std::vector<std::string>& args,
37
    const std::vector<std::string>& exec_args) {
38
  return new NodeMainInstance(isolate, event_loop, platform, args, exec_args);
39
}
40
41
4470
NodeMainInstance::NodeMainInstance(
42
    Isolate::CreateParams* params,
43
    uv_loop_t* event_loop,
44
    MultiIsolatePlatform* platform,
45
    const std::vector<std::string>& args,
46
    const std::vector<std::string>& exec_args,
47
    const std::vector<size_t>* per_isolate_data_indexes)
48
    : args_(args),
49
      exec_args_(exec_args),
50
      array_buffer_allocator_(ArrayBufferAllocator::Create()),
51
      isolate_(nullptr),
52
      platform_(platform),
53
      isolate_data_(nullptr),
54
4470
      owns_isolate_(true) {
55
4470
  params->array_buffer_allocator = array_buffer_allocator_.get();
56
4470
  isolate_ = Isolate::Allocate();
57
4470
  CHECK_NOT_NULL(isolate_);
58
  // Register the isolate on the platform before the isolate gets initialized,
59
  // so that the isolate can access the platform during initialization.
60
4470
  platform->RegisterIsolate(isolate_, event_loop);
61
4470
  SetIsolateCreateParamsForNode(params);
62
4470
  Isolate::Initialize(isolate_, *params);
63
64
4470
  deserialize_mode_ = per_isolate_data_indexes != nullptr;
65
  // If the indexes are not nullptr, we are not deserializing
66

4470
  CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
67
  isolate_data_.reset(new IsolateData(isolate_,
68
                                      event_loop,
69
                                      platform,
70
4470
                                      array_buffer_allocator_.get(),
71
4470
                                      per_isolate_data_indexes));
72
4470
  SetIsolateUpForNode(isolate_, IsolateSettingCategories::kMisc);
73
4470
  if (!deserialize_mode_) {
74
    // If in deserialize mode, delay until after the deserialization is
75
    // complete.
76
4470
    SetIsolateUpForNode(isolate_, IsolateSettingCategories::kErrorHandlers);
77
  }
78
4470
}
79
80
void NodeMainInstance::Dispose() {
81
  CHECK(!owns_isolate_);
82
  platform_->DrainTasks(isolate_);
83
  delete this;
84
}
85
86


8178
NodeMainInstance::~NodeMainInstance() {
87
4089
  if (!owns_isolate_) {
88
    return;
89
  }
90
4089
  isolate_->Dispose();
91
4089
  platform_->UnregisterIsolate(isolate_);
92
4089
}
93
94
4470
int NodeMainInstance::Run() {
95
4470
  Locker locker(isolate_);
96
8559
  Isolate::Scope isolate_scope(isolate_);
97
8559
  HandleScope handle_scope(isolate_);
98
99
4470
  int exit_code = 0;
100
8559
  std::unique_ptr<Environment> env = CreateMainEnvironment(&exit_code);
101
102
4470
  CHECK_NOT_NULL(env);
103
4470
  Context::Scope context_scope(env->context());
104
105
4470
  if (exit_code == 0) {
106
    {
107
4469
      AsyncCallbackScope callback_scope(env.get());
108
4469
      env->async_hooks()->push_async_ids(1, 0);
109
4469
      LoadEnvironment(env.get());
110
4233
      env->async_hooks()->pop_async_id(1);
111
    }
112
113
    {
114
4232
      SealHandleScope seal(isolate_);
115
      bool more;
116
      env->performance_state()->Mark(
117
4232
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
118
4106
      do {
119
4245
        uv_run(env->event_loop(), UV_RUN_DEFAULT);
120
121
4107
        per_process::v8_platform.DrainVMTasks(isolate_);
122
123
4107
        more = uv_loop_alive(env->event_loop());
124

4107
        if (more && !env->is_stopping()) continue;
125
126
4107
        env->RunBeforeExitCallbacks();
127
128
4107
        if (!uv_loop_alive(env->event_loop())) {
129
4107
          EmitBeforeExit(env.get());
130
        }
131
132
        // Emit `beforeExit` if the loop became alive either after emitting
133
        // event, or after running some callbacks.
134
4106
        more = uv_loop_alive(env->event_loop());
135

4106
      } while (more == true && !env->is_stopping());
136
      env->performance_state()->Mark(
137
4093
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
138
    }
139
140
4093
    env->set_trace_sync_io(false);
141
4093
    exit_code = EmitExit(env.get());
142
4088
    WaitForInspectorDisconnect(env.get());
143
  }
144
145
4089
  env->set_can_call_into_js(false);
146
4089
  env->stop_sub_worker_contexts();
147
4089
  uv_tty_reset_mode();
148
4089
  env->RunCleanup();
149
4089
  RunAtExit(env.get());
150
151
4089
  per_process::v8_platform.DrainVMTasks(isolate_);
152
4089
  per_process::v8_platform.CancelVMTasks(isolate_);
153
154
#if defined(LEAK_SANITIZER)
155
  __lsan_do_leak_check();
156
#endif
157
158
8178
  return exit_code;
159
}
160
161
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
162
// and the environment creation routine in workers somehow.
163
4470
std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
164
    int* exit_code) {
165
4470
  *exit_code = 0;  // Reset the exit code to 0
166
167
4470
  HandleScope handle_scope(isolate_);
168
169
  // TODO(addaleax): This should load a real per-Isolate option, currently
170
  // this is still effectively per-process.
171
4470
  if (isolate_data_->options()->track_heap_objects) {
172
1
    isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
173
  }
174
175
  Local<Context> context;
176
4470
  if (deserialize_mode_) {
177
    context =
178
        Context::FromSnapshot(isolate_, kNodeContextIndex).ToLocalChecked();
179
    SetIsolateUpForNode(isolate_, IsolateSettingCategories::kErrorHandlers);
180
  } else {
181
4470
    context = NewContext(isolate_);
182
  }
183
184
4470
  CHECK(!context.IsEmpty());
185
  Context::Scope context_scope(context);
186
187
  std::unique_ptr<Environment> env = std::make_unique<Environment>(
188
4470
      isolate_data_.get(),
189
      context,
190
      static_cast<Environment::Flags>(Environment::kIsMainThread |
191
                                      Environment::kOwnsProcessState |
192
8940
                                      Environment::kOwnsInspector));
193
4470
  env->InitializeLibuv(per_process::v8_is_profiling);
194
4470
  env->ProcessCliArgs(args_, exec_args_);
195
196
#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
197
4470
  CHECK(!env->inspector_agent()->IsListening());
198
  // Inspector agent can't fail to start, but if it was configured to listen
199
  // right away on the websocket port and fails to bind/etc, this will return
200
  // false.
201
8606
  env->inspector_agent()->Start(args_.size() > 1 ? args_[1].c_str() : "",
202
8940
                                env->options()->debug_options(),
203
                                env->inspector_host_port(),
204
22016
                                true);
205


4541
  if (env->options()->debug_options().inspector_enabled &&
206
71
      !env->inspector_agent()->IsListening()) {
207
1
    *exit_code = 12;  // Signal internal error.
208
1
    return env;
209
  }
210
#else
211
  // inspector_enabled can't be true if !HAVE_INSPECTOR or
212
  // !NODE_USE_V8_PLATFORM
213
  // - the option parser should not allow that.
214
  CHECK(!env->options()->debug_options().inspector_enabled);
215
#endif  // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
216
217
8938
  if (RunBootstrapping(env.get()).IsEmpty()) {
218
    *exit_code = 1;
219
  }
220
221
8939
  return env;
222
}
223
224
}  // namespace node