GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/env.cc Lines: 500 528 94.7 %
Date: 2020-05-27 22:15:15 Branches: 445 729 61.0 %

Line Branch Exec Source
1
#include "env.h"
2
3
#include "async_wrap.h"
4
#include "base_object-inl.h"
5
#include "debug_utils-inl.h"
6
#include "memory_tracker-inl.h"
7
#include "node_buffer.h"
8
#include "node_context_data.h"
9
#include "node_errors.h"
10
#include "node_internals.h"
11
#include "node_options-inl.h"
12
#include "node_process.h"
13
#include "node_v8_platform-inl.h"
14
#include "node_worker.h"
15
#include "req_wrap-inl.h"
16
#include "stream_base.h"
17
#include "tracing/agent.h"
18
#include "tracing/traced_value.h"
19
#include "util-inl.h"
20
#include "v8-profiler.h"
21
22
#include <algorithm>
23
#include <atomic>
24
#include <cstdio>
25
#include <memory>
26
27
namespace node {
28
29
using errors::TryCatchScope;
30
using v8::ArrayBuffer;
31
using v8::Boolean;
32
using v8::Context;
33
using v8::EmbedderGraph;
34
using v8::Function;
35
using v8::FunctionTemplate;
36
using v8::HandleScope;
37
using v8::Integer;
38
using v8::Isolate;
39
using v8::Local;
40
using v8::MaybeLocal;
41
using v8::NewStringType;
42
using v8::Number;
43
using v8::Object;
44
using v8::Private;
45
using v8::Script;
46
using v8::SnapshotCreator;
47
using v8::StackTrace;
48
using v8::String;
49
using v8::Symbol;
50
using v8::TracingController;
51
using v8::TryCatch;
52
using v8::Undefined;
53
using v8::Value;
54
using worker::Worker;
55
56
int const Environment::kNodeContextTag = 0x6e6f64;
57
void* const Environment::kNodeContextTagPtr = const_cast<void*>(
58
    static_cast<const void*>(&Environment::kNodeContextTag));
59
60
1
std::vector<size_t> IsolateData::Serialize(SnapshotCreator* creator) {
61
1
  Isolate* isolate = creator->GetIsolate();
62
1
  std::vector<size_t> indexes;
63
2
  HandleScope handle_scope(isolate);
64
  // XXX(joyeecheung): technically speaking, the indexes here should be
65
  // consecutive and we could just return a range instead of an array,
66
  // but that's not part of the V8 API contract so we use an array
67
  // just to be safe.
68
69
#define VP(PropertyName, StringValue) V(Private, PropertyName)
70
#define VY(PropertyName, StringValue) V(Symbol, PropertyName)
71
#define VS(PropertyName, StringValue) V(String, PropertyName)
72
#define V(TypeName, PropertyName)                                              \
73
  indexes.push_back(creator->AddData(PropertyName##_.Get(isolate)));
74
8
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
75
9
  PER_ISOLATE_SYMBOL_PROPERTIES(VY)
76
225
  PER_ISOLATE_STRING_PROPERTIES(VS)
77
#undef V
78
#undef VY
79
#undef VS
80
#undef VP
81
48
  for (size_t i = 0; i < AsyncWrap::PROVIDERS_LENGTH; i++)
82
94
    indexes.push_back(creator->AddData(async_wrap_provider(i)));
83
84
2
  return indexes;
85
}
86
87
4257
void IsolateData::DeserializeProperties(const std::vector<size_t>* indexes) {
88
4257
  size_t i = 0;
89
8514
  HandleScope handle_scope(isolate_);
90
91
#define VP(PropertyName, StringValue) V(Private, PropertyName)
92
#define VY(PropertyName, StringValue) V(Symbol, PropertyName)
93
#define VS(PropertyName, StringValue) V(String, PropertyName)
94
#define V(TypeName, PropertyName)                                              \
95
  do {                                                                         \
96
    MaybeLocal<TypeName> field =                                               \
97
        isolate_->GetDataFromSnapshotOnce<TypeName>((*indexes)[i++]);          \
98
    if (field.IsEmpty()) {                                                     \
99
      fprintf(stderr, "Failed to deserialize " #PropertyName "\n");            \
100
    }                                                                          \
101
    PropertyName##_.Set(isolate_, field.ToLocalChecked());                     \
102
  } while (0);
103



119196
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
104




136224
  PER_ISOLATE_SYMBOL_PROPERTIES(VY)
105
















































































































3814272
  PER_ISOLATE_STRING_PROPERTIES(VS)
106
#undef V
107
#undef VY
108
#undef VS
109
#undef VP
110
111
204336
  for (size_t j = 0; j < AsyncWrap::PROVIDERS_LENGTH; j++) {
112
    MaybeLocal<String> field =
113
400158
        isolate_->GetDataFromSnapshotOnce<String>((*indexes)[i++]);
114
200079
    if (field.IsEmpty()) {
115
      fprintf(stderr, "Failed to deserialize AsyncWrap provider %zu\n", j);
116
    }
117
200079
    async_wrap_providers_[j].Set(isolate_, field.ToLocalChecked());
118
  }
119
4257
}
120
121
353
void IsolateData::CreateProperties() {
122
  // Create string and private symbol properties as internalized one byte
123
  // strings after the platform is properly initialized.
124
  //
125
  // Internalized because it makes property lookups a little faster and
126
  // because the string is created in the old space straight away.  It's going
127
  // to end up in the old space sooner or later anyway but now it doesn't go
128
  // through v8::Eternal's new space handling first.
129
  //
130
  // One byte because our strings are ASCII and we can safely skip V8's UTF-8
131
  // decoding step.
132
133
706
  HandleScope handle_scope(isolate_);
134
135
#define V(PropertyName, StringValue)                                           \
136
  PropertyName##_.Set(                                                         \
137
      isolate_,                                                                \
138
      Private::New(isolate_,                                                   \
139
                   String::NewFromOneByte(                                     \
140
                       isolate_,                                               \
141
                       reinterpret_cast<const uint8_t*>(StringValue),          \
142
                       NewStringType::kInternalized,                           \
143
                       sizeof(StringValue) - 1)                                \
144
                       .ToLocalChecked()));
145
5295
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
146
#undef V
147
#define V(PropertyName, StringValue)                                           \
148
  PropertyName##_.Set(                                                         \
149
      isolate_,                                                                \
150
      Symbol::New(isolate_,                                                    \
151
                  String::NewFromOneByte(                                      \
152
                      isolate_,                                                \
153
                      reinterpret_cast<const uint8_t*>(StringValue),           \
154
                      NewStringType::kInternalized,                            \
155
                      sizeof(StringValue) - 1)                                 \
156
                      .ToLocalChecked()));
157
6001
  PER_ISOLATE_SYMBOL_PROPERTIES(V)
158
#undef V
159
#define V(PropertyName, StringValue)                                           \
160
  PropertyName##_.Set(                                                         \
161
      isolate_,                                                                \
162
      String::NewFromOneByte(isolate_,                                         \
163
                             reinterpret_cast<const uint8_t*>(StringValue),    \
164
                             NewStringType::kInternalized,                     \
165
                             sizeof(StringValue) - 1)                          \
166
          .ToLocalChecked());
167
158497
  PER_ISOLATE_STRING_PROPERTIES(V)
168
#undef V
169
170
  // Create all the provider strings that will be passed to JS. Place them in
171
  // an array so the array index matches the PROVIDER id offset. This way the
172
  // strings can be retrieved quickly.
173
#define V(Provider)                                                           \
174
  async_wrap_providers_[AsyncWrap::PROVIDER_ ## Provider].Set(                \
175
      isolate_,                                                               \
176
      String::NewFromOneByte(                                                 \
177
        isolate_,                                                             \
178
        reinterpret_cast<const uint8_t*>(#Provider),                          \
179
        NewStringType::kInternalized,                                         \
180
        sizeof(#Provider) - 1).ToLocalChecked());
181
33535
  NODE_ASYNC_PROVIDER_TYPES(V)
182
#undef V
183
353
}
184
185
4610
IsolateData::IsolateData(Isolate* isolate,
186
                         uv_loop_t* event_loop,
187
                         MultiIsolatePlatform* platform,
188
                         ArrayBufferAllocator* node_allocator,
189
4610
                         const std::vector<size_t>* indexes)
190
    : isolate_(isolate),
191
      event_loop_(event_loop),
192
4610
      allocator_(isolate->GetArrayBufferAllocator()),
193
9188
      node_allocator_(node_allocator == nullptr ? nullptr
194
4578
                                                : node_allocator->GetImpl()),
195
4610
      uses_node_allocator_(allocator_ == node_allocator_),
196
1120230
      platform_(platform) {
197
4610
  CHECK_NOT_NULL(allocator_);
198
199
9220
  options_.reset(
200
13830
      new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
201
202
4610
  if (indexes == nullptr) {
203
353
    CreateProperties();
204
  } else {
205
4257
    DeserializeProperties(indexes);
206
  }
207
4610
}
208
209
19
void IsolateData::MemoryInfo(MemoryTracker* tracker) const {
210
#define V(PropertyName, StringValue)                                           \
211
  tracker->TrackField(#PropertyName, PropertyName());
212
19
  PER_ISOLATE_SYMBOL_PROPERTIES(V)
213
#undef V
214
215
#define V(PropertyName, StringValue)                                           \
216
  tracker->TrackField(#PropertyName, PropertyName());
217
19
  PER_ISOLATE_STRING_PROPERTIES(V)
218
#undef V
219
220
19
  tracker->TrackField("async_wrap_providers", async_wrap_providers_);
221
222
19
  if (node_allocator_ != nullptr) {
223
    tracker->TrackFieldWithSize(
224
19
        "node_allocator", sizeof(*node_allocator_), "NodeArrayBufferAllocator");
225
  } else {
226
    tracker->TrackFieldWithSize(
227
        "allocator", sizeof(*allocator_), "v8::ArrayBuffer::Allocator");
228
  }
229
  tracker->TrackFieldWithSize(
230
19
      "platform", sizeof(*platform_), "MultiIsolatePlatform");
231
  // TODO(joyeecheung): implement MemoryRetainer in the option classes.
232
19
}
233
234
4264
void InitThreadLocalOnce() {
235
4264
  CHECK_EQ(0, uv_key_create(&Environment::thread_local_env));
236
4264
}
237
238
119
void TrackingTraceStateObserver::UpdateTraceCategoryState() {
239

119
  if (!env_->owns_process_state() || !env_->can_call_into_js()) {
240
    // Ideally, we’d have a consistent story that treats all threads/Environment
241
    // instances equally here. However, tracing is essentially global, and this
242
    // callback is called from whichever thread calls `StartTracing()` or
243
    // `StopTracing()`. The only way to do this in a threadsafe fashion
244
    // seems to be only tracking this from the main thread, and only allowing
245
    // these state modifications from the main thread.
246
68
    return;
247
  }
248
249
222
  bool async_hooks_enabled = (*(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
250
222
                                 TRACING_CATEGORY_NODE1(async_hooks)))) != 0;
251
252
111
  Isolate* isolate = env_->isolate();
253
170
  HandleScope handle_scope(isolate);
254
111
  Local<Function> cb = env_->trace_category_state_function();
255
111
  if (cb.IsEmpty())
256
52
    return;
257
118
  TryCatchScope try_catch(env_);
258
59
  try_catch.SetVerbose(true);
259
118
  Local<Value> args[] = {Boolean::New(isolate, async_hooks_enabled)};
260
177
  USE(cb->Call(env_->context(), Undefined(isolate), arraysize(args), args));
261
}
262
263
4594
void Environment::CreateProperties() {
264
9188
  HandleScope handle_scope(isolate_);
265
4594
  Local<Context> ctx = context();
266
267
  {
268
    Context::Scope context_scope(ctx);
269
4594
    Local<FunctionTemplate> templ = FunctionTemplate::New(isolate());
270
13782
    templ->InstanceTemplate()->SetInternalFieldCount(
271
4594
        BaseObject::kInternalFieldCount);
272
273
4594
    set_binding_data_ctor_template(templ);
274
  }
275
276
  // Store primordials setup by the per-context script in the environment.
277
  Local<Object> per_context_bindings =
278
9188
      GetPerContextExports(ctx).ToLocalChecked();
279
  Local<Value> primordials =
280
13782
      per_context_bindings->Get(ctx, primordials_string()).ToLocalChecked();
281
4594
  CHECK(primordials->IsObject());
282
4594
  set_primordials(primordials.As<Object>());
283
284
  Local<Object> process_object =
285
9187
      node::CreateProcessObject(this).FromMaybe(Local<Object>());
286
4593
  set_process_object(process_object);
287
4594
}
288
289
4594
std::string GetExecPath(const std::vector<std::string>& argv) {
290
  char exec_path_buf[2 * PATH_MAX];
291
4594
  size_t exec_path_len = sizeof(exec_path_buf);
292
4594
  std::string exec_path;
293
4594
  if (uv_exepath(exec_path_buf, &exec_path_len) == 0) {
294
4594
    exec_path = std::string(exec_path_buf, exec_path_len);
295
  } else {
296
    exec_path = argv[0];
297
  }
298
299
  // On OpenBSD process.execPath will be relative unless we
300
  // get the full path before process.execPath is used.
301
#if defined(__OpenBSD__)
302
  uv_fs_t req;
303
  req.ptr = nullptr;
304
  if (0 ==
305
      uv_fs_realpath(nullptr, &req, exec_path.c_str(), nullptr)) {
306
    CHECK_NOT_NULL(req.ptr);
307
    exec_path = std::string(static_cast<char*>(req.ptr));
308
  }
309
  uv_fs_req_cleanup(&req);
310
#endif
311
312
4594
  return exec_path;
313
}
314
315
4594
Environment::Environment(IsolateData* isolate_data,
316
                         Local<Context> context,
317
                         const std::vector<std::string>& args,
318
                         const std::vector<std::string>& exec_args,
319
                         EnvironmentFlags::Flags flags,
320
4594
                         ThreadId thread_id)
321
4594
    : isolate_(context->GetIsolate()),
322
      isolate_data_(isolate_data),
323
      immediate_info_(context->GetIsolate()),
324
      tick_info_(context->GetIsolate()),
325
4594
      timer_base_(uv_now(isolate_data->event_loop())),
326
      exec_argv_(exec_args),
327
      argv_(args),
328
      exec_path_(GetExecPath(args)),
329
4594
      should_abort_on_uncaught_toggle_(isolate_, 1),
330
4594
      stream_base_state_(isolate_, StreamBase::kNumStreamBaseStateFields),
331
      flags_(flags),
332
8887
      thread_id_(thread_id.id == static_cast<uint64_t>(-1) ?
333
4293
          AllocateEnvironmentThreadId().id : thread_id.id),
334
381302
      context_(context->GetIsolate(), context) {
335
  // We'll be creating new objects so make sure we've entered the context.
336
9188
  HandleScope handle_scope(isolate());
337
  Context::Scope context_scope(context);
338
339
  // Set some flags if only kDefaultFlags was passed. This can make API version
340
  // transitions easier for embedders.
341
4594
  if (flags_ & EnvironmentFlags::kDefaultFlags) {
342
8584
    flags_ = flags_ |
343
4292
        EnvironmentFlags::kOwnsProcessState |
344
        EnvironmentFlags::kOwnsInspector;
345
  }
346
347
4594
  set_env_vars(per_process::system_environment);
348
4594
  enabled_debug_list_.Parse(this);
349
350
  // We create new copies of the per-Environment option sets, so that it is
351
  // easier to modify them after Environment creation. The defaults are
352
  // part of the per-Isolate option set, for which in turn the defaults are
353
  // part of the per-process option set.
354
4594
  options_.reset(new EnvironmentOptions(*isolate_data->options()->per_env));
355
9188
  inspector_host_port_.reset(
356
13782
      new ExclusiveAccess<HostPort>(options_->debug_options().host_port));
357
358
#if HAVE_INSPECTOR
359
  // We can only create the inspector agent after having cloned the options.
360
4594
  inspector_agent_ = std::make_unique<inspector::Agent>(this);
361
#endif
362
363
4594
  AssignToContext(context, ContextInfo(""));
364
365
  static uv_once_t init_once = UV_ONCE_INIT;
366
4594
  uv_once(&init_once, InitThreadLocalOnce);
367
4594
  uv_key_set(&thread_local_env, this);
368
369
4594
  if (tracing::AgentWriterHandle* writer = GetTracingAgentWriter()) {
370
4594
    trace_state_observer_ = std::make_unique<TrackingTraceStateObserver>(this);
371
4594
    if (TracingController* tracing_controller = writer->GetTracingController())
372
4558
      tracing_controller->AddTraceStateObserver(trace_state_observer_.get());
373
  }
374
375
4594
  destroy_async_id_list_.reserve(512);
376
377
  performance_state_ =
378
4594
      std::make_unique<performance::PerformanceState>(isolate());
379
4594
  performance_state_->Mark(
380
4594
      performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT);
381
4594
  performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_NODE_START,
382
9188
                           per_process::node_start_time);
383
4594
  performance_state_->Mark(
384
      performance::NODE_PERFORMANCE_MILESTONE_V8_START,
385
9188
      performance::performance_v8_start);
386
387
9188
  if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
388
4594
          TRACING_CATEGORY_NODE1(environment)) != 0) {
389
16
    auto traced_value = tracing::TracedValue::Create();
390
8
    traced_value->BeginArray("args");
391
8
    for (const std::string& arg : args) traced_value->AppendString(arg);
392
8
    traced_value->EndArray();
393
8
    traced_value->BeginArray("exec_args");
394
8
    for (const std::string& arg : exec_args) traced_value->AppendString(arg);
395
8
    traced_value->EndArray();
396

16
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE1(environment),
397
                                      "Environment",
398
                                      this,
399
                                      "args",
400
                                      std::move(traced_value));
401
  }
402
403
  // By default, always abort when --abort-on-uncaught-exception was passed.
404
4594
  should_abort_on_uncaught_toggle_[0] = 1;
405
406
4594
  if (options_->no_force_async_hooks_checks) {
407
1
    async_hooks_.no_force_checks();
408
  }
409
410
  // TODO(joyeecheung): deserialize when the snapshot covers the environment
411
  // properties.
412
4594
  CreateProperties();
413
414
  // This adjusts the return value of base_object_count() so that tests that
415
  // check the count do not have to account for internally created BaseObjects.
416
4593
  initial_base_object_count_ = base_object_count();
417
4594
}
418
419
324478
Environment::~Environment() {
420
4162
  if (Environment** interrupt_data = interrupt_data_.load()) {
421
    // There are pending RequestInterrupt() callbacks. Tell them not to run,
422
    // then force V8 to run interrupts by compiling and running an empty script
423
    // so as not to leak memory.
424
10
    *interrupt_data = nullptr;
425
426
20
    Isolate::AllowJavascriptExecutionScope allow_js_here(isolate());
427
20
    HandleScope handle_scope(isolate());
428
20
    TryCatch try_catch(isolate());
429
10
    Context::Scope context_scope(context());
430
431
#ifdef DEBUG
432
    bool consistency_check = false;
433
    isolate()->RequestInterrupt([](Isolate*, void* data) {
434
      *static_cast<bool*>(data) = true;
435
    }, &consistency_check);
436
#endif
437
438
    Local<Script> script;
439
30
    if (Script::Compile(context(), String::Empty(isolate())).ToLocal(&script))
440
20
      USE(script->Run(context()));
441
442
    DCHECK(consistency_check);
443
  }
444
445
  // FreeEnvironment() should have set this.
446
4163
  CHECK(is_stopping());
447
448
4162
  isolate()->GetHeapProfiler()->RemoveBuildEmbedderGraphCallback(
449
4163
      BuildEmbedderGraph, this);
450
451
8326
  HandleScope handle_scope(isolate());
452
453
#if HAVE_INSPECTOR
454
  // Destroy inspector agent before erasing the context. The inspector
455
  // destructor depends on the context still being accessible.
456
4163
  inspector_agent_.reset();
457
#endif
458
459
12488
  context()->SetAlignedPointerInEmbedderData(
460
4162
      ContextEmbedderIndex::kEnvironment, nullptr);
461
462
4163
  if (trace_state_observer_) {
463
4163
    tracing::AgentWriterHandle* writer = GetTracingAgentWriter();
464
4163
    CHECK_NOT_NULL(writer);
465
4163
    if (TracingController* tracing_controller = writer->GetTracingController())
466
4129
      tracing_controller->RemoveTraceStateObserver(trace_state_observer_.get());
467
  }
468
469

8326
  TRACE_EVENT_NESTABLE_ASYNC_END0(
470
    TRACING_CATEGORY_NODE1(environment), "Environment", this);
471
472
  // Do not unload addons on the main thread. Some addons need to retain memory
473
  // beyond the Environment's lifetime, and unloading them early would break
474
  // them; with Worker threads, we have the opportunity to be stricter.
475
  // Also, since the main thread usually stops just before the process exits,
476
  // this is far less relevant here.
477
4163
  if (!is_main_thread()) {
478
    // Dereference all addons that were loaded into this environment.
479
311
    for (binding::DLib& addon : loaded_addons_) {
480
11
      addon.Close();
481
    }
482
  }
483
484
4163
  CHECK_EQ(base_object_count_, 0);
485
8326
}
486
487
4570
void Environment::InitializeLibuv(bool start_profiler_idle_notifier) {
488
9140
  HandleScope handle_scope(isolate());
489
4570
  Context::Scope context_scope(context());
490
491
4570
  CHECK_EQ(0, uv_timer_init(event_loop(), timer_handle()));
492
4570
  uv_unref(reinterpret_cast<uv_handle_t*>(timer_handle()));
493
494
4570
  uv_check_init(event_loop(), immediate_check_handle());
495
4570
  uv_unref(reinterpret_cast<uv_handle_t*>(immediate_check_handle()));
496
497
4570
  uv_idle_init(event_loop(), immediate_idle_handle());
498
499
4570
  uv_check_start(immediate_check_handle(), CheckImmediate);
500
501
  // Inform V8's CPU profiler when we're idle.  The profiler is sampling-based
502
  // but not all samples are created equal; mark the wall clock time spent in
503
  // epoll_wait() and friends so profiling tools can filter it out.  The samples
504
  // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
505
  // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
506
  // probably fortify in the API contract, namely that the last started prepare
507
  // or check watcher runs first.  It's not 100% foolproof; if an add-on starts
508
  // a prepare or check watcher after us, any samples attributed to its callback
509
  // will be recorded with state=IDLE.
510
4570
  uv_prepare_init(event_loop(), &idle_prepare_handle_);
511
4570
  uv_check_init(event_loop(), &idle_check_handle_);
512
9140
  uv_async_init(
513
      event_loop(),
514
      &task_queues_async_,
515
6854
      [](uv_async_t* async) {
516
2284
        Environment* env = ContainerOf(
517
1142
            &Environment::task_queues_async_, async);
518
1142
        env->RunAndClearNativeImmediates();
519
11420
      });
520
4570
  uv_unref(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_));
521
4570
  uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
522
4570
  uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
523
524
  {
525
9140
    Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
526
4570
    task_queues_async_initialized_ = true;
527

9140
    if (native_immediates_threadsafe_.size() > 0 ||
528
4570
        native_immediates_interrupts_.size() > 0) {
529
      uv_async_send(&task_queues_async_);
530
    }
531
  }
532
533
  // Register clean-up cb to be called to clean up the handles
534
  // when the environment is freed, note that they are not cleaned in
535
  // the one environment per process setup, but will be called in
536
  // FreeEnvironment.
537
4570
  RegisterHandleCleanups();
538
539
4570
  if (start_profiler_idle_notifier) {
540
3
    StartProfilerIdleNotifier();
541
  }
542
4570
}
543
544
86
void Environment::ExitEnv() {
545
86
  set_can_call_into_js(false);
546
86
  set_stopping(true);
547
86
  isolate_->TerminateExecution();
548
172
  SetImmediateThreadsafe([](Environment* env) { uv_stop(env->event_loop()); });
549
86
}
550
551
4570
void Environment::RegisterHandleCleanups() {
552
  HandleCleanupCb close_and_finish = [](Environment* env, uv_handle_t* handle,
553
54236
                                        void* arg) {
554
24833
    handle->data = env;
555
556
49663
    env->CloseHandle(handle, [](uv_handle_t* handle) {
557
#ifdef DEBUG
558
      memset(handle, 0xab, uv_handle_size(handle->type));
559
#endif
560
49667
    });
561
58802
  };
562
563
27420
  auto register_handle = [&](uv_handle_t* handle) {
564
27420
    RegisterHandleCleanup(handle, close_and_finish, nullptr);
565
31990
  };
566
4570
  register_handle(reinterpret_cast<uv_handle_t*>(timer_handle()));
567
4570
  register_handle(reinterpret_cast<uv_handle_t*>(immediate_check_handle()));
568
4570
  register_handle(reinterpret_cast<uv_handle_t*>(immediate_idle_handle()));
569
4570
  register_handle(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_));
570
4570
  register_handle(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
571
4570
  register_handle(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
572
4570
}
573
574
8316
void Environment::CleanupHandles() {
575
  {
576
16632
    Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
577
8316
    task_queues_async_initialized_ = false;
578
  }
579
580
  Isolate::DisallowJavascriptExecutionScope disallow_js(isolate(),
581
16632
      Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
582
583
8316
  RunAndClearNativeImmediates(true /* skip unrefed SetImmediate()s */);
584
585
8355
  for (ReqWrapBase* request : req_wrap_queue_)
586
39
    request->Cancel();
587
588
10458
  for (HandleWrap* handle : handle_wrap_queue_)
589
4286
    handle->Close();
590
591
33145
  for (HandleCleanup& hc : handle_cleanup_queue_)
592
24832
    hc.cb_(this, hc.handle_, hc.arg_);
593
8315
  handle_cleanup_queue_.clear();
594
595

49024
  while (handle_cleanup_waiting_ != 0 ||
596

24659
         request_waiting_ != 0 ||
597
8319
         !handle_wrap_queue_.IsEmpty()) {
598
8024
    uv_run(event_loop(), UV_RUN_ONCE);
599
  }
600
8316
}
601
602
3
void Environment::StartProfilerIdleNotifier() {
603
3
  if (profiler_idle_notifier_started_)
604
    return;
605
606
3
  profiler_idle_notifier_started_ = true;
607
608
225
  uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) {
609
108
    Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle);
610
108
    env->isolate()->SetIdle(true);
611
222
  });
612
613
223
  uv_check_start(&idle_check_handle_, [](uv_check_t* handle) {
614
107
    Environment* env = ContainerOf(&Environment::idle_check_handle_, handle);
615
107
    env->isolate()->SetIdle(false);
616
220
  });
617
}
618
619
void Environment::StopProfilerIdleNotifier() {
620
  profiler_idle_notifier_started_ = false;
621
  uv_prepare_stop(&idle_prepare_handle_);
622
  uv_check_stop(&idle_check_handle_);
623
}
624
625
299611
void Environment::PrintSyncTrace() const {
626
299611
  if (!trace_sync_io_) return;
627
628
2
  HandleScope handle_scope(isolate());
629
630
1
  fprintf(
631
1
      stderr, "(node:%d) WARNING: Detected use of sync API\n", uv_os_getpid());
632
1
  PrintStackTrace(isolate(),
633
                  StackTrace::CurrentStackTrace(
634
1
                      isolate(), stack_trace_limit(), StackTrace::kDetailed));
635
}
636
637
4162
void Environment::RunCleanup() {
638
4162
  started_cleanup_ = true;
639
  TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
640
8325
                              "RunCleanup", this);
641
4161
  bindings_.clear();
642
4163
  initial_base_object_count_ = 0;
643
4163
  CleanupHandles();
644
645
12469
  while (!cleanup_hooks_.empty()) {
646
    // Copy into a vector, since we can't sort an unordered_set in-place.
647
    std::vector<CleanupHookCallback> callbacks(
648
8306
        cleanup_hooks_.begin(), cleanup_hooks_.end());
649
    // We can't erase the copied elements from `cleanup_hooks_` yet, because we
650
    // need to be able to check whether they were un-scheduled by another hook.
651
652
8306
    std::sort(callbacks.begin(), callbacks.end(),
653
728375
              [](const CleanupHookCallback& a, const CleanupHookCallback& b) {
654
      // Sort in descending order so that the most recently inserted callbacks
655
      // are run first.
656
728375
      return a.insertion_order_counter_ > b.insertion_order_counter_;
657
732528
    });
658
659
92457
    for (const CleanupHookCallback& cb : callbacks) {
660
88304
      if (cleanup_hooks_.count(cb) == 0) {
661
        // This hook was removed from the `cleanup_hooks_` set during another
662
        // hook that was run earlier. Nothing to do here.
663
624
        continue;
664
      }
665
666
87680
      cb.fn_(cb.arg_);
667
87680
      cleanup_hooks_.erase(cb);
668
    }
669
4153
    CleanupHandles();
670
  }
671
4163
}
672
673
4651
void Environment::RunAtExitCallbacks() {
674
  TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
675
9302
                              "AtExit", this);
676
13822
  for (ExitCallback at_exit : at_exit_functions_) {
677
9171
    at_exit.cb_(at_exit.arg_);
678
  }
679
4651
  at_exit_functions_.clear();
680
4651
}
681
682
9190
void Environment::AtExit(void (*cb)(void* arg), void* arg) {
683
9190
  at_exit_functions_.push_front(ExitCallback{cb, arg});
684
9191
}
685
686
423529
void Environment::RunAndClearInterrupts() {
687
429881
  while (native_immediates_interrupts_.size() > 0) {
688
12704
    NativeImmediateQueue queue;
689
    {
690
12704
      Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
691
6352
      queue.ConcatMove(std::move(native_immediates_interrupts_));
692
    }
693
6352
    DebugSealHandleScope seal_handle_scope(isolate());
694
695
19062
    while (auto head = queue.Shift())
696
12710
      head->Call(this);
697
  }
698
417183
}
699
700
410981
void Environment::RunAndClearNativeImmediates(bool only_refed) {
701
  TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
702
821966
                              "RunAndClearNativeImmediates", this);
703
410984
  size_t ref_count = 0;
704
705
  // Handle interrupts first. These functions are not allowed to throw
706
  // exceptions, so we do not need to handle that.
707
410984
  RunAndClearInterrupts();
