Skip to content

Commit 63101a6

Browse files
committed
Store Isolate* in WallProfiler.
A WallProfiler belong to exactly one isolate, we can bind it in the constructor and not have to retrieve Isolate::GetCurrent subsequently
1 parent 6253599 commit 63101a6

File tree

2 files changed

+60
-59
lines changed

2 files changed

+60
-59
lines changed

bindings/profilers/wall.cc

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ void SignalHandler::HandleProfilerSignal(int sig,
332332
auto time_from = Now();
333333
old_handler(sig, info, context);
334334
auto time_to = Now();
335-
auto async_id = prof->GetAsyncId(isolate);
335+
auto async_id = prof->GetAsyncId();
336336
prof->PushContext(time_from, time_to, cpu_time, async_id);
337337
}
338338
#else
@@ -384,20 +384,20 @@ void WallProfiler::CleanupHook(void* data) {
384384
auto isolate = static_cast<Isolate*>(data);
385385
auto prof = g_profilers.RemoveProfilerForIsolate(isolate);
386386
if (prof) {
387-
prof->Cleanup(isolate);
387+
prof->Cleanup();
388388
delete prof;
389389
}
390390
}
391391

392392
// This is only called when isolate is terminated without `beforeExit`
393393
// notification.
394-
void WallProfiler::Cleanup(Isolate* isolate) {
394+
void WallProfiler::Cleanup() {
395395
if (started_) {
396396
cpuProfiler_->Stop(profileId_);
397397
if (interceptSignal()) {
398398
SignalHandler::DecreaseUseCount();
399399
}
400-
Dispose(isolate, false);
400+
Dispose(false);
401401
}
402402
}
403403

@@ -411,18 +411,17 @@ ContextsByNode WallProfiler::GetContextsByNode(CpuProfile* profile,
411411
return contextsByNode;
412412
}
413413

414-
auto isolate = Isolate::GetCurrent();
415-
auto v8Context = isolate->GetCurrentContext();
414+
auto v8Context = isolate_->GetCurrentContext();
416415
auto contextIt = contexts.begin();
417416

418417
// deltaIdx is the offset of the sample to process compared to current
419418
// iteration index
420419
int deltaIdx = 0;
421420

422-
auto contextKey = String::NewFromUtf8Literal(isolate, "context");
423-
auto timestampKey = String::NewFromUtf8Literal(isolate, "timestamp");
424-
auto cpuTimeKey = String::NewFromUtf8Literal(isolate, "cpuTime");
425-
auto asyncIdKey = String::NewFromUtf8Literal(isolate, "asyncId");
421+
auto contextKey = String::NewFromUtf8Literal(isolate_, "context");
422+
auto timestampKey = String::NewFromUtf8Literal(isolate_, "timestamp");
423+
auto cpuTimeKey = String::NewFromUtf8Literal(isolate_, "cpuTime");
424+
auto asyncIdKey = String::NewFromUtf8Literal(isolate_, "asyncId");
426425
auto V8toEpochOffset = GetV8ToEpochOffset();
427426
auto lastCpuTime = startCpuTime;
428427

@@ -467,18 +466,18 @@ ContextsByNode WallProfiler::GetContextsByNode(CpuProfile* profile,
467466
auto it = contextsByNode.find(sample);
468467
Local<Array> array;
469468
if (it == contextsByNode.end()) {
470-
array = Array::New(isolate);
469+
array = Array::New(isolate_);
471470
contextsByNode[sample] = {array, 1};
472471
} else {
473472
array = it->second.contexts;
474473
++it->second.hitcount;
475474
}
476475
// Conforms to TimeProfileNodeContext defined in v8-types.ts
477-
Local<Object> timedContext = Object::New(isolate);
476+
Local<Object> timedContext = Object::New(isolate_);
478477
timedContext
479478
->Set(v8Context,
480479
timestampKey,
481-
BigInt::New(isolate, sampleTimestamp + V8toEpochOffset))
480+
BigInt::New(isolate_, sampleTimestamp + V8toEpochOffset))
482481
.Check();
483482
auto* function_name = sample->GetFunctionNameStr();
484483
// If current sample is program, reports its cpu time to the next sample
@@ -488,7 +487,7 @@ ContextsByNode WallProfiler::GetContextsByNode(CpuProfile* profile,
488487
->Set(
489488
v8Context,
490489
cpuTimeKey,
491-
Number::New(isolate, sampleContext.cpu_time - lastCpuTime))
490+
Number::New(isolate_, sampleContext.cpu_time - lastCpuTime))
492491
.Check();
493492
lastCpuTime = sampleContext.cpu_time;
494493
}
@@ -499,14 +498,14 @@ ContextsByNode WallProfiler::GetContextsByNode(CpuProfile* profile,
499498
timedContext
500499
->Set(v8Context,
501500
contextKey,
502-
sampleContext.context.get()->Get(isolate))
501+
sampleContext.context.get()->Get(isolate_))
503502
.Check();
504503
}
505504
if (collectAsyncId_) {
506505
timedContext
507506
->Set(v8Context,
508507
asyncIdKey,
509-
Number::New(isolate, sampleContext.async_id))
508+
Number::New(isolate_, sampleContext.async_id))
510509
.Check();
511510
}
512511
}
@@ -527,7 +526,7 @@ void GCPrologueCallback(Isolate* isolate,
527526
GCType type,
528527
GCCallbackFlags flags,
529528
void* data) {
530-
static_cast<WallProfiler*>(data)->OnGCStart(isolate);
529+
static_cast<WallProfiler*>(data)->OnGCStart();
531530
}
532531

