Commit 302a5d20 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by V8 LUCI CQ

[async-await] Further simplify `await` and its instrumentation.

Following up on https://crrev.com/c/3383775 we are now able to further
simplify the implementation of `await` and its instrumentation (for both
debugger and promise hooks), which aligns the implementation more
closely with the spec text and removes a whole bunch of unnecessary
code.

This also moves the `await` instrumentation into runtime-debug.cc along
with the other instrumentation methods for async functions.

Bug: chromium:1280519, chromium:1277451, chromium:1246867
Change-Id: I3fb543c76229091b502f3188da962784977158ab
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3386597
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78610}
parent fec4bd06
...@@ -22,7 +22,7 @@ class ValueUnwrapContext { ...@@ -22,7 +22,7 @@ class ValueUnwrapContext {
} // namespace } // namespace
TNode<Object> AsyncBuiltinsAssembler::AwaitOld( TNode<Object> AsyncBuiltinsAssembler::Await(
TNode<Context> context, TNode<JSGeneratorObject> generator, TNode<Context> context, TNode<JSGeneratorObject> generator,
TNode<Object> value, TNode<JSPromise> outer_promise, TNode<Object> value, TNode<JSPromise> outer_promise,
TNode<SharedFunctionInfo> on_resolve_sfi, TNode<SharedFunctionInfo> on_resolve_sfi,
...@@ -30,92 +30,57 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOld( ...@@ -30,92 +30,57 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOld(
TNode<Oddball> is_predicted_as_caught) { TNode<Oddball> is_predicted_as_caught) {
const TNode<NativeContext> native_context = LoadNativeContext(context); const TNode<NativeContext> native_context = LoadNativeContext(context);
static const int kClosureContextSize = // We do the `PromiseResolve(%Promise%,value)` avoiding to unnecessarily
FixedArray::SizeFor(Context::MIN_CONTEXT_EXTENDED_SLOTS); // create wrapper promises. Now if {value} is already a promise with the
TNode<Context> closure_context = // intrinsics %Promise% constructor as its "constructor", we don't need
UncheckedCast<Context>(AllocateInNewSpace(kClosureContextSize)); // to allocate the wrapper promise.
{ {
// Initialize the await context, storing the {generator} as extension. TVARIABLE(Object, var_value, value);
TNode<Map> map = CAST( Label if_slow_path(this, Label::kDeferred), if_done(this),
LoadContextElement(native_context, Context::AWAIT_CONTEXT_MAP_INDEX)); if_slow_constructor(this, Label::kDeferred);
StoreMapNoWriteBarrier(closure_context, map); GotoIf(TaggedIsSmi(value), &if_slow_path);
StoreObjectFieldNoWriteBarrier( TNode<HeapObject> value_object = CAST(value);
closure_context, Context::kLengthOffset, const TNode<Map> value_map = LoadMap(value_object);
SmiConstant(Context::MIN_CONTEXT_EXTENDED_SLOTS)); GotoIfNot(IsJSPromiseMap(value_map), &if_slow_path);
const TNode<Object> empty_scope_info = // We can skip the "constructor" lookup on {value} if it's [[Prototype]]
LoadContextElement(native_context, Context::SCOPE_INFO_INDEX); // is the (initial) Promise.prototype and the @@species protector is
StoreContextElementNoWriteBarrier( // intact, as that guards the lookup path for "constructor" on
closure_context, Context::SCOPE_INFO_INDEX, empty_scope_info); // JSPromise instances which have the (initial) Promise.prototype.
StoreContextElementNoWriteBarrier(closure_context, Context::PREVIOUS_INDEX, const TNode<Object> promise_prototype =
native_context); LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
StoreContextElementNoWriteBarrier(closure_context, Context::EXTENSION_INDEX, GotoIfNot(TaggedEqual(LoadMapPrototype(value_map), promise_prototype),
generator); &if_slow_constructor);
} Branch(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor,
&if_done);
// Let promiseCapability be ! NewPromiseCapability(%Promise%). // At this point, {value} doesn't have the initial promise prototype or
const TNode<JSFunction> promise_fun = // the promise @@species protector was invalidated, but {value} could still
CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX)); // have the %Promise% as its "constructor", so we need to check that as
CSA_DCHECK(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun))); // well.
const TNode<Map> promise_map = CAST( BIND(&if_slow_constructor);
LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset));
// Assert that the JSPromise map has an instance size is
// JSPromise::kSizeWithEmbedderFields.
CSA_DCHECK(this,
IntPtrEqual(LoadMapInstanceSizeInWords(promise_map),
IntPtrConstant(JSPromise::kSizeWithEmbedderFields /
kTaggedSize)));
TNode<JSPromise> promise;
{ {
// Allocate and initialize Promise const TNode<Object> value_constructor = GetProperty(
TNode<HeapObject> wrapped_value = context, value, isolate()->factory()->constructor_string());
AllocateInNewSpace(JSPromise::kSizeWithEmbedderFields); const TNode<Object> promise_function =
StoreMapNoWriteBarrier(wrapped_value, promise_map); LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
StoreObjectFieldRoot(wrapped_value, JSPromise::kPropertiesOrHashOffset, Branch(TaggedEqual(value_constructor, promise_function), &if_done,
RootIndex::kEmptyFixedArray); &if_slow_path);
StoreObjectFieldRoot(wrapped_value, JSPromise::kElementsOffset,
RootIndex::kEmptyFixedArray);
promise = CAST(wrapped_value);
PromiseInit(promise);
} }
// Allocate and initialize resolve handler BIND(&if_slow_path);
TNode<HeapObject> on_resolve = {
AllocateInNewSpace(JSFunction::kSizeWithoutPrototype); // We need to mark the {value} wrapper as having {outer_promise}
InitializeNativeClosure(closure_context, native_context, on_resolve, // as its parent, which is why we need to inline a good chunk of
on_resolve_sfi); // logic from the `PromiseResolve` builtin here.
var_value = NewJSPromise(native_context, outer_promise);
// Allocate and initialize reject handler CallBuiltin(Builtin::kResolvePromise, native_context, var_value.value(),
TNode<HeapObject> on_reject = value);
AllocateInNewSpace(JSFunction::kSizeWithoutPrototype); Goto(&if_done);
InitializeNativeClosure(closure_context, native_context, on_reject, }
on_reject_sfi);
TVARIABLE(HeapObject, var_throwaway, UndefinedConstant());
RunContextPromiseHookInit(context, promise, outer_promise);
InitAwaitPromise(Runtime::kAwaitPromisesInitOld, context, value, promise,
outer_promise, on_reject, is_predicted_as_caught,
&var_throwaway);
// Perform ! Call(promiseCapability.[[Resolve]], undefined, « promise »).
CallBuiltin(Builtin::kResolvePromise, context, promise, value);
return CallBuiltin(Builtin::kPerformPromiseThen, context, promise, on_resolve,
on_reject, var_throwaway.value());
}
TNode<Object> AsyncBuiltinsAssembler::AwaitOptimized(
TNode<Context> context, TNode<JSGeneratorObject> generator,
TNode<JSPromise> promise, TNode<JSPromise> outer_promise,
TNode<SharedFunctionInfo> on_resolve_sfi,
TNode<SharedFunctionInfo> on_reject_sfi,
TNode<Oddball> is_predicted_as_caught) {
const TNode<NativeContext> native_context = LoadNativeContext(context);
// 2. Let promise be ? PromiseResolve(« promise »). BIND(&if_done);
// We skip this step, because promise is already guaranteed to be a value = var_value.value();
// JSPRomise at this point. }
static const int kClosureContextSize = static const int kClosureContextSize =
FixedArray::SizeFor(Context::MIN_CONTEXT_EXTENDED_SLOTS); FixedArray::SizeFor(Context::MIN_CONTEXT_EXTENDED_SLOTS);
...@@ -151,107 +116,37 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOptimized( ...@@ -151,107 +116,37 @@ TNode<Object> AsyncBuiltinsAssembler::AwaitOptimized(
InitializeNativeClosure(closure_context, native_context, on_reject, InitializeNativeClosure(closure_context, native_context, on_reject,
on_reject_sfi); on_reject_sfi);
TVARIABLE(HeapObject, var_throwaway, UndefinedConstant());
InitAwaitPromise(Runtime::kAwaitPromisesInit, context, promise, promise,
outer_promise, on_reject, is_predicted_as_caught,
&var_throwaway);
return CallBuiltin(Builtin::kPerformPromiseThen, native_context, promise,
on_resolve, on_reject, var_throwaway.value());
}
void AsyncBuiltinsAssembler::InitAwaitPromise(
Runtime::FunctionId id, TNode<Context> context, TNode<Object> value,
TNode<Object> promise, TNode<Object> outer_promise,
TNode<HeapObject> on_reject, TNode<Oddball> is_predicted_as_caught,
TVariable<HeapObject>* var_throwaway) {
// Deal with PromiseHooks and debug support in the runtime. This // Deal with PromiseHooks and debug support in the runtime. This
// also allocates the throwaway promise, which is only needed in // also allocates the throwaway promise, which is only needed in
// case of PromiseHooks or debugging. // case of PromiseHooks or debugging.
Label if_debugging(this, Label::kDeferred), TVARIABLE(Object, var_throwaway, UndefinedConstant());
if_promise_hook(this, Label::kDeferred), Label if_instrumentation(this, Label::kDeferred),
not_debugging(this), if_instrumentation_done(this);
do_nothing(this);
TNode<Uint32T> promiseHookFlags = PromiseHookFlags(); TNode<Uint32T> promiseHookFlags = PromiseHookFlags();
Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate( GotoIf(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(
promiseHookFlags), &if_debugging, &not_debugging); promiseHookFlags),
BIND(&if_debugging); &if_instrumentation);
*var_throwaway =
CAST(CallRuntime(id, context, value, promise,
outer_promise, on_reject, is_predicted_as_caught));
Goto(&do_nothing);
BIND(&not_debugging);
#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS #ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
// This call to NewJSPromise is to keep behaviour parity with what happens // This call to NewJSPromise is to keep behaviour parity with what happens
// in Runtime::kAwaitPromisesInit above if native hooks are set. It will // in Runtime::kDebugAsyncFunctionSuspended below if native hooks are set.
// create a throwaway promise that will trigger an init event and will get // It creates a throwaway promise that will trigger an init event and get
// passed into Builtin::kPerformPromiseThen below. // passed into Builtin::kPerformPromiseThen below.
Branch(IsContextPromiseHookEnabled(promiseHookFlags), &if_promise_hook, GotoIfNot(IsContextPromiseHookEnabled(promiseHookFlags),
&do_nothing); &if_instrumentation_done);
BIND(&if_promise_hook); var_throwaway = NewJSPromise(context, value);
*var_throwaway = NewJSPromise(context, promise);
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS #endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
Goto(&do_nothing); Goto(&if_instrumentation_done);
BIND(&do_nothing); BIND(&if_instrumentation);
}
TNode<Object> AsyncBuiltinsAssembler::Await(
TNode<Context> context, TNode<JSGeneratorObject> generator,
TNode<Object> value, TNode<JSPromise> outer_promise,
TNode<SharedFunctionInfo> on_resolve_sfi,
TNode<SharedFunctionInfo> on_reject_sfi,
TNode<Oddball> is_predicted_as_caught) {
TVARIABLE(Object, result);
Label if_old(this), if_new(this), done(this),
if_slow_constructor(this, Label::kDeferred);
// We do the `PromiseResolve(%Promise%,value)` avoiding to unnecessarily
// create wrapper promises. Now if {value} is already a promise with the
// intrinsics %Promise% constructor as its "constructor", we don't need
// to allocate the wrapper promise and can just use the `AwaitOptimized`
// logic.
GotoIf(TaggedIsSmi(value), &if_old);
TNode<HeapObject> value_object = CAST(value);
const TNode<Map> value_map = LoadMap(value_object);
GotoIfNot(IsJSPromiseMap(value_map), &if_old);
// We can skip the "constructor" lookup on {value} if it's [[Prototype]]
// is the (initial) Promise.prototype and the @@species protector is
// intact, as that guards the lookup path for "constructor" on
// JSPromise instances which have the (initial) Promise.prototype.
const TNode<NativeContext> native_context = LoadNativeContext(context);
const TNode<Object> promise_prototype =
LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
GotoIfNot(TaggedEqual(LoadMapPrototype(value_map), promise_prototype),
&if_slow_constructor);
Branch(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor, &if_new);
// At this point, {value} doesn't have the initial promise prototype or
// the promise @@species protector was invalidated, but {value} could still
// have the %Promise% as its "constructor", so we need to check that as well.
BIND(&if_slow_constructor);
{ {
const TNode<Object> value_constructor = var_throwaway =
GetProperty(context, value, isolate()->factory()->constructor_string()); CallRuntime(Runtime::kDebugAsyncFunctionSuspended, native_context,
const TNode<Object> promise_function = value, outer_promise, on_reject, is_predicted_as_caught);
LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); Goto(&if_instrumentation_done);
Branch(TaggedEqual(value_constructor, promise_function), &if_new, &if_old);
} }
BIND(&if_instrumentation_done);
BIND(&if_old); return CallBuiltin(Builtin::kPerformPromiseThen, native_context, value,
result = AwaitOld(context, generator, value, outer_promise, on_resolve_sfi, on_resolve, on_reject, var_throwaway.value());
on_reject_sfi, is_predicted_as_caught);
Goto(&done);
BIND(&if_new);
result =
AwaitOptimized(context, generator, CAST(value), outer_promise,
on_resolve_sfi, on_reject_sfi, is_predicted_as_caught);
Goto(&done);
BIND(&done);
return result.value();
} }
void AsyncBuiltinsAssembler::InitializeNativeClosure( void AsyncBuiltinsAssembler::InitializeNativeClosure(
......
...@@ -48,26 +48,6 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler { ...@@ -48,26 +48,6 @@ class AsyncBuiltinsAssembler : public PromiseBuiltinsAssembler {
TNode<SharedFunctionInfo> shared_info); TNode<SharedFunctionInfo> shared_info);
TNode<Context> AllocateAsyncIteratorValueUnwrapContext( TNode<Context> AllocateAsyncIteratorValueUnwrapContext(
TNode<NativeContext> native_context, TNode<Oddball> done); TNode<NativeContext> native_context, TNode<Oddball> done);
TNode<Object> AwaitOld(TNode<Context> context,
TNode<JSGeneratorObject> generator,
TNode<Object> value, TNode<JSPromise> outer_promise,
TNode<SharedFunctionInfo> on_resolve_sfi,
TNode<SharedFunctionInfo> on_reject_sfi,
TNode<Oddball> is_predicted_as_caught);
TNode<Object> AwaitOptimized(TNode<Context> context,
TNode<JSGeneratorObject> generator,
TNode<JSPromise> promise,
TNode<JSPromise> outer_promise,
TNode<SharedFunctionInfo> on_resolve_sfi,
TNode<SharedFunctionInfo> on_reject_sfi,
TNode<Oddball> is_predicted_as_caught);
void InitAwaitPromise(
Runtime::FunctionId id, TNode<Context> context, TNode<Object> value,
TNode<Object> promise, TNode<Object> outer_promise,
TNode<HeapObject> on_reject, TNode<Oddball> is_predicted_as_caught,
TVariable<HeapObject>* var_throwaway);
}; };
} // namespace internal } // namespace internal
......
...@@ -826,6 +826,46 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionEntered) { ...@@ -826,6 +826,46 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionEntered) {
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
} }
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
DCHECK_EQ(4, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 2);
CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 3);
// Allocate the throwaway promise and fire the appropriate init
// hook for the throwaway promise (passing the {promise} as its
// parent).
Handle<JSPromise> throwaway = isolate->factory()->NewJSPromiseWithoutHook();
isolate->OnAsyncFunctionSuspended(throwaway, promise);
// The Promise will be thrown away and not handled, but it
// shouldn't trigger unhandled reject events as its work is done
throwaway->set_has_handler(true);
// Enable proper debug support for promises.
if (isolate->debug()->is_active()) {
Object::SetProperty(isolate, reject_handler,
isolate->factory()->promise_forwarding_handler_symbol(),
isolate->factory()->true_value(),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
promise->set_handled_hint(is_predicted_as_caught);
// Mark the dependency to {outer_promise} in case the {throwaway}
// Promise is found on the Promise stack
Object::SetProperty(isolate, throwaway,
isolate->factory()->promise_handled_by_symbol(),
outer_promise, StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
}
return *throwaway;
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) { RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) {
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -836,7 +876,7 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) { ...@@ -836,7 +876,7 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) {
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) { RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
HandleScope shs(isolate); HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0); CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->OnAsyncFunctionFinished(promise); isolate->OnAsyncFunctionFinished(promise);
return *promise; return *promise;
......
...@@ -121,78 +121,6 @@ RUNTIME_FUNCTION(Runtime_PromiseHookInit) { ...@@ -121,78 +121,6 @@ RUNTIME_FUNCTION(Runtime_PromiseHookInit) {
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
} }
namespace {
Handle<JSPromise> AwaitPromisesInitCommon(Isolate* isolate,
Handle<Object> value,
Handle<JSPromise> promise,
Handle<JSPromise> outer_promise,
Handle<JSFunction> reject_handler,
bool is_predicted_as_caught) {
// Allocate the throwaway promise and fire the appropriate init
// hook for the throwaway promise (passing the {promise} as its
// parent).
Handle<JSPromise> throwaway = isolate->factory()->NewJSPromiseWithoutHook();
isolate->OnAsyncFunctionSuspended(throwaway, promise);
// The Promise will be thrown away and not handled, but it
// shouldn't trigger unhandled reject events as its work is done
throwaway->set_has_handler(true);
// Enable proper debug support for promises.
if (isolate->debug()->is_active()) {
if (value->IsJSPromise()) {
Object::SetProperty(
isolate, reject_handler,
isolate->factory()->promise_forwarding_handler_symbol(),
isolate->factory()->true_value(), StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Handle<JSPromise>::cast(value)->set_handled_hint(is_predicted_as_caught);
}
// Mark the dependency to {outer_promise} in case the {throwaway}
// Promise is found on the Promise stack
Object::SetProperty(isolate, throwaway,
isolate->factory()->promise_handled_by_symbol(),
outer_promise, StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
}
return throwaway;
}
} // namespace
RUNTIME_FUNCTION(Runtime_AwaitPromisesInit) {
DCHECK_EQ(5, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
reject_handler, is_predicted_as_caught);
}
RUNTIME_FUNCTION(Runtime_AwaitPromisesInitOld) {
DCHECK_EQ(5, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, outer_promise, 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, reject_handler, 3);
CONVERT_BOOLEAN_ARG_CHECKED(is_predicted_as_caught, 4);
// Fire the init hook for the wrapper promise (that we created for the
// {value} previously).
isolate->RunAllPromiseHooks(PromiseHookType::kInit, promise, outer_promise);
return *AwaitPromisesInitCommon(isolate, value, promise, outer_promise,
reject_handler, is_predicted_as_caught);
}
RUNTIME_FUNCTION(Runtime_PromiseHookBefore) { RUNTIME_FUNCTION(Runtime_PromiseHookBefore) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
......
...@@ -124,6 +124,7 @@ namespace internal { ...@@ -124,6 +124,7 @@ namespace internal {
F(ClearStepping, 0, 1) \ F(ClearStepping, 0, 1) \
F(CollectGarbage, 1, 1) \ F(CollectGarbage, 1, 1) \
F(DebugAsyncFunctionEntered, 1, 1) \ F(DebugAsyncFunctionEntered, 1, 1) \
F(DebugAsyncFunctionSuspended, 4, 1) \
F(DebugAsyncFunctionResumed, 1, 1) \ F(DebugAsyncFunctionResumed, 1, 1) \
F(DebugAsyncFunctionFinished, 2, 1) \ F(DebugAsyncFunctionFinished, 2, 1) \
F(DebugBreakAtEntry, 1, 1) \ F(DebugBreakAtEntry, 1, 1) \
...@@ -374,8 +375,6 @@ namespace internal { ...@@ -374,8 +375,6 @@ namespace internal {
F(PromiseHookAfter, 1, 1) \ F(PromiseHookAfter, 1, 1) \
F(PromiseHookBefore, 1, 1) \ F(PromiseHookBefore, 1, 1) \
F(PromiseHookInit, 2, 1) \ F(PromiseHookInit, 2, 1) \
F(AwaitPromisesInit, 5, 1) \
F(AwaitPromisesInitOld, 5, 1) \
F(PromiseRejectEventFromStack, 2, 1) \ F(PromiseRejectEventFromStack, 2, 1) \
F(PromiseRevokeReject, 1, 1) \ F(PromiseRevokeReject, 1, 1) \
F(PromiseStatus, 1, 1) \ F(PromiseStatus, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment