GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_perf.cc Lines: 119 351 33.9 %
Date: 2021-02-19 04:08:54 Branches: 15 158 9.5 %

Line Branch Exec Source
1
#include "aliased_buffer.h"
2
#include "histogram-inl.h"
3
#include "memory_tracker-inl.h"
4
#include "node_internals.h"
5
#include "node_perf.h"
6
#include "node_buffer.h"
7
#include "node_process.h"
8
#include "util-inl.h"
9
10
#include <cinttypes>
11
12
namespace node {
13
namespace performance {
14
15
using v8::Context;
16
using v8::DontDelete;
17
using v8::Function;
18
using v8::FunctionCallbackInfo;
19
using v8::FunctionTemplate;
20
using v8::GCCallbackFlags;
21
using v8::GCType;
22
using v8::HandleScope;
23
using v8::Int32;
24
using v8::Integer;
25
using v8::Isolate;
26
using v8::Local;
27
using v8::MaybeLocal;
28
using v8::Number;
29
using v8::Object;
30
using v8::PropertyAttribute;
31
using v8::ReadOnly;
32
using v8::String;
33
using v8::Value;
34
35
// Microseconds in a millisecond, as a float.
36
#define MICROS_PER_MILLIS 1e3
37
38
// https://w3c.github.io/hr-time/#dfn-time-origin
39
122
const uint64_t timeOrigin = PERFORMANCE_NOW();
40
// https://w3c.github.io/hr-time/#dfn-time-origin-timestamp
41
122
const double timeOriginTimestamp = GetCurrentTimeInMicroseconds();
42
uint64_t performance_v8_start;
43
44
152
PerformanceState::PerformanceState(Isolate* isolate,
45
152
                                   const PerformanceState::SerializeInfo* info)
46
    : root(isolate,
47
           sizeof(performance_state_internal),
48
           MAYBE_FIELD_PTR(info, root)),
49
      milestones(isolate,
50
                 offsetof(performance_state_internal, milestones),
51
                 NODE_PERFORMANCE_MILESTONE_INVALID,
52
                 root,
53
                 MAYBE_FIELD_PTR(info, milestones)),
54
      observers(isolate,
55
                offsetof(performance_state_internal, observers),
56
                NODE_PERFORMANCE_ENTRY_TYPE_INVALID,
57
                root,
58

152
                MAYBE_FIELD_PTR(info, observers)) {
59
152
  if (info == nullptr) {
60
52
    for (size_t i = 0; i < milestones.Length(); i++) milestones[i] = -1.;
61
  }
62
152
}
63
64
7
PerformanceState::SerializeInfo PerformanceState::Serialize(
65
    v8::Local<v8::Context> context, v8::SnapshotCreator* creator) {
66
7
  SerializeInfo info{root.Serialize(context, creator),
67
7
                     milestones.Serialize(context, creator),
68
14
                     observers.Serialize(context, creator)};
69
7
  return info;
70
}
71
72
100
void PerformanceState::Deserialize(v8::Local<v8::Context> context) {
73
100
  root.Deserialize(context);
74
  // This is just done to set up the pointers, we will actually reset
75
  // all the milestones after deserialization.
76
100
  milestones.Deserialize(context);
77
100
  observers.Deserialize(context);
78
100
}
79
80
7
std::ostream& operator<<(std::ostream& o,
81
                         const PerformanceState::SerializeInfo& i) {
82
  o << "{\n"
83
7
    << "  " << i.root << ",  // root\n"
84
14
    << "  " << i.milestones << ",  // milestones\n"
85
14
    << "  " << i.observers << ",  // observers\n"
86
7
    << "}";
87
7
  return o;
88
}
89
90
786
void PerformanceState::Mark(enum PerformanceMilestone milestone,
91
                             uint64_t ts) {
92
786
  this->milestones[milestone] = static_cast<double>(ts);
93
  TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
94
786
      TRACING_CATEGORY_NODE1(bootstrap),
95
      GetPerformanceMilestoneName(milestone),
96
115
      TRACE_EVENT_SCOPE_THREAD, ts / 1000);
97
1572
}
98
99
// Initialize the performance entry object properties
100
inline void InitObject(const PerformanceEntry& entry, Local<Object> obj) {
101
  Environment* env = entry.env();
102
  Isolate* isolate = env->isolate();
103
  Local<Context> context = env->context();
104
  PropertyAttribute attr =
105
      static_cast<PropertyAttribute>(ReadOnly | DontDelete);
106
  obj->DefineOwnProperty(context,
107
                         env->name_string(),
108
                         String::NewFromUtf8(isolate,
109
                                             entry.name().c_str())
110
                             .ToLocalChecked(),
111
                         attr)
112
      .Check();
113
  obj->DefineOwnProperty(context,
114
                         env->entry_type_string(),
115
                         String::NewFromUtf8(isolate,
116
                                             entry.type().c_str())
117
                             .ToLocalChecked(),
118
                         attr)
119
      .Check();
120
  obj->DefineOwnProperty(context,
121
                         env->start_time_string(),
122
                         Number::New(isolate, entry.startTime()),
123
                         attr).Check();
124
  obj->DefineOwnProperty(context,
125
                         env->duration_string(),
126
                         Number::New(isolate, entry.duration()),
127
                         attr).Check();
128
}
129
130
// Create a new PerformanceEntry object
131
MaybeLocal<Object> PerformanceEntry::ToObject() const {
132
  Local<Object> obj;
133
  if (!env_->performance_entry_template()
134
           ->NewInstance(env_->context())
135
           .ToLocal(&obj)) {
136
    return MaybeLocal<Object>();
137
  }
138
  InitObject(*this, obj);
139
  return obj;
140
}
141
142
// Allow creating a PerformanceEntry object from JavaScript
143
void PerformanceEntry::New(const FunctionCallbackInfo<Value>& args) {
144
  Environment* env = Environment::GetCurrent(args);
145
  Isolate* isolate = env->isolate();
146
  Utf8Value name(isolate, args[0]);
147
  Utf8Value type(isolate, args[1]);
148
  uint64_t now = PERFORMANCE_NOW();
149
  PerformanceEntry entry(env, *name, *type, now, now);
150
  Local<Object> obj = args.This();
151
  InitObject(entry, obj);
152
  PerformanceEntry::Notify(env, entry.kind(), obj);
153
}
154
155
// Pass the PerformanceEntry object to the PerformanceObservers
156
void PerformanceEntry::Notify(Environment* env,
157
                              PerformanceEntryType type,
158
                              Local<Value> object) {
159
  Context::Scope scope(env->context());
160
  AliasedUint32Array& observers = env->performance_state()->observers;
161
  if (!env->performance_entry_callback().IsEmpty() &&
162
      type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID && observers[type]) {
163
    node::MakeSyncCallback(env->isolate(),
164
                           object.As<Object>(),
165
                           env->performance_entry_callback(),
166
                           1, &object);
167
  }
168
}
169
170
// Create a User Timing Mark
171
void Mark(const FunctionCallbackInfo<Value>& args) {
172
  Environment* env = Environment::GetCurrent(args);
173
  HandleScope scope(env->isolate());
174
  Utf8Value name(env->isolate(), args[0]);
175
  uint64_t now = PERFORMANCE_NOW();
176
  auto marks = env->performance_marks();
177
  (*marks)[*name] = now;
178
179
  TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP(
180
      TRACING_CATEGORY_NODE2(perf, usertiming),
181
      *name, now / 1000);
182
183
  PerformanceEntry entry(env, *name, "mark", now, now);
184
  Local<Object> obj;
185
  if (!entry.ToObject().ToLocal(&obj)) return;
186
  PerformanceEntry::Notify(env, entry.kind(), obj);
187
  args.GetReturnValue().Set(obj);
188
}
189
190
void ClearMark(const FunctionCallbackInfo<Value>& args) {
191
  Environment* env = Environment::GetCurrent(args);
192
  auto marks = env->performance_marks();
193
194
  if (args.Length() == 0) {
195
    marks->clear();
196
  } else {
197
    Utf8Value name(env->isolate(), args[0]);
198
    marks->erase(*name);
199
  }
200
}
201
202
inline uint64_t GetPerformanceMark(Environment* env, const std::string& name) {
203
  auto marks = env->performance_marks();
204
  auto res = marks->find(name);
205
  return res != marks->end() ? res->second : 0;
206
}
207
208
// Create a User Timing Measure. A Measure is a PerformanceEntry that
209
// measures the duration between two distinct user timing marks
210
void Measure(const FunctionCallbackInfo<Value>& args) {
211
  Environment* env = Environment::GetCurrent(args);
212
  HandleScope scope(env->isolate());
213
  Utf8Value name(env->isolate(), args[0]);
214
  Utf8Value startMark(env->isolate(), args[1]);
215
216
  AliasedFloat64Array& milestones = env->performance_state()->milestones;
217
218
  uint64_t startTimestamp = timeOrigin;
219
  uint64_t start = GetPerformanceMark(env, *startMark);
220
  if (start != 0) {
221
    startTimestamp = start;
222
  } else {
223
    PerformanceMilestone milestone = ToPerformanceMilestoneEnum(*startMark);
224
    if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
225
      startTimestamp = milestones[milestone];
226
  }
227
228
  uint64_t endTimestamp = 0;
229
  if (args[2]->IsUndefined()) {
230
    endTimestamp = PERFORMANCE_NOW();
231
  } else {
232
    Utf8Value endMark(env->isolate(), args[2]);
233
    endTimestamp = GetPerformanceMark(env, *endMark);
234
    if (endTimestamp == 0) {
235
      PerformanceMilestone milestone = ToPerformanceMilestoneEnum(*endMark);
236
      if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
237
        endTimestamp = milestones[milestone];
238
    }
239
  }
240
241
  if (endTimestamp < startTimestamp)
242
    endTimestamp = startTimestamp;
243
244
  TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
245
      TRACING_CATEGORY_NODE2(perf, usertiming),
246
      *name, *name, startTimestamp / 1000);
247
  TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
248
      TRACING_CATEGORY_NODE2(perf, usertiming),
249
      *name, *name, endTimestamp / 1000);
250
251
  PerformanceEntry entry(env, *name, "measure", startTimestamp, endTimestamp);
252
  Local<Object> obj;
253
  if (!entry.ToObject().ToLocal(&obj)) return;
254
  PerformanceEntry::Notify(env, entry.kind(), obj);
255
  args.GetReturnValue().Set(obj);
256
}
257
258
// Allows specific Node.js lifecycle milestones to be set from JavaScript
259
void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
260
  Environment* env = Environment::GetCurrent(args);
261
  Local<Context> context = env->context();
262
  PerformanceMilestone milestone =
263
      static_cast<PerformanceMilestone>(
264
          args[0]->Int32Value(context).ToChecked());
265
  if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
266
    env->performance_state()->Mark(milestone);
267
}
268
269
270
void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) {
271
  Environment* env = Environment::GetCurrent(args);
272
  CHECK(args[0]->IsFunction());
273
  env->set_performance_entry_callback(args[0].As<Function>());
274
}
275
276
// Creates a GC Performance Entry and passes it to observers
277
void PerformanceGCCallback(Environment* env,
278
                           std::unique_ptr<GCPerformanceEntry> entry) {
279
  HandleScope scope(env->isolate());
280
  Local<Context> context = env->context();
281
282
  AliasedUint32Array& observers = env->performance_state()->observers;
283
  if (observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
284
    Local<Object> obj;
285
    if (!entry->ToObject().ToLocal(&obj)) return;
286
    PropertyAttribute attr =
287
        static_cast<PropertyAttribute>(ReadOnly | DontDelete);
288
    obj->DefineOwnProperty(context,
289
                           env->kind_string(),
290
                           Integer::New(env->isolate(), entry->gckind()),
291
                           attr).Check();
292
    obj->DefineOwnProperty(context,
293
                           env->flags_string(),
294
                           Integer::New(env->isolate(), entry->gcflags()),
295
                           attr).Check();
296
    PerformanceEntry::Notify(env, entry->kind(), obj);
297
  }
298
}
299
300
// Marks the start of a GC cycle
301
void MarkGarbageCollectionStart(Isolate* isolate,
302
                                GCType type,
303
                                GCCallbackFlags flags,
304
                                void* data) {
305
  Environment* env = static_cast<Environment*>(data);
306
  env->performance_state()->performance_last_gc_start_mark = PERFORMANCE_NOW();
307
}
308
309
// Marks the end of a GC cycle
310
void MarkGarbageCollectionEnd(Isolate* isolate,
311
                              GCType type,
312
                              GCCallbackFlags flags,
313
                              void* data) {
314
  Environment* env = static_cast<Environment*>(data);
315
  PerformanceState* state = env->performance_state();
316
  // If no one is listening to gc performance entries, do not create them.
317
  if (!state->observers[NODE_PERFORMANCE_ENTRY_TYPE_GC])
318
    return;
319
  auto entry = std::make_unique<GCPerformanceEntry>(
320
      env,
321
      static_cast<PerformanceGCKind>(type),
322
      static_cast<PerformanceGCFlags>(flags),
323
      state->performance_last_gc_start_mark,
324
      PERFORMANCE_NOW());
325
  env->SetImmediate([entry = std::move(entry)](Environment* env) mutable {
326
    PerformanceGCCallback(env, std::move(entry));
327
  }, CallbackFlags::kUnrefed);
328
}
329
330
void GarbageCollectionCleanupHook(void* data) {
331
  Environment* env = static_cast<Environment*>(data);
332
  env->isolate()->RemoveGCPrologueCallback(MarkGarbageCollectionStart, data);
333
  env->isolate()->RemoveGCEpilogueCallback(MarkGarbageCollectionEnd, data);
334
}
335
336
static void InstallGarbageCollectionTracking(
337
    const FunctionCallbackInfo<Value>& args) {
338
  Environment* env = Environment::GetCurrent(args);
339
340
  env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart,
341
                                        static_cast<void*>(env));
342
  env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
343
                                        static_cast<void*>(env));
344
  env->AddCleanupHook(GarbageCollectionCleanupHook, env);
345
}
346
347
static void RemoveGarbageCollectionTracking(
348
  const FunctionCallbackInfo<Value> &args) {
349
  Environment* env = Environment::GetCurrent(args);
350
351
  env->RemoveCleanupHook(GarbageCollectionCleanupHook, env);
352
  GarbageCollectionCleanupHook(env);
353
}
354
355
// Gets the name of a function
356
inline Local<Value> GetName(Local<Function> fn) {
357
  Local<Value> val = fn->GetDebugName();
358
  if (val.IsEmpty() || val->IsUndefined()) {
359
    Local<Value> boundFunction = fn->GetBoundFunction();
360
    if (!boundFunction.IsEmpty() && !boundFunction->IsUndefined()) {
361
      val = GetName(boundFunction.As<Function>());
362
    }
363
  }
364
  return val;
365
}
366
367
// Executes a wrapped Function and captures timing information, causing a
368
// Function PerformanceEntry to be emitted to PerformanceObservers after
369
// execution.
370
void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
371
  Isolate* isolate = args.GetIsolate();
372
  Local<Context> context = isolate->GetCurrentContext();
373
  Environment* env = Environment::GetCurrent(context);