708
709
821966
  auto drain_list = [&](NativeImmediateQueue* queue) {
710
1699678
    TryCatchScope try_catch(this);
711
821972
    DebugSealHandleScope seal_handle_scope(isolate());
712
933747
    while (auto head = queue->Shift()) {
713
55892
      bool is_refed = head->flags() & CallbackFlags::kRefed;
714
55892
      if (is_refed)
715
33533
        ref_count++;
716
717

55892
      if (is_refed || !only_refed)
718
111472
        head->Call(this);
719
720
55888
      head.reset();  // Destroy now so that this is also observed by try_catch.
721
722
55888
      if (UNLIKELY(try_catch.HasCaught())) {
723

3
        if (!try_catch.HasTerminated() && can_call_into_js())
724
1
          errors::TriggerUncaughtException(isolate(), try_catch);
725
726
2
        return true;
727
      }
728
55886
    }
729
821972
    return false;
730
410986
  };
731
410987
  while (drain_list(&native_immediates_)) {}
732
733
410984
  immediate_info()->ref_count_dec(ref_count);
734
735
410986
  if (immediate_info()->ref_count() == 0)
736
380748
    ToggleImmediateRef(false);
737
738
  // It is safe to check .size() first, because there is a causal relationship
739
  // between pushes to the threadsafe immediate list and this function being
740
  // called. For the common case, it's worth checking the size first before
741
  // establishing a mutex lock.
742
  // This is intentionally placed after the `ref_count` handling, because when
743
  // refed threadsafe immediates are created, they are not counted towards the
744
  // count in immediate_info() either.
745
821967
  NativeImmediateQueue threadsafe_immediates;
746
410982
  if (native_immediates_threadsafe_.size() > 0) {
747
790
    Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
748
395
    threadsafe_immediates.ConcatMove(std::move(native_immediates_threadsafe_));
749
  }
750
410988
  while (drain_list(&threadsafe_immediates)) {}
751
410982
}
752
753
6356
void Environment::RequestInterruptFromV8() {
754
  // The Isolate may outlive the Environment, so some logic to handle the
755
  // situation in which the Environment is destroyed before the handler runs
756
  // is required.
757
758
  // We allocate a new pointer to a pointer to this Environment instance, and
759
  // try to set it as interrupt_data_. If interrupt_data_ was already set, then
760
  // callbacks are already scheduled to run and we can delete our own pointer
761
  // and just return. If it was nullptr previously, the Environment** is stored;
762
  // ~Environment sets the Environment* contained in it to nullptr, so that
763
  // the callback can check whether ~Environment has already run and it is thus
764
  // not safe to access the Environment instance itself.
765
6356
  Environment** interrupt_data = new Environment*(this);
766
6358
  Environment** dummy = nullptr;
767
6358
  if (!interrupt_data_.compare_exchange_strong(dummy, interrupt_data)) {
768
275
    delete interrupt_data;
769
275
    return;  // Already scheduled.
770
  }
771
772
30399
  isolate()->RequestInterrupt([](Isolate* isolate, void* data) {
773
12142
    std::unique_ptr<Environment*> env_ptr { static_cast<Environment**>(data) };
774
6076
    Environment* env = *env_ptr;
775
6076
    if (env == nullptr) {
776
      // The Environment has already been destroyed. That should be okay; any
777
      // callback added before the Environment shuts down would have been
778
      // handled during cleanup.
779
10
      return;
780
    }
781
6066
    env->interrupt_data_.store(nullptr);
782
6066
    env->RunAndClearInterrupts();
783
18240
  }, interrupt_data);
784
}
785
786
5667
void Environment::ScheduleTimer(int64_t duration_ms) {
787
5667
  if (started_cleanup_) return;
788
5667
  uv_timer_start(timer_handle(), RunTimers, duration_ms, 0);
789
}
790
791
1092
void Environment::ToggleTimerRef(bool ref) {
792
1092
  if (started_cleanup_) return;
793
794
1092
  if (ref) {
795
759
    uv_ref(reinterpret_cast<uv_handle_t*>(timer_handle()));
796
  } else {
797
333
    uv_unref(reinterpret_cast<uv_handle_t*>(timer_handle()));
798
  }
799
}
800
801
4616
void Environment::RunTimers(uv_timer_t* handle) {
802
4616
  Environment* env = Environment::from_timer_handle(handle);
803
  TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
804
9222
                              "RunTimers", env);