533532
void GCEpilogueCallback(Isolate* isolate,
@@ -565,39 +564,38 @@ WallProfiler::WallProfiler(std::chrono::microseconds samplingPeriod,
565564
collectionMode_.store(CollectionMode::kNoCollect, std::memory_order_relaxed);
566565
gcCount.store(0, std::memory_order_relaxed);
567566

568-
// TODO: bind to this isolate? Would fix the Dispose(nullptr) issue.
569-
auto isolate = v8::Isolate::GetCurrent();
567+
isolate_ = v8::Isolate::GetCurrent();
570568
v8::Local<v8::ArrayBuffer> buffer =
571-
v8::ArrayBuffer::New(isolate, sizeof(uint32_t) * kFieldCount);
569+
v8::ArrayBuffer::New(isolate_, sizeof(uint32_t) * kFieldCount);
572570

573571
v8::Local<v8::Uint32Array> jsArray =
574572
v8::Uint32Array::New(buffer, 0, kFieldCount);
575573
fields_ = static_cast<uint32_t*>(buffer->GetBackingStore()->Data());
576-
jsArray_ = v8::Global<v8::Uint32Array>(isolate, jsArray);
574+
jsArray_ = v8::Global<v8::Uint32Array>(isolate_, jsArray);
577575
std::fill(fields_, fields_ + kFieldCount, 0);
578576

579577
if (collectAsyncId_) {
580-
isolate->AddGCPrologueCallback(&GCPrologueCallback, this);
581-
isolate->AddGCEpilogueCallback(&GCEpilogueCallback, this);
578+
isolate_->AddGCPrologueCallback(&GCPrologueCallback, this);
579+
isolate_->AddGCEpilogueCallback(&GCEpilogueCallback, this);
582580
}
583581
}
584582

585-
void WallProfiler::Dispose(Isolate* isolate, bool removeFromMap) {
583+
void WallProfiler::Dispose(bool removeFromMap) {
586584
if (cpuProfiler_ != nullptr) {
587585
cpuProfiler_->Dispose();
588586
cpuProfiler_ = nullptr;
589587

590588
if (removeFromMap) {
591-
g_profilers.RemoveProfiler(isolate, this);
589+
g_profilers.RemoveProfiler(isolate_, this);
592590
}
593591

594592
if (collectAsyncId_) {
595-
isolate->RemoveGCPrologueCallback(&GCPrologueCallback, this);
596-
isolate->RemoveGCEpilogueCallback(&GCEpilogueCallback, this);
593+
isolate_->RemoveGCPrologueCallback(&GCPrologueCallback, this);
594+
isolate_->RemoveGCEpilogueCallback(&GCEpilogueCallback, this);
597595
}
598596

599597
node::RemoveEnvironmentCleanupHook(
600-
isolate, &WallProfiler::CleanupHook, isolate);
598+
isolate_, &WallProfiler::CleanupHook, isolate_);
601599
}
602600
}
603601

@@ -738,8 +736,8 @@ Result WallProfiler::StartImpl() {
738736
: CollectionMode::kNoCollect);
739737
collectionMode_.store(collectionMode, std::memory_order_relaxed);
740738
started_ = true;
741-
auto isolate = Isolate::GetCurrent();
742-
node::AddEnvironmentCleanupHook(isolate, &WallProfiler::CleanupHook, isolate);
739+
node::AddEnvironmentCleanupHook(
740+
isolate_, &WallProfiler::CleanupHook, isolate_);
743741
return {};
744742
}
745743

