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

[debug] Consolidate promise stack runtime functions.

Following up on https://crrev.com/c/3383775 I realized that we could
just use the existing %DebugPopPromise and %DebugPushPromise runtime
functions, which do exactly the same job as %DebugAsyncFunctionFinished
and %DebugAsyncFunctionResumed, and are already used in other places of
promise instrumentation.

We can also remove %DebugAsyncFunctionEntered and utilize the logic in
NewJSPromise() to deal with the various promise hooks, and otherwise go
with %DebugPushPromise for the debugger side.

Bug: chromium:1280519
Change-Id: I79c77236f19c8783161c1eee36d2a16d52c60e82
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3386382Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78626}
parent 1e42a27f
......@@ -46,7 +46,7 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure(
{
TNode<JSPromise> promise = LoadObjectField<JSPromise>(
async_function_object, JSAsyncFunctionObject::kPromiseOffset);
CallRuntime(Runtime::kDebugAsyncFunctionResumed, context, promise);
CallRuntime(Runtime::kDebugPushPromise, context, promise);
Goto(&if_instrumentation_done);
}
BIND(&if_instrumentation_done);
......@@ -103,21 +103,10 @@ TF_BUILTIN(AsyncFunctionEnter, AsyncFunctionBuiltinsAssembler) {
RootIndex::kUndefinedValue);
// Allocate and initialize the promise.
TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<JSFunction> promise_function =
CAST(LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX));
TNode<Map> promise_map = LoadObjectField<Map>(
promise_function, JSFunction::kPrototypeOrInitialMapOffset);
TNode<JSPromise> promise = UncheckedCast<JSPromise>(
AllocateInNewSpace(JSPromise::kSizeWithEmbedderFields));
StoreMapNoWriteBarrier(promise, promise_map);
StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset,
RootIndex::kEmptyFixedArray);
StoreObjectFieldRoot(promise, JSPromise::kElementsOffset,
RootIndex::kEmptyFixedArray);
PromiseInit(promise);
TNode<JSPromise> promise = NewJSPromise(context);
// Allocate and initialize the async function object.
TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<Map> async_function_object_map = CAST(LoadContextElement(
native_context, Context::ASYNC_FUNCTION_OBJECT_MAP_INDEX));
TNode<JSAsyncFunctionObject> async_function_object =
......@@ -152,22 +141,15 @@ TF_BUILTIN(AsyncFunctionEnter, AsyncFunctionBuiltinsAssembler) {
StoreObjectFieldNoWriteBarrier(
async_function_object, JSAsyncFunctionObject::kPromiseOffset, promise);
RunContextPromiseHookInit(context, promise, UndefinedConstant());
// Fire promise hooks if enabled and push the Promise under construction
// in an async function on the catch prediction stack to handle exceptions
// thrown before the first await.
Label if_instrumentation(this, Label::kDeferred),
if_instrumentation_done(this);
Branch(IsIsolatePromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
&if_instrumentation, &if_instrumentation_done);
BIND(&if_instrumentation);
{
CallRuntime(Runtime::kDebugAsyncFunctionEntered, context, promise);
Goto(&if_instrumentation_done);
}
BIND(&if_instrumentation_done);
// While we are executing an async function, we need to have the implicit
// promise on the stack to get the catch prediction right, even before we
// awaited for the first time.
Label if_debugging(this);
GotoIf(IsDebugActive(), &if_debugging);
Return(async_function_object);
BIND(&if_debugging);
CallRuntime(Runtime::kDebugPushPromise, context, promise);
Return(async_function_object);
}
......@@ -185,12 +167,13 @@ TF_BUILTIN(AsyncFunctionReject, AsyncFunctionBuiltinsAssembler) {
CallBuiltin(Builtin::kRejectPromise, context, promise, reason,
FalseConstant());
Label if_debugging(this, Label::kDeferred);
Label if_debugging(this);
GotoIf(IsDebugActive(), &if_debugging);
Return(promise);
BIND(&if_debugging);
TailCallRuntime(Runtime::kDebugAsyncFunctionFinished, context, promise);
CallRuntime(Runtime::kDebugPopPromise, context);
Return(promise);
}
TF_BUILTIN(AsyncFunctionResolve, AsyncFunctionBuiltinsAssembler) {
......@@ -203,12 +186,13 @@ TF_BUILTIN(AsyncFunctionResolve, AsyncFunctionBuiltinsAssembler) {
CallBuiltin(Builtin::kResolvePromise, context, promise, value);
Label if_debugging(this, Label::kDeferred);
Label if_debugging(this);
GotoIf(IsDebugActive(), &if_debugging);
Return(promise);
BIND(&if_debugging);
TailCallRuntime(Runtime::kDebugAsyncFunctionFinished, context, promise);
CallRuntime(Runtime::kDebugPopPromise, context);
Return(promise);
}
// AsyncFunctionReject and AsyncFunctionResolve are both required to return
......
......@@ -4899,15 +4899,6 @@ void Isolate::RunPromiseHookForAsyncEventDelegate(PromiseHookType type,
}
}
void Isolate::OnAsyncFunctionEntered(Handle<JSPromise> promise) {
if (HasIsolatePromiseHooks()) {
DCHECK_NE(nullptr, promise_hook_);
promise_hook_(PromiseHookType::kInit, v8::Utils::PromiseToLocal(promise),
v8::Utils::ToLocal(factory()->undefined_value()));
}
OnAsyncFunctionResumed(promise);
}
void Isolate::OnAsyncFunctionSuspended(Handle<JSPromise> promise,
Handle<JSPromise> parent) {
DCHECK_EQ(0, promise->async_task_id());
......@@ -4929,21 +4920,6 @@ void Isolate::OnAsyncFunctionSuspended(Handle<JSPromise> promise,
}
}
void Isolate::OnAsyncFunctionResumed(Handle<JSPromise> promise) {
if (debug()->is_active()) {
// While we are executing an async function, we need to
// have the implicit promise on the stack to get the catch
// prediction right.
PushPromise(promise);
}
}
void Isolate::OnAsyncFunctionFinished(Handle<JSPromise> promise) {
if (debug()->is_active()) {
PopPromise();
}
}
void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
promise_reject_callback_ = callback;
}
......
......@@ -950,11 +950,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
}
// Async function instrumentation support.
void OnAsyncFunctionEntered(Handle<JSPromise> promise);
void OnAsyncFunctionSuspended(Handle<JSPromise> promise,
Handle<JSPromise> parent);
void OnAsyncFunctionResumed(Handle<JSPromise> promise);
void OnAsyncFunctionFinished(Handle<JSPromise> promise);
// Re-throw an exception. This involves no error reporting since error
// reporting was handled when the exception was thrown originally.
......
......@@ -818,14 +818,6 @@ RUNTIME_FUNCTION(Runtime_IncBlockCounter) {
UNREACHABLE(); // Never called. See the IncBlockCounter builtin instead.
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionEntered) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->OnAsyncFunctionEntered(promise);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
DCHECK_EQ(4, args.length());
HandleScope scope(isolate);
......@@ -866,22 +858,6 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
return *throwaway;
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->OnAsyncFunctionResumed(promise);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->OnAsyncFunctionFinished(promise);
return *promise;
}
RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -123,10 +123,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_DEBUG(F, I) \
F(ClearStepping, 0, 1) \
F(CollectGarbage, 1, 1) \
F(DebugAsyncFunctionEntered, 1, 1) \
F(DebugAsyncFunctionSuspended, 4, 1) \
F(DebugAsyncFunctionResumed, 1, 1) \
F(DebugAsyncFunctionFinished, 2, 1) \
F(DebugBreakAtEntry, 1, 1) \
F(DebugCollectCoverage, 0, 1) \
F(DebugGetLoadedScriptIds, 0, 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