GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/api/environment.cc Lines: 89 154 57.8 %
Date: 2019-03-02 22:23:06 Branches: 35 75 46.7 %

Line Branch Exec Source
1
#include "env.h"
2
#include "node.h"
3
#include "node_context_data.h"
4
#include "node_errors.h"
5
#include "node_internals.h"
6
#include "node_native_module.h"
7
#include "node_platform.h"
8
#include "node_process.h"
9
#include "node_v8_platform-inl.h"
10
#include "uv.h"
11
12
#ifdef NODE_ENABLE_VTUNE_PROFILING
13
#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
14
#endif
15
16
namespace node {
17
using v8::Context;
18
using v8::Function;
19
using v8::HandleScope;
20
using v8::Isolate;
21
using v8::Local;
22
using v8::MaybeLocal;
23
using v8::Message;
24
using v8::MicrotasksPolicy;
25
using v8::ObjectTemplate;
26
using v8::String;
27
using v8::Value;
28
29
33
static bool AllowWasmCodeGenerationCallback(Local<Context> context,
30
                                            Local<String>) {
31
  Local<Value> wasm_code_gen =
32
66
      context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration);
33

99
  return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue();
34
}
35
36
32
static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
37
32
  HandleScope scope(isolate);
38
32
  Environment* env = Environment::GetCurrent(isolate);
39
32
  return env != nullptr &&
40

95
         (env->is_main_thread() || !env->is_stopping_worker()) &&
41

158
         env->should_abort_on_uncaught_toggle()[0] &&
42
66
         !env->inside_should_not_abort_on_uncaught_scope();