805
806
4617
  if (!env->can_call_into_js())
807
    return;
808
809
9220
  HandleScope handle_scope(env->isolate());
810
9220
  Context::Scope context_scope(env->context());
811
812
4615
  Local<Object> process = env->process_object();
813
9221
  InternalCallbackScope scope(env, process, {0, 0});
814
815
4617
  Local<Function> cb = env->timers_callback_function();
816
  MaybeLocal<Value> ret;
817
4617
  Local<Value> arg = env->GetNow();
818
  // This code will loop until all currently due timers will process. It is
819
  // impossible for us to end up in an infinite loop due to how the JS-side
820
  // is structured.
821
4638
  do {
822
9284
    TryCatchScope try_catch(env);
823
4647
    try_catch.SetVerbose(true);
824
9295
    ret = cb->Call(env->context(), process, 1, &arg);
825

4638
  } while (ret.IsEmpty() && env->can_call_into_js());
826
827
  // NOTE(apapirovski): If it ever becomes possible that `call_into_js` above
828
  // is reset back to `true` after being previously set to `false` then this
829
  // code becomes invalid and needs to be rewritten. Otherwise catastrophic
830
  // timers corruption will occur and all timers behaviour will become
831
  // entirely unpredictable.
832
4607
  if (ret.IsEmpty())