374
  CHECK_NOT_NULL(env);
375
  Local<Function> fn = args.Data().As<Function>();
376
  size_t count = args.Length();
377
  size_t idx;
378
  SlicedArguments call_args(args);
379
  Utf8Value name(isolate, GetName(fn));
380
  bool is_construct_call = args.IsConstructCall();
381
382
  uint64_t start = PERFORMANCE_NOW();
383
  TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
384
      TRACING_CATEGORY_NODE2(perf, timerify),
385
      *name, *name, start / 1000);
386
  v8::MaybeLocal<Value> ret;
387
388
  if (is_construct_call) {
389
    ret = fn->NewInstance(context, call_args.length(), call_args.out())
390
        .FromMaybe(Local<Object>());
391
  } else {
392
    ret = fn->Call(context, args.This(), call_args.length(), call_args.out());
393
  }
394
395
  uint64_t end = PERFORMANCE_NOW();
396
  TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
397
      TRACING_CATEGORY_NODE2(perf, timerify),
398
      *name, *name, end / 1000);
399
400
  if (ret.IsEmpty())
401
    return;
402
  args.GetReturnValue().Set(ret.ToLocalChecked());
403
404
  AliasedUint32Array& observers = env->performance_state()->observers;
405
  if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
406
    return;
407
408
  PerformanceEntry entry(env, *name, "function", start, end);
409
  Local<Object> obj;
410
  if (!entry.ToObject().ToLocal(&obj)) return;
411
  for (idx = 0; idx < count; idx++)
412
    obj->Set(context, idx, args[idx]).Check();
413
  PerformanceEntry::Notify(env, entry.kind(), obj);
414
}
415
416
// Wraps a Function in a TimerFunctionCall
417
void Timerify(const FunctionCallbackInfo<Value>& args) {
418
  Environment* env = Environment::GetCurrent(args);
419
  Local<Context> context = env->context();
420
  CHECK(args[0]->IsFunction());
421
  CHECK(args[1]->IsNumber());
422
  Local<Function> fn = args[0].As<Function>();
423
  int length = args[1]->IntegerValue(context).ToChecked();
424
  Local<Function> wrap =
425
      Function::New(context, TimerFunctionCall, fn, length).ToLocalChecked();
426
  args.GetReturnValue().Set(wrap);
427
}
428
429
// Notify a custom PerformanceEntry to observers
430
void Notify(const FunctionCallbackInfo<Value>& args) {
431
  Environment* env = Environment::GetCurrent(args);
432
  Utf8Value type(env->isolate(), args[0]);
433
  Local<Value> entry = args[1];
434
  PerformanceEntryType entry_type = ToPerformanceEntryTypeEnum(*type);
435
  AliasedUint32Array& observers = env->performance_state()->observers;
436
  if (entry_type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID &&
437
      observers[entry_type]) {
438
    USE(env->performance_entry_callback()->
439
      Call(env->context(), Undefined(env->isolate()), 1, &entry));
440
  }
441
}
442
443
// Return idle time of the event loop
444
void LoopIdleTime(const FunctionCallbackInfo<Value>& args) {
445
  Environment* env = Environment::GetCurrent(args);
446
  uint64_t idle_time = uv_metrics_idle_time(env->event_loop());
447
  args.GetReturnValue().Set(1.0 * idle_time / 1e6);
448
}
449
450
// Event Loop Timing Histogram
451
void ELDHistogram::New(const FunctionCallbackInfo<Value>& args) {
452
  Environment* env = Environment::GetCurrent(args);
453
  CHECK(args.IsConstructCall());
454
  int32_t resolution = args[0].As<Int32>()->Value();
455
  CHECK_GT(resolution, 0);
456
  new ELDHistogram(env, args.This(), resolution);
457
}
458
459
4
void ELDHistogram::Initialize(Environment* env, Local<Object> target) {
460
4
  Local<FunctionTemplate> tmpl = env->NewFunctionTemplate(New);
461
8
  tmpl->Inherit(IntervalHistogram::GetConstructorTemplate(env));
462
12
  tmpl->InstanceTemplate()->SetInternalFieldCount(
463
4
      ELDHistogram::kInternalFieldCount);
464
4
  env->SetConstructorFunction(target, "ELDHistogram", tmpl);
465
4
}
466
467
ELDHistogram::ELDHistogram(
468
    Environment* env,
469
    Local<Object> wrap,
470
    int32_t interval)
471
    : IntervalHistogram(
472
          env,
473
          wrap,
474
          AsyncWrap::PROVIDER_ELDHISTOGRAM,
475
          interval, 1, 3.6e12, 3) {}
476
477
void ELDHistogram::OnInterval() {
478
  uint64_t delta = histogram()->RecordDelta();
479
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
480
                  "delay", delta);
481
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
482
                 "min", histogram()->Min());
483
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
484
                 "max", histogram()->Max());
485
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
486
                 "mean", histogram()->Mean());
487
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
488
                 "stddev", histogram()->Stddev());
489
}
490
491
4
void Initialize(Local<Object> target,
492
                Local<Value> unused,
493
                Local<Context> context,
494
                void* priv) {
495
4
  Environment* env = Environment::GetCurrent(context);
496
4
  Isolate* isolate = env->isolate();
497
4
  PerformanceState* state = env->performance_state();
498
499
8
  target->Set(context,
500
              FIXED_ONE_BYTE_STRING(isolate, "observerCounts"),
501
16
              state->observers.GetJSArray()).Check();
502
8
  target->Set(context,
503
              FIXED_ONE_BYTE_STRING(isolate, "milestones"),
504
16
              state->milestones.GetJSArray()).Check();
505
506
  Local<String> performanceEntryString =
507
4
      FIXED_ONE_BYTE_STRING(isolate, "PerformanceEntry");
508
509
4
  Local<FunctionTemplate> pe = FunctionTemplate::New(isolate);
510
4
  pe->SetClassName(performanceEntryString);
511
8
  Local<Function> fn = pe->GetFunction(context).ToLocalChecked();
512
8
  target->Set(context, performanceEntryString, fn).Check();
513
4
  env->set_performance_entry_template(fn);
514
515
4
  env->SetMethod(target, "clearMark", ClearMark);
516
4
  env->SetMethod(target, "mark", Mark);
517
4
  env->SetMethod(target, "measure", Measure);
518
4
  env->SetMethod(target, "markMilestone", MarkMilestone);
519
4
  env->SetMethod(target, "setupObservers", SetupPerformanceObservers);
520
4
  env->SetMethod(target, "timerify", Timerify);
521
  env->SetMethod(target,
522
                 "installGarbageCollectionTracking",
523
4
                 InstallGarbageCollectionTracking);
524
  env->SetMethod(target,
525
                 "removeGarbageCollectionTracking",
526
4
                 RemoveGarbageCollectionTracking);
527
4
  env->SetMethod(target, "notify", Notify);
528
4
  env->SetMethod(target, "loopIdleTime", LoopIdleTime);
529
530
4
  Local<Object> constants = Object::New(isolate);
531
532
4
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_MAJOR);
533
12
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_MINOR);
534
20
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_INCREMENTAL);
535
24
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_WEAKCB);
536
24
537
24
  NODE_DEFINE_CONSTANT(
538
20
    constants, NODE_PERFORMANCE_GC_FLAGS_NO);
539
16
  NODE_DEFINE_CONSTANT(
540
12
    constants, NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED);
541
16
  NODE_DEFINE_CONSTANT(
542
12
    constants, NODE_PERFORMANCE_GC_FLAGS_FORCED);
543
20
  NODE_DEFINE_CONSTANT(
544
12
    constants, NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING);
545
16
  NODE_DEFINE_CONSTANT(
546
12
    constants, NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE);
547
20
  NODE_DEFINE_CONSTANT(
548
20
    constants, NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY);
549
20
  NODE_DEFINE_CONSTANT(
550
12
    constants, NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE);
551
16
552
4
#define V(name, _)                                                            \
553
12
  NODE_DEFINE_HIDDEN_CONSTANT(constants, NODE_PERFORMANCE_ENTRY_TYPE_##name);
554
20
  NODE_PERFORMANCE_ENTRY_TYPES(V)
555
8
#undef V
556
4
557
4
#define V(name, _)                                                            \
558
12
  NODE_DEFINE_HIDDEN_CONSTANT(constants, NODE_PERFORMANCE_MILESTONE_##name);
559
8
  NODE_PERFORMANCE_MILESTONES(V)
560
16
#undef V
561
8
562
8
  PropertyAttribute attr =
563
28
      static_cast<PropertyAttribute>(ReadOnly | DontDelete);
564
8
565
24
  target->DefineOwnProperty(context,
566
8
                            FIXED_ONE_BYTE_STRING(isolate, "timeOrigin"),
567
8
                            Number::New(isolate, timeOrigin / 1e6),
568
40
                            attr).ToChecked();
569
8
570
24
  target->DefineOwnProperty(
571
8
      context,
572
8
      FIXED_ONE_BYTE_STRING(isolate, "timeOriginTimestamp"),
573
24
      Number::New(isolate, timeOriginTimestamp / MICROS_PER_MILLIS),
574
24
      attr).ToChecked();
575
16
576
16
  target->DefineOwnProperty(context,
577
8
                            env->constants_string(),
578
24
                            constants,
579
28
                            attr).ToChecked();
580
16
581
12
  HistogramBase::Initialize(env, target);
582
12
  ELDHistogram::Initialize(env, target);
583
28
}
584
16
585
16
}  // namespace performance
586
4
}  // namespace node
587
4
588

493
NODE_MODULE_CONTEXT_AWARE_INTERNAL(performance, node::performance::Initialize)