Commit e6f991c8 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[debugger] Properly remove promises from prediction stack upon `await`.

Make sure that we pop the async function promise from the catch
prediction stack when `await`ing inside an async function, and
push it back onto the stack when we're resuming execution. This
is to ensure that we don't leak memory when there are suspended
async functions while navigating away to a new page.

Bug: chromium:968603
Change-Id: I004715bc95d426958f1a89ce76c4856da1d4ceee
Cq-Include-Trybots: luci.chromium.try:linux-rel,win7-rel
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1655652
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62117}
parent 2dba18ed
......@@ -36,6 +36,21 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwaitResumeClosure(
TNode<JSAsyncFunctionObject> async_function_object =
CAST(LoadContextElement(context, Context::EXTENSION_INDEX));
// Push the promise for the {async_function_object} back onto the catch
// prediction stack to handle exceptions thrown after resuming from the
// await properly.
Label if_instrumentation(this, Label::kDeferred),
if_instrumentation_done(this);
Branch(IsDebugActive(), &if_instrumentation, &if_instrumentation_done);
BIND(&if_instrumentation);
{
TNode<JSPromise> promise = LoadObjectField<JSPromise>(
async_function_object, JSAsyncFunctionObject::kPromiseOffset);
CallRuntime(Runtime::kDebugAsyncFunctionResumed, context, promise);
Goto(&if_instrumentation_done);
}
BIND(&if_instrumentation_done);
// Inline version of GeneratorPrototypeNext / GeneratorPrototypeReturn with
// unnecessary runtime checks removed.
......
......@@ -750,6 +750,23 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionEntered) {
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->PopPromise();
isolate->OnAsyncFunctionStateChanged(promise, debug::kAsyncFunctionSuspended);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionResumed) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->PushPromise(promise);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
DCHECK_EQ(2, args.length());
HandleScope scope(isolate);
......@@ -763,14 +780,6 @@ RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
return *promise;
}
RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
isolate->OnAsyncFunctionStateChanged(promise, debug::kAsyncFunctionSuspended);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -115,8 +115,9 @@ namespace internal {
F(ClearStepping, 0, 1) \
F(CollectGarbage, 1, 1) \
F(DebugAsyncFunctionEntered, 1, 1) \
F(DebugAsyncFunctionFinished, 2, 1) \
F(DebugAsyncFunctionSuspended, 1, 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