43
}
44
45
1317
static void OnMessage(Local<Message> message, Local<Value> error) {
46
1317
  Isolate* isolate = message->GetIsolate();
47
1317
  switch (message->ErrorLevel()) {
48
    case Isolate::MessageErrorLevel::kMessageWarning: {
49
1
      Environment* env = Environment::GetCurrent(isolate);
50
1
      if (!env) {
51
        break;
52
      }
53
2
      Utf8Value filename(isolate, message->GetScriptOrigin().ResourceName());
54
      // (filename):(line) (message)
55
2
      std::stringstream warning;
56
1
      warning << *filename;
57
1
      warning << ":";
58
3
      warning << message->GetLineNumber(env->context()).FromMaybe(-1);
59
1
      warning << " ";
60
3
      v8::String::Utf8Value msg(isolate, message->Get());
61
1
      warning << *msg;
62
1
      USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8"));
63
2
      break;
64
    }
65
    case Isolate::MessageErrorLevel::kMessageError:
66
1316
      FatalException(isolate, error, message);
67
1176
      break;
68
  }
69
1177
}
70
71
887384
void* ArrayBufferAllocator::Allocate(size_t size) {
72

887384
  if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
73
46349
    return UncheckedCalloc(size);
74
  else
75
841035
    return UncheckedMalloc(size);
76
}
77
78
DebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() {
79
  CHECK(allocations_.empty());
80
}
81
82
void* DebuggingArrayBufferAllocator::Allocate(size_t size) {
83
  Mutex::ScopedLock lock(mutex_);
84
  void* data = ArrayBufferAllocator::Allocate(size);
85
  RegisterPointerInternal(data, size);
86
  return data;
87
}
88
89
void* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) {
90
  Mutex::ScopedLock lock(mutex_);
91
  void* data = ArrayBufferAllocator::AllocateUninitialized(size);
92
  RegisterPointerInternal(data, size);
93
  return data;
94
}
95
96
void DebuggingArrayBufferAllocator::Free(void* data, size_t size) {
97
  Mutex::ScopedLock lock(mutex_);
98
  UnregisterPointerInternal(data, size);
99
  ArrayBufferAllocator::Free(data, size);
100
}
101
102
void* DebuggingArrayBufferAllocator::Reallocate(void* data,
103
                                                size_t old_size,
104
                                                size_t size) {
105
  Mutex::ScopedLock lock(mutex_);
106
  void* ret = ArrayBufferAllocator::Reallocate(data, old_size, size);
107
  if (ret == nullptr) {
108
    if (size == 0)  // i.e. equivalent to free().
109
      UnregisterPointerInternal(data, old_size);
110
    return nullptr;
111
  }
112
113
  if (data != nullptr) {
114
    auto it = allocations_.find(data);
115
    CHECK_NE(it, allocations_.end());
116
    allocations_.erase(it);
117
  }
118
119
  RegisterPointerInternal(ret, size);
120
  return ret;
121
}
122
123
void DebuggingArrayBufferAllocator::RegisterPointer(void* data, size_t size) {
124
  Mutex::ScopedLock lock(mutex_);
125
  RegisterPointerInternal(data, size);
126
}
127
128
void DebuggingArrayBufferAllocator::UnregisterPointer(void* data, size_t size) {
129
  Mutex::ScopedLock lock(mutex_);
130
  UnregisterPointerInternal(data, size);
131
}
132
133
void DebuggingArrayBufferAllocator::UnregisterPointerInternal(void* data,
134
                                                              size_t size) {
135
  if (data == nullptr) return;
136
  auto it = allocations_.find(data);
137
  CHECK_NE(it, allocations_.end());
138
  CHECK_EQ(it->second, size);
139
  allocations_.erase(it);
140
}
141
142
void DebuggingArrayBufferAllocator::RegisterPointerInternal(void* data,
143
                                                            size_t size) {
144
  if (data == nullptr) return;
145
  CHECK_EQ(allocations_.count(data), 0);
146
  allocations_[data] = size;
147
}
148
149
4424
ArrayBufferAllocator* CreateArrayBufferAllocator() {
150
4424
  if (per_process::cli_options->debug_arraybuffer_allocations)
151
    return new DebuggingArrayBufferAllocator();
152
  else
153
4424
    return new ArrayBufferAllocator();
154
}
155
156
4054
void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) {
157
4054
  delete allocator;
158
4054
}
159
160
4424
Isolate* NewIsolate(ArrayBufferAllocator* allocator, uv_loop_t* event_loop) {
161
4424
  Isolate::CreateParams params;
162
4424
  params.array_buffer_allocator = allocator;
163
164
4424
  double total_memory = uv_get_total_memory();
165
4424
  if (total_memory > 0) {
166
    // V8 defaults to 700MB or 1.4GB on 32 and 64 bit platforms respectively.
167
    // This default is based on browser use-cases. Tell V8 to configure the
168
    // heap based on the actual physical memory.
169
4424
    params.constraints.ConfigureDefaults(total_memory, 0);
170
  }
171
172
#ifdef NODE_ENABLE_VTUNE_PROFILING
173
  params.code_event_handler = vTune::GetVtuneCodeEventHandler();
174
#endif
175
176
4424
  Isolate* isolate = Isolate::Allocate();
177
4424
  if (isolate == nullptr) return nullptr;
178
179
  // Register the isolate on the platform before the isolate gets initialized,
180
  // so that the isolate can access the platform during initialization.
181
4424
  per_process::v8_platform.Platform()->RegisterIsolate(isolate, event_loop);
182
4424
  Isolate::Initialize(isolate, params);
183
184
  isolate->AddMessageListenerWithErrorLevel(
185
      OnMessage,
186
      Isolate::MessageErrorLevel::kMessageError |
187
4424
          Isolate::MessageErrorLevel::kMessageWarning);
188
4424
  isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException);
189
4424
  isolate->SetMicrotasksPolicy(MicrotasksPolicy::kExplicit);
190
4424
  isolate->SetFatalErrorHandler(OnFatalError);
191
4424
  isolate->SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback);
192
4424
  v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate);
193
194
4424
  return isolate;
195
}
196
197
4421
IsolateData* CreateIsolateData(Isolate* isolate,
198
                               uv_loop_t* loop,
199
                               MultiIsolatePlatform* platform,
200
                               ArrayBufferAllocator* allocator) {
201
4421
  return new IsolateData(isolate, loop, platform, allocator);
202
}
203
204
4052
void FreeIsolateData(IsolateData* isolate_data) {
205
4052
  delete isolate_data;
206
4052
}
207
208
Environment* CreateEnvironment(IsolateData* isolate_data,
209
                               Local<Context> context,
210
                               int argc,
211
                               const char* const* argv,
212
                               int exec_argc,
213
                               const char* const* exec_argv) {
214
  Isolate* isolate = context->GetIsolate();
215
  HandleScope handle_scope(isolate);
216
  Context::Scope context_scope(context);
217
  // TODO(addaleax): This is a much better place for parsing per-Environment
218
  // options than the global parse call.
219
  std::vector<std::string> args(argv, argv + argc);
220
  std::vector<std::string> exec_args(exec_argv, exec_argv + exec_argc);
221
  // TODO(addaleax): Provide more sensible flags, in an embedder-accessible way.
222
  Environment* env = new Environment(
223
      isolate_data,
224
      context,
225
      static_cast<Environment::Flags>(Environment::kIsMainThread |
226
                                      Environment::kOwnsProcessState |
227
                                      Environment::kOwnsInspector));
228
  env->Start(per_process::v8_is_profiling);
229
  env->ProcessCliArgs(args, exec_args);
230
  return env;
231
}
232
233
173
void FreeEnvironment(Environment* env) {
234
173
  env->RunCleanup();
235
173
  delete env;
236
173
}
237
238
Environment* GetCurrentEnvironment(Local<Context> context) {
239
  return Environment::GetCurrent(context);
240
}
241
242
MultiIsolatePlatform* GetMainThreadMultiIsolatePlatform() {
243
  return per_process::v8_platform.Platform();
244
}
245
246
MultiIsolatePlatform* CreatePlatform(
247
    int thread_pool_size,
248
    node::tracing::TracingController* tracing_controller) {
249
  return new NodePlatform(thread_pool_size, tracing_controller);
250
}
251
252
4248
MultiIsolatePlatform* InitializeV8Platform(int thread_pool_size) {
253
4248
  per_process::v8_platform.Initialize(thread_pool_size);
254
4248
  return per_process::v8_platform.Platform();
255
}
256
257
void FreePlatform(MultiIsolatePlatform* platform) {
258
  delete platform;
259
}
260
261
8987
Local<Context> NewContext(Isolate* isolate,
262
                          Local<ObjectTemplate> object_template) {
263
17974
  auto context = Context::New(isolate, nullptr, object_template);
264
8987
  if (context.IsEmpty()) return context;
265
8987
  HandleScope handle_scope(isolate);
266
267
  context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration,
268
8987
                           True(isolate));
269
270
  {
271
    // Run lib/internal/bootstrap/context.js
272
    Context::Scope context_scope(context);
273
274
    std::vector<Local<String>> parameters = {
275
17971
        FIXED_ONE_BYTE_STRING(isolate, "global")};
276
26961
    Local<Value> arguments[] = {context->Global()};
277
    MaybeLocal<Function> maybe_fn =
278
        per_process::native_module_loader.LookupAndCompile(
279
8987
            context, "internal/bootstrap/context", &parameters, nullptr);
280
8987
    if (maybe_fn.IsEmpty()) {
281
      return Local<Context>();
282
    }
283
8987
    Local<Function> fn = maybe_fn.ToLocalChecked();
284
    MaybeLocal<Value> result =
285
17974
        fn->Call(context, Undefined(isolate), arraysize(arguments), arguments);
286
    // Execution failed during context creation.
287
    // TODO(joyeecheung): deprecate this signature and return a MaybeLocal.
288
8987
    if (result.IsEmpty()) {
289
3
      return Local<Context>();
290
8984
    }
291
  }
292
293
8984
  return context;
294
}
295
296
8
uv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
297
8
  HandleScope handle_scope(isolate);
298
8
  Local<Context> context = isolate->GetCurrentContext();
299
8
  if (context.IsEmpty()) return nullptr;
300
8
  Environment* env = Environment::GetCurrent(context);
301
8
  if (env == nullptr) return nullptr;
302
8
  return env->event_loop();
303
}
304
305
}  // namespace node