Skip to content

Commit 4788019

Browse files
committed
Convert execution async resource to use a stack
1 parent d0d7522 commit 4788019

File tree

6 files changed

+50
-27
lines changed

6 files changed

+50
-27
lines changed

lib/async_hooks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class AsyncResource {
171171

172172
runInAsyncScope(fn, thisArg, ...args) {
173173
const asyncId = this[async_id_symbol];
174-
emitBefore(asyncId, this[trigger_async_id_symbol]);
174+
emitBefore(asyncId, this[trigger_async_id_symbol], this);
175175

176176
const ret = thisArg === undefined ?
177177
fn(...args) :

lib/internal/async_hooks.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ const active_hooks = {
7676
const { registerDestroyHook } = async_wrap;
7777
const { enqueueMicrotask } = internalBinding('task_queue');
7878

79-
const { executionAsyncResource, setExecutionAsyncResource } = async_wrap;
79+
const { executionAsyncResource, pushExecutionAsyncResource,
80+
popExecutionAsyncResource } = async_wrap;
8081

8182
// Each constant tracks how many callbacks there are for any given step of
8283
// async execution. These are tracked so if the user didn't include callbacks
@@ -360,7 +361,7 @@ function emitBeforeScript(asyncId, triggerAsyncId, resource) {
360361
validateAsyncId(asyncId, 'asyncId');
361362
validateAsyncId(triggerAsyncId, 'triggerAsyncId');
362363

363-
setExecutionAsyncResource(resource);
364+
pushExecutionAsyncResource(resource);
364365
pushAsyncIds(asyncId, triggerAsyncId);
365366

366367
if (async_hook_fields[kBefore] > 0)
@@ -374,8 +375,7 @@ function emitAfterScript(asyncId) {
374375
if (async_hook_fields[kAfter] > 0)
375376
emitAfterNative(asyncId);
376377

377-
setExecutionAsyncResource(null);
378-
378+
popExecutionAsyncResource();
379379
popAsyncIds(asyncId);
380380
}
381381

@@ -477,7 +477,8 @@ module.exports = {
477477
emitAfter: emitAfterScript,
478478
emitDestroy: emitDestroyScript,
479479
registerDestroyHook,
480-
setExecutionAsyncResource,
480+
pushExecutionAsyncResource,
481+
popExecutionAsyncResource,
481482
nativeHooks: {
482483
init: emitInitNative,
483484
before: emitBeforeNative,

lib/internal/timers.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ const {
9797
emitBefore,
9898
emitAfter,
9999
emitDestroy,
100-
setExecutionAsyncResource
100+
popExecutionAsyncResource,
101+
pushExecutionAsyncResource,
101102
} = require('internal/async_hooks');
102103

103104
// Symbols for storing async id state.
@@ -539,7 +540,7 @@ function getTimerCallbacks(runNextTicks) {
539540
else
540541
timer._onTimeout(...args);
541542
} finally {
542-
setExecutionAsyncResource(null);
543+
popExecutionAsyncResource();
543544
if (timer._repeat && timer._idleTimeout !== -1) {
544545
timer._idleTimeout = timer._repeat;
545546
if (start === undefined)
@@ -555,6 +556,7 @@ function getTimerCallbacks(runNextTicks) {
555556
}
556557
timer._destroyed = true;
557558
}
559+
pushExecutionAsyncResource(timer);
558560
}
559561

560562
emitAfter(asyncId);

src/async_wrap.cc

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ void AsyncWrap::EmitTraceEventBefore() {
148148
void AsyncWrap::EmitBefore(Environment* env, double async_id,
149149
v8::Local<v8::Object> resource) {
150150
v8::Local<v8::Context> context = env->isolate()->GetCurrentContext();
151-
env->async_hooks()->set_execution_async_resource(resource);
151+
env->async_hooks()->push_execution_async_resource(resource);
152152

153153
Emit(env, async_id, AsyncHooks::kBefore,
154154
env->async_hooks_before_function());
@@ -180,7 +180,7 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
180180
Emit(env, async_id, AsyncHooks::kAfter,
181181
env->async_hooks_after_function());
182182

183-
env->async_hooks()->clear_execution_async_resource();
183+
env->async_hooks()->pop_execution_async_resource();
184184
}
185185

186186
class PromiseWrap : public AsyncWrap {
@@ -266,10 +266,14 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
266266

267267
// needed for async functions :/
268268
// the top level will not emit before and after
269-
env->async_hooks()->set_execution_async_resource(wrap->object());
269+
env->async_hooks()->push_execution_async_resource(wrap->object());
270270
}
271271
}
272272

273+
if (type == PromiseHookType::kResolve && !parent->IsPromise()) {
274+
env->async_hooks()->pop_execution_async_resource();
275+
}
276+
273277
if (wrap == nullptr) return;
274278

275279
if (type == PromiseHookType::kBefore) {
@@ -402,11 +406,19 @@ static void GetExecutionAsyncResource(const FunctionCallbackInfo<Value>& args) {
402406
args.GetReturnValue().Set(env->async_hooks()->get_execution_async_resource());
403407
}
404408

405-
static void SetExecutionAsyncResource(const FunctionCallbackInfo<Value>& args) {
409+
static void PushExecutionAsyncResource(
410+
const FunctionCallbackInfo<Value>& args) {
411+
Isolate* isolate = args.GetIsolate();
412+
Environment* env = Environment::GetCurrent(args);
413+
v8::Local<v8::Context> context = isolate->GetCurrentContext();
414+
env->async_hooks()->push_execution_async_resource(args[0]);
415+
}
416+
417+
static void PopExecutionAsyncResource(const FunctionCallbackInfo<Value>& args) {
406418
Isolate* isolate = args.GetIsolate();
407419
Environment* env = Environment::GetCurrent(args);
408420
v8::Local<v8::Context> context = isolate->GetCurrentContext();
409-
env->async_hooks()->set_execution_async_resource(args[0]);
421+
env->async_hooks()->pop_execution_async_resource();
410422
}
411423

412424
void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) {
@@ -497,10 +509,12 @@ void AsyncWrap::Initialize(Local<Object> target,
497509
env->SetMethod(target, "disablePromiseHook", DisablePromiseHook);
498510
env->SetMethod(target, "registerDestroyHook", RegisterDestroyHook);
499511
env->SetMethod(target, "executionAsyncResource", GetExecutionAsyncResource);
500-
env->SetMethod(target, "setExecutionAsyncResource",
501-
SetExecutionAsyncResource);
512+
env->SetMethod(target, "pushExecutionAsyncResource",
513+
PushExecutionAsyncResource);
514+
env->SetMethod(target, "popExecutionAsyncResource",
515+
PopExecutionAsyncResource);
502516

503-
env->async_hooks()->clear_execution_async_resource();
517+
env->async_hooks()->push_execution_async_resource(v8::Object::New(isolate));
504518

505519
PropertyAttribute ReadOnlyDontDelete =
506520
static_cast<PropertyAttribute>(ReadOnly | DontDelete);

src/env-inl.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ inline MultiIsolatePlatform* IsolateData::platform() const {
6767
inline AsyncHooks::AsyncHooks()
6868
: async_ids_stack_(env()->isolate(), 16 * 2),
6969
fields_(env()->isolate(), kFieldsCount),
70-
async_id_fields_(env()->isolate(), kUidFieldsCount),
71-
execution_async_resource_(env()->isolate(), v8::Null(env()->isolate())) {
70+
async_id_fields_(env()->isolate(), kUidFieldsCount) {
7271
v8::HandleScope handle_scope(env()->isolate());
7372

7473
// Always perform async_hooks checks, not just when async_hooks is enabled.
@@ -207,17 +206,23 @@ inline AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() {
207206
old_default_trigger_async_id_;
208207
}
209208

210-
inline void AsyncHooks::set_execution_async_resource(
209+
inline void AsyncHooks::push_execution_async_resource(
211210
v8::Local<v8::Value> execution_async_resource) {
212-
execution_async_resource_.Reset(env()->isolate(), execution_async_resource);
211+
execution_async_resources_.push(v8::Global<v8::Value>(
212+
env()->isolate(), execution_async_resource));
213213
}
214214

215-
inline v8::Local<v8::Value> AsyncHooks::get_execution_async_resource() {
216-
return execution_async_resource_.Get(env()->isolate());
215+
inline void AsyncHooks::pop_execution_async_resource() {
216+
if (execution_async_resources_.size()) {
217+
execution_async_resources_.pop();
218+
}
217219
}
218220

219-
inline void AsyncHooks::clear_execution_async_resource() {
220-
execution_async_resource_.Reset();
221+
inline v8::Local<v8::Value> AsyncHooks::get_execution_async_resource() {
222+
if (!execution_async_resources_.size()) {
223+
return v8::Null(env()->isolate());
224+
}
225+
return execution_async_resources_.top().Get(env()->isolate());
221226
}
222227

223228
Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) {

src/env.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <cstdint>
4646
#include <functional>
4747
#include <list>
48+
#include <stack>
4849
#include <unordered_map>
4950
#include <unordered_set>
5051
#include <vector>
@@ -684,10 +685,10 @@ class AsyncHooks : public MemoryRetainer {
684685
inline bool pop_async_id(double async_id);
685686
inline void clear_async_id_stack(); // Used in fatal exceptions.
686687

687-
inline void set_execution_async_resource(
688+
inline void push_execution_async_resource(
688689
v8::Local<v8::Value> execution_async_resource_);
690+
inline void pop_execution_async_resource();
689691
inline v8::Local<v8::Value> get_execution_async_resource();
690-
inline void clear_execution_async_resource();
691692

692693
AsyncHooks(const AsyncHooks&) = delete;
693694
AsyncHooks& operator=(const AsyncHooks&) = delete;
@@ -732,7 +733,7 @@ class AsyncHooks : public MemoryRetainer {
732733

733734
void grow_async_ids_stack();
734735

735-
v8::Persistent<v8::Value> execution_async_resource_;
736+
std::stack<v8::Global<v8::Value>> execution_async_resources_;
736737
};
737738

738739
class ImmediateInfo : public MemoryRetainer {

0 commit comments

Comments
 (0)