Commit 04b9e7a1 authored by Simon Zünd's avatar Simon Zünd Committed by V8 LUCI CQ

Call debug hook AsyncFunctionSuspended when debugger is active

This CL fixes a memory leak where we would not properly pop all
Promises from the Isolate-wide Promise stack. This can happen under
the following conditions:
  - `await`ing a Promise in an async function
  - Debugger is active
  - AsyncEventDelegate is not set.

In the case above, the promise of the surrounding async function is
pushed onto the global Promise stack, but not poped before the
await. This CL fixes that.

R=bmeurer@chromium.org

Fixed: chromium:1225905
Change-Id: If03f6bfda48b8cb14bc6a68815fd702632edc68d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3268464Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77790}
parent 7a63228d
......@@ -265,6 +265,7 @@ void AsyncFunctionBuiltinsAssembler::AsyncFunctionAwait(
Label after_debug_hook(this), call_debug_hook(this, Label::kDeferred);
GotoIf(HasAsyncEventDelegate(), &call_debug_hook);
GotoIf(IsDebugActive(), &call_debug_hook);
Goto(&after_debug_hook);
BIND(&after_debug_hook);
......
......@@ -259,7 +259,8 @@ class AsyncEventDelegate {
bool is_blackboxed) = 0;
};
void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);
V8_EXPORT_PRIVATE void SetAsyncEventDelegate(Isolate* isolate,
AsyncEventDelegate* delegate);
void ResetBlackboxedStateCache(Isolate* isolate,
v8::Local<debug::Script> script);
......
......@@ -5688,3 +5688,32 @@ TEST(TerminateOnResumeAtInterruptFromOtherThread) {
v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded();
}
namespace {
class NoopDelegate : public v8::debug::DebugDelegate {};
} // namespace
// Tests that the Isolate::Pop/Push leaves an empty stack for `await` when
// the Debugger is active but the AsyncEventDelegate is not set.
// Regression test for https://crbug.com/1225905
TEST(AwaitCleansUpGlobalPromiseStack) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
NoopDelegate delegate;
v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
v8::debug::SetAsyncEventDelegate(env->GetIsolate(), nullptr);
v8::Local<v8::String> source = v8_str(
"(async () => {\n"
" await Promise.resolve();\n"
"})();\n");
CompileRun(source);
CHECK_EQ(CcTest::i_isolate()->thread_local_top()->promise_on_stack_, nullptr);
v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded();
}
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