833
3
    return;
834
835
  // To allow for less JS-C++ boundary crossing, the value returned from JS
836
  // serves a few purposes:
837
  // 1. If it's 0, no more timers exist and the handle should be unrefed
838
  // 2. If it's > 0, the value represents the next timer's expiry and there
839
  //    is at least one timer remaining that is refed.
840
  // 3. If it's < 0, the absolute value represents the next timer's expiry
841
  //    and there are no timers that are refed.
842
  int64_t expiry_ms =
843
18414
      ret.ToLocalChecked()->IntegerValue(env->context()).FromJust();
844
845
4604
  uv_handle_t* h = reinterpret_cast<uv_handle_t*>(handle);
846
847
4604
  if (expiry_ms != 0) {
848
    int64_t duration_ms =
849
4269
        llabs(expiry_ms) - (uv_now(env->event_loop()) - env->timer_base());
850
851
4269
    env->ScheduleTimer(duration_ms > 0 ? duration_ms : 1);
852
853
4270
    if (expiry_ms > 0)
854
3888
      uv_ref(h);
855
    else
856
382
      uv_unref(h);
857
  } else {
858
335
    uv_unref(h);
859
  }
860
}
861
862
863
401522
void Environment::CheckImmediate(uv_check_t* handle) {
864
401522
  Environment* env = Environment::from_immediate_check_handle(handle);
865
  TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
866
431696
                              "CheckImmediate", env);