@@ -786,8 +784,8 @@ v8::ProfilerId WallProfiler::StartInternal() {
786784
// we wait for one signal before starting a new profile which should leave
787785
// time to process in-flight tick samples.
788786
if (detectV8Bug_ && !workaroundV8Bug_) {
789-
cpuProfiler_->CollectSample(v8::Isolate::GetCurrent());
790-
cpuProfiler_->CollectSample(v8::Isolate::GetCurrent());
787+
cpuProfiler_->CollectSample(isolate_);
788+
cpuProfiler_->CollectSample(isolate_);
791789
}
792790

793791
return result.id;
@@ -933,7 +931,7 @@ Result WallProfiler::StopImpl(bool restart, v8::Local<v8::Value>& profile) {
933931
v8_profile->Delete();
934932

935933
if (!restart) {
936-
Dispose(v8::Isolate::GetCurrent(), true);
934+
Dispose(true);
937935
} else if (workaroundV8Bug_) {
938936
waitForSignal(callCount + 1);
939937
collectionMode_.store(withContexts_ ? CollectionMode::kCollectContexts
@@ -968,12 +966,11 @@ NAN_MODULE_INIT(WallProfiler::Init) {
968966
Nan::New("state").ToLocalChecked(),
969967
SharedArrayGetter);
970968

971-
PerIsolateData::For(Isolate::GetCurrent())
972-
->WallProfilerConstructor()
973-
.Reset(Nan::GetFunction(tpl).ToLocalChecked());
969+
auto isolate = Isolate::GetCurrent();
970+
PerIsolateData::For(isolate)->WallProfilerConstructor().Reset(
971+
Nan::GetFunction(tpl).ToLocalChecked());
974972
Nan::Set(target, className, Nan::GetFunction(tpl).ToLocalChecked());
975973

976-
auto isolate = v8::Isolate::GetCurrent();
977974
v8::PropertyAttribute ReadOnlyDontDelete =
978975
static_cast<v8::PropertyAttribute>(ReadOnly | DontDelete);
979976

@@ -992,28 +989,26 @@ NAN_MODULE_INIT(WallProfiler::Init) {
992989

993990
v8::CpuProfiler* WallProfiler::CreateV8CpuProfiler() {
994991
if (cpuProfiler_ == nullptr) {
995-
v8::Isolate* isolate = v8::Isolate::GetCurrent();
996-
997-
bool inserted = g_profilers.AddProfiler(isolate, this);
992+
bool inserted = g_profilers.AddProfiler(isolate_, this);
998993

999994
if (!inserted) {
1000995
// refuse to create a new profiler if one is already active
1001996
return nullptr;
1002997
}
1003-
cpuProfiler_ = v8::CpuProfiler::New(isolate);
998+
cpuProfiler_ = v8::CpuProfiler::New(isolate_);
1004999
cpuProfiler_->SetSamplingInterval(
10051000
std::chrono::microseconds(samplingPeriod_).count());
10061001
}
10071002
return cpuProfiler_;
10081003
}
10091004

1010-
v8::Local<v8::Value> WallProfiler::GetContext(Isolate* isolate) {
1005+
v8::Local<v8::Value> WallProfiler::GetContext() {
10111006
auto context = *curContext_.load(std::memory_order_relaxed);
1012-
if (!context) return v8::Undefined(isolate);
1013-
return context->Get(isolate);
1007+
if (!context) return v8::Undefined(isolate_);
1008+
return context->Get(isolate_);
10141009
}
10151010

1016-
void WallProfiler::SetContext(Isolate* isolate, Local<Value> value) {
1011+
void WallProfiler::SetContext(Local<Value> value) {
10171012
// Need to be careful here, because we might be interrupted by a
10181013
// signal handler that will make use of curContext_.
10191014
// Update of shared_ptr is not atomic, so instead we use a pointer
@@ -1024,7 +1019,7 @@ void WallProfiler::SetContext(Isolate* isolate, Local<Value> value) {
10241019
? &context2_
10251020
: &context1_;
10261021
if (!value->IsNullOrUndefined()) {
1027-
*newCurContext = std::make_shared<Global<Value>>(isolate, value);
1022+
*newCurContext = std::make_shared<Global<Value>>(isolate_, value);
10281023
} else {
10291024
newCurContext->reset();
10301025
}
@@ -1034,17 +1029,17 @@ void WallProfiler::SetContext(Isolate* isolate, Local<Value> value) {
10341029

10351030
NAN_GETTER(WallProfiler::GetContext) {
10361031
auto profiler = Nan::ObjectWrap::Unwrap<WallProfiler>(info.This());
1037-
info.GetReturnValue().Set(profiler->GetContext(info.GetIsolate()));
1032+
info.GetReturnValue().Set(profiler->GetContext());
10381033
}
10391034

10401035
NAN_SETTER(WallProfiler::SetContext) {
10411036
auto profiler = Nan::ObjectWrap::Unwrap<WallProfiler>(info.This());
1042-
profiler->SetContext(info.GetIsolate(), value);
1037+
profiler->SetContext(value);
10431038
}
10441039

10451040
NAN_GETTER(WallProfiler::SharedArrayGetter) {
10461041
auto profiler = Nan::ObjectWrap::Unwrap<WallProfiler>(info.This());
1047-
info.GetReturnValue().Set(profiler->jsArray_.Get(v8::Isolate::GetCurrent()));
1042+
info.GetReturnValue().Set(profiler->GetSharedArray());
10481043
}
10491044

10501045
NAN_METHOD(WallProfiler::V8ProfilerStuckEventLoopDetected) {
@@ -1071,7 +1066,7 @@ double GetAsyncIdNoGC(v8::Isolate* isolate) {
10711066
#endif
10721067
}
10731068

1074-
double WallProfiler::GetAsyncId(v8::Isolate* isolate) {
1069+
double WallProfiler::GetAsyncId() {
10751070
if (!collectAsyncId_) {
10761071
return -1;
10771072
}
@@ -1080,14 +1075,14 @@ double WallProfiler::GetAsyncId(v8::Isolate* isolate) {
10801075
if (curGcCount > 0) {
10811076
return gcAsyncId;
10821077
}
1083-
return GetAsyncIdNoGC(isolate);
1078+
return GetAsyncIdNoGC(isolate_);
10841079
}
10851080

1086-
void WallProfiler::OnGCStart(v8::Isolate* isolate) {
1081+
void WallProfiler::OnGCStart() {
10871082
auto curCount = gcCount.load(std::memory_order_relaxed);
10881083
std::atomic_signal_fence(std::memory_order_acquire);
10891084
if (curCount == 0) {
1090-
gcAsyncId = GetAsyncIdNoGC(isolate);
1085+
gcAsyncId = GetAsyncIdNoGC(isolate_);
10911086
}
10921087
gcCount.store(curCount + 1, std::memory_order_relaxed);
10931088
std::atomic_signal_fence(std::memory_order_release);

bindings/profilers/wall.hh

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class WallProfiler : public Nan::ObjectWrap {
4747

4848
std::chrono::microseconds samplingPeriod_{0};
4949
v8::CpuProfiler* cpuProfiler_ = nullptr;
50+
v8::Isolate* isolate_ = nullptr;
51+
5052
// TODO: Investigate use of v8::Persistent instead of shared_ptr<Global> to
5153
// avoid heap allocation. Need to figure out the right move/copy semantics in
5254
// and out of the ring buffer.
@@ -93,7 +95,7 @@ class WallProfiler : public Nan::ObjectWrap {
9395
ContextBuffer contexts_;
9496

9597
~WallProfiler() = default;
96-
void Dispose(v8::Isolate* isolate, bool removeFromMap);
98+
void Dispose(bool removeFromMap);
9799

98100
// A new CPU profiler object will be created each time profiling is started
99101
// to work around https://bugs.chromium.org/p/v8/issues/detail?id=11051.
@@ -105,7 +107,11 @@ class WallProfiler : public Nan::ObjectWrap {
105107

106108
bool waitForSignal(uint64_t targetCallCount = 0);
107109
static void CleanupHook(void* data);
108-
void Cleanup(v8::Isolate* isolate);
110+
void Cleanup();
111+
112+
v8::Local<v8::Uint32Array> GetSharedArray() const {
113+
return jsArray_.Get(isolate_);
114+
}
109115

110116
public:
111117
/**
@@ -124,8 +130,8 @@ class WallProfiler : public Nan::ObjectWrap {
124130
bool collectAsyncId,
125131
bool isMainThread);
126132

127-
v8::Local<v8::Value> GetContext(v8::Isolate*);
128-
void SetContext(v8::Isolate*, v8::Local<v8::Value>);
133+
v8::Local<v8::Value> GetContext();
134+
void SetContext(v8::Local<v8::Value>);
129135
void PushContext(int64_t time_from,
130136
int64_t time_to,
131137
int64_t cpu_time,
@@ -155,8 +161,8 @@ class WallProfiler : public Nan::ObjectWrap {
155161
return threadCpuStopWatch_.GetAndReset();
156162
}
157163

158-
double GetAsyncId(v8::Isolate* isolate);
159-
void OnGCStart(v8::Isolate* isolate);
164+
double GetAsyncId();
165+
void OnGCStart();
160166
void OnGCEnd();
161167

162168
static NAN_METHOD(New);

0 commit comments

Comments
 (0)