867
868
431696
  HandleScope scope(env->isolate());
869
431696
  Context::Scope context_scope(env->context());
870
871
401529
  env->RunAndClearNativeImmediates();
872
873

401529
  if (env->immediate_info()->count() == 0 || !env->can_call_into_js())
874
371344
    return;
875
876
30715
  do {
877
61441
    MakeCallback(env->isolate(),
878
                 env->process_object(),
879
                 env->immediate_callback_function(),
880
                 0,
881
                 nullptr,
882
30729
                 {0, 0}).ToLocalChecked();
883

30715
  } while (env->immediate_info()->has_outstanding() && env->can_call_into_js());
884
885
30170
  if (env->immediate_info()->ref_count() == 0)
886
4336
    env->ToggleImmediateRef(false);
887
}
888
889
437553
void Environment::ToggleImmediateRef(bool ref) {
890
437553
  if (started_cleanup_) return;
891
892
429240
  if (ref) {
893
    // Idle handle is needed only to stop the event loop from blocking in poll.
894
158286
    uv_idle_start(immediate_idle_handle(), [](uv_idle_t*){ });
895
  } else {
896
376784
    uv_idle_stop(immediate_idle_handle());
897
  }
898
}
899
900
901
21075
Local<Value> Environment::GetNow() {
902
21075
  uv_update_time(event_loop());
903
21076
  uint64_t now = uv_now(event_loop());
904
21076
  CHECK_GE(now, timer_base());
905
21076
  now -= timer_base();
906
21075
  if (now <= 0xffffffff)
907
42149
    return Integer::NewFromUnsigned(isolate(), static_cast<uint32_t>(now));
908
  else
909
    return Number::New(isolate(), static_cast<double>(now));
910
}
911
912
28
void CollectExceptionInfo(Environment* env,
913
                          Local<Object> obj,
914
                          int errorno,
915
                          const char* err_string,
916
                          const char* syscall,
917
                          const char* message,
918
                          const char* path,
919
                          const char* dest) {
920
56
  obj->Set(env->context(),
921
           env->errno_string(),
922
140
           Integer::New(env->isolate(), errorno)).Check();
923
924
56
  obj->Set(env->context(), env->code_string(),
925
140
           OneByteString(env->isolate(), err_string)).Check();
926
927
28
  if (message != nullptr) {
928
56
    obj->Set(env->context(), env->message_string(),
929
140
             OneByteString(env->isolate(), message)).Check();
930
  }
931
932
  Local<Value> path_buffer;
933
28
  if (path != nullptr) {
934
    path_buffer =
935
      Buffer::Copy(env->isolate(), path, strlen(path)).ToLocalChecked();
936
    obj->Set(env->context(), env->path_string(), path_buffer).Check();
937
  }
938
939
  Local<Value> dest_buffer;
940
28
  if (dest != nullptr) {
941
    dest_buffer =
942
      Buffer::Copy(env->isolate(), dest, strlen(dest)).ToLocalChecked();
943
    obj->Set(env->context(), env->dest_string(), dest_buffer).Check();
944
  }
945
946
28
  if (syscall != nullptr) {
947
56
    obj->Set(env->context(), env->syscall_string(),
948
140
             OneByteString(env->isolate(), syscall)).Check();
949
  }
950
28
}
951
952
28
void Environment::CollectUVExceptionInfo(Local<Value> object,
953
                                         int errorno,
954
                                         const char* syscall,
955
                                         const char* message,
956
                                         const char* path,
957
                                         const char* dest) {
958

28
  if (!object->IsObject() || errorno == 0)
959
    return;
960
961
28
  Local<Object> obj = object.As<Object>();
962
28
  const char* err_string = uv_err_name(errorno);
963
964

28
  if (message == nullptr || message[0] == '\0') {
965
28
    message = uv_strerror(errorno);
966
  }
967
968
  node::CollectExceptionInfo(this, obj, errorno, err_string,
969
28
                             syscall, message, path, dest);
970
}
971
972
19
void ImmediateInfo::MemoryInfo(MemoryTracker* tracker) const {
973
19
  tracker->TrackField("fields", fields_);
974
19
}
975
976
19
void TickInfo::MemoryInfo(MemoryTracker* tracker) const {
977
19
  tracker->TrackField("fields", fields_);
978
19
}
979
980
19
void AsyncHooks::MemoryInfo(MemoryTracker* tracker) const {
981
19
  tracker->TrackField("async_ids_stack", async_ids_stack_);
982
19
  tracker->TrackField("fields", fields_);
983
19
  tracker->TrackField("async_id_fields", async_id_fields_);
984
19
}
985
986
4
void AsyncHooks::grow_async_ids_stack() {
987
4
  async_ids_stack_.reserve(async_ids_stack_.Length() * 3);
988
989
12
  env()->async_hooks_binding()->Set(
990
      env()->context(),
991
      env()->async_ids_stack_string(),
992
20
      async_ids_stack_.GetJSArray()).Check();
993
4
}
994
995
uv_key_t Environment::thread_local_env = {};
996
997
468
void Environment::Exit(int exit_code) {
998
468
  if (options()->trace_exit) {
999
2
    HandleScope handle_scope(isolate());
1000
1001
1
    if (is_main_thread()) {
1002
1
      fprintf(stderr, "(node:%d) ", uv_os_getpid());
1003
    } else {
1004
      fprintf(stderr, "(node:%d, thread:%" PRIu64 ") ",
1005
              uv_os_getpid(), thread_id());
1006
    }
1007
1008
    fprintf(
1009
1
        stderr, "WARNING: Exited the environment with code %d\n", exit_code);
1010
1
    PrintStackTrace(isolate(),
1011
                    StackTrace::CurrentStackTrace(
1012
1
                        isolate(), stack_trace_limit(), StackTrace::kDetailed));
1013
  }
1014
468
  process_exit_handler_(this, exit_code);
1015
42
}
1016
1017
4614
void Environment::stop_sub_worker_contexts() {
1018
  DCHECK_EQ(Isolate::GetCurrent(), isolate());
1019
1020
4639
  while (!sub_worker_contexts_.empty()) {
1021
25
    Worker* w = *sub_worker_contexts_.begin();
1022
25
    remove_sub_worker_context(w);
1023
25
    w->Exit(1);
1024
25
    w->JoinThread();
1025
  }
1026
4588
}
1027
1028
2
Environment* Environment::worker_parent_env() const {
1029
2
  if (worker_context() == nullptr) return nullptr;
1030
  return worker_context()->env();
1031
}
1032
1033
348
void MemoryTracker::TrackField(const char* edge_name,
1034
                               const CleanupHookCallback& value,
1035
                               const char* node_name) {
1036
696
  HandleScope handle_scope(isolate_);
1037
  // Here, we utilize the fact that CleanupHookCallback instances
1038
  // are all unique and won't be tracked twice in one BuildEmbedderGraph
1039
  // callback.
1040
  MemoryRetainerNode* n =
1041
348
      PushNode("CleanupHookCallback", sizeof(value), edge_name);
1042
  // TODO(joyeecheung): at the moment only arguments of type BaseObject will be
1043
  // identified and tracked here (based on their deleters),
1044
  // but we may convert and track other known types here.
1045
348
  BaseObject* obj = value.GetBaseObject();
1046

348
  if (obj != nullptr && obj->IsDoneInitializing()) {
1047
325
    TrackField("arg", obj);
1048
  }
1049
348
  CHECK_EQ(CurrentNode(), n);
1050
348
  CHECK_NE(n->size_, 0);
1051
348
  PopNode();
1052
348
}
1053
1054
19
void Environment::BuildEmbedderGraph(Isolate* isolate,
1055
                                     EmbedderGraph* graph,
1056
                                     void* data) {
1057
38
  MemoryTracker tracker(isolate, graph);
1058
19
  Environment* env = static_cast<Environment*>(data);
1059
19
  tracker.Track(env);
1060
19
}
1061
1062
19
inline size_t Environment::SelfSize() const {
1063
19
  size_t size = sizeof(*this);
1064
  // Remove non pointer fields that will be tracked in MemoryInfo()
1065
  // TODO(joyeecheung): refactor the MemoryTracker interface so
1066
  // this can be done for common types within the Track* calls automatically
1067
  // if a certain scope is entered.
1068
19
  size -= sizeof(async_hooks_);
1069
19
  size -= sizeof(tick_info_);
1070
19
  size -= sizeof(immediate_info_);
1071
19
  return size;
1072
}
1073
1074
19
void Environment::MemoryInfo(MemoryTracker* tracker) const {
1075
  // Iteratable STLs have their own sizes subtracted from the parent
1076
  // by default.
1077
19
  tracker->TrackField("isolate_data", isolate_data_);
1078
19
  tracker->TrackField("native_modules_with_cache", native_modules_with_cache);
1079
19
  tracker->TrackField("native_modules_without_cache",
1080
19
                      native_modules_without_cache);
1081
19
  tracker->TrackField("destroy_async_id_list", destroy_async_id_list_);
1082
19
  tracker->TrackField("exec_argv", exec_argv_);
1083
19
  tracker->TrackField("should_abort_on_uncaught_toggle",
1084
19
                      should_abort_on_uncaught_toggle_);
1085
19
  tracker->TrackField("stream_base_state", stream_base_state_);
1086
19
  tracker->TrackField("cleanup_hooks", cleanup_hooks_);
1087
19
  tracker->TrackField("async_hooks", async_hooks_);
1088
19
  tracker->TrackField("immediate_info", immediate_info_);
1089
19
  tracker->TrackField("tick_info", tick_info_);
1090
1091
#define V(PropertyName, TypeName)                                              \
1092
  tracker->TrackField(#PropertyName, PropertyName());
1093
19
  ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
1094
#undef V
1095
1096
  // FIXME(joyeecheung): track other fields in Environment.
1097
  // Currently MemoryTracker is unable to track these
1098
  // correctly:
1099
  // - Internal types that do not implement MemoryRetainer yet
1100
  // - STL containers with MemoryRetainer* inside
1101
  // - STL containers with numeric types inside that should not have their
1102
  //   nodes elided e.g. numeric keys in maps.
1103
  // We also need to make sure that when we add a non-pointer field as its own
1104
  // node, we shift its sizeof() size out of the Environment node.
1105
19
}
1106
1107
316256
char* Environment::Reallocate(char* data, size_t old_size, size_t size) {
1108
316256
  if (old_size == size) return data;
1109
  // If we know that the allocator is our ArrayBufferAllocator, we can let
1110
  // if reallocate directly.
1111
293868
  if (isolate_data()->uses_node_allocator()) {
1112
    return static_cast<char*>(
1113
293868
        isolate_data()->node_allocator()->Reallocate(data, old_size, size));
1114
  }
1115
  // Generic allocators do not provide a reallocation method; we need to
1116
  // allocate a new chunk of memory and copy the data over.
1117
  char* new_data = AllocateUnchecked(size);
1118
  if (new_data == nullptr) return nullptr;
1119
  memcpy(new_data, data, std::min(size, old_size));
1120
  if (size > old_size)
1121
    memset(new_data + old_size, 0, size - old_size);
1122
  Free(data, old_size);
1123
  return new_data;
1124
}
1125
1126
600358
void Environment::RunWeakRefCleanup() {
1127
600358
  isolate()->ClearKeptObjects();
1128
600366
}
1129
1130
// Not really any better place than env.cc at this moment.
1131
83243
void BaseObject::DeleteMe(void* data) {
1132
83243
  BaseObject* self = static_cast<BaseObject*>(data);
1133

85681
  if (self->has_pointer_data() &&
1134
2438
      self->pointer_data()->strong_ptr_count > 0) {
1135
248
    return self->Detach();
1136
  }
1137
82995
  delete self;
1138
}
1139
1140
265
bool BaseObject::IsDoneInitializing() const { return true; }
1141
1142
325
Local<Object> BaseObject::WrappedObject() const {
1143
325
  return object();
1144
}
1145
1146
}  // namespace node