Expose the recurring flag on the async stack tagging API

This CL exposes the `recurring` flag on the experimental async stack
tagging API which was implemeted in the following CL:
https://chromium-review.googlesource.com/c/v8/v8/+/3212506

It serves as a prototype to check if such an API is suitable for
improving stack traces for frameworks which split up tasks across
multiple frames, yielding back to the main thread when some time budget
is consumed.

The tests are implemented as Blink web tests in the following CL:
https://chromium-review.googlesource.com/c/chromium/src/+/3383386

Bug: chromium:332624
Change-Id: I3e8c5de723cb7c0413d03ca4292c22d6a6e565b0
Signed-off-by: Victor Porof <victorporof@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3380495
Reviewed-by: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78647}
This commit is contained in:
Victor Porof 2022-01-17 09:42:07 +00:00 committed by V8 LUCI CQ
parent 55be041933
commit 5f3ff431ec
2 changed files with 33 additions and 16 deletions

View File

@ -513,7 +513,11 @@ v8::Maybe<int64_t> V8Console::ValidateAndGetTaskId(
void V8Console::scheduleAsyncTask( void V8Console::scheduleAsyncTask(
const v8::FunctionCallbackInfo<v8::Value>& info) { const v8::FunctionCallbackInfo<v8::Value>& info) {
if (info.Length() != 1) { if (info.Length() != 1 && info.Length() != 2) {
info.GetIsolate()->ThrowError("Unexpected arguments");
return;
}
if (info.Length() == 2 && !info[1]->IsBoolean()) {
info.GetIsolate()->ThrowError("Unexpected arguments"); info.GetIsolate()->ThrowError("Unexpected arguments");
return; return;
} }
@ -521,6 +525,8 @@ void V8Console::scheduleAsyncTask(
v8::debug::ConsoleCallArguments args(info); v8::debug::ConsoleCallArguments args(info);
ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector); ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
String16 argName = helper.firstArgToString(String16()); String16 argName = helper.firstArgToString(String16());
bool recurring =
info.Length() == 2 ? info[1].As<v8::Boolean>()->Value() : false;
int64_t id = m_taskIdCounter++; int64_t id = m_taskIdCounter++;
auto it = m_asyncTaskIds.find(id); auto it = m_asyncTaskIds.find(id);
@ -529,11 +535,13 @@ void V8Console::scheduleAsyncTask(
return; return;
} }
int* taskPtr = new int(); AsyncTaskInfo taskInfo;
m_asyncTaskIds.emplace(id, taskPtr); taskInfo.ptr = new int();
taskInfo.recurring = recurring;
m_asyncTaskIds.emplace(id, taskInfo);
StringView taskName = StringView(argName.characters16(), argName.length()); StringView taskName = StringView(argName.characters16(), argName.length());
m_inspector->asyncTaskScheduled(taskName, taskPtr, false); m_inspector->asyncTaskScheduled(taskName, taskInfo.ptr, recurring);
info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), id)); info.GetReturnValue().Set(v8::Number::New(info.GetIsolate(), id));
} }
@ -544,8 +552,8 @@ void V8Console::startAsyncTask(
if (maybeArgId.IsNothing()) return; if (maybeArgId.IsNothing()) return;
int64_t taskId = maybeArgId.FromJust(); int64_t taskId = maybeArgId.FromJust();
int* taskPtr = m_asyncTaskIds[taskId]; AsyncTaskInfo taskInfo = m_asyncTaskIds[taskId];
m_inspector->asyncTaskStarted(taskPtr); m_inspector->asyncTaskStarted(taskInfo.ptr);
} }
void V8Console::finishAsyncTask( void V8Console::finishAsyncTask(
@ -554,10 +562,14 @@ void V8Console::finishAsyncTask(
if (maybeArgId.IsNothing()) return; if (maybeArgId.IsNothing()) return;
int64_t taskId = maybeArgId.FromJust(); int64_t taskId = maybeArgId.FromJust();
int* taskPtr = m_asyncTaskIds[taskId]; AsyncTaskInfo taskInfo = m_asyncTaskIds[taskId];
m_inspector->asyncTaskFinished(taskPtr); m_inspector->asyncTaskFinished(taskInfo.ptr);
delete taskPtr; if (taskInfo.recurring) {
return;
}
delete taskInfo.ptr;
m_asyncTaskIds.erase(taskId); m_asyncTaskIds.erase(taskId);
} }
@ -567,10 +579,10 @@ void V8Console::cancelAsyncTask(
if (maybeArgId.IsNothing()) return; if (maybeArgId.IsNothing()) return;
int64_t taskId = maybeArgId.FromJust(); int64_t taskId = maybeArgId.FromJust();
int* taskPtr = m_asyncTaskIds[taskId]; AsyncTaskInfo taskInfo = m_asyncTaskIds[taskId];
m_inspector->asyncTaskCanceled(taskPtr); m_inspector->asyncTaskCanceled(taskInfo.ptr);
delete taskPtr; delete taskInfo.ptr;
m_asyncTaskIds.erase(taskId); m_asyncTaskIds.erase(taskId);
} }

View File

@ -56,6 +56,11 @@ class V8Console : public v8::debug::ConsoleDelegate {
v8::Local<v8::ArrayBuffer> m_thisReference; v8::Local<v8::ArrayBuffer> m_thisReference;
}; };
struct AsyncTaskInfo {
int* ptr;
bool recurring;
};
explicit V8Console(V8InspectorImpl* inspector); explicit V8Console(V8InspectorImpl* inspector);
private: private:
@ -185,11 +190,11 @@ class V8Console : public v8::debug::ConsoleDelegate {
// A map of unique pointers used for the scheduling and joining async stacks. // A map of unique pointers used for the scheduling and joining async stacks.
// The async stack traces instrumentation is exposed on the console object, // The async stack traces instrumentation is exposed on the console object,
// behind a --experimental-async-stack-tagging-api flag. For now, it serves as // behind a --experimental-async-stack-tagging-api flag. For now, it serves
// a prototype that aims to validate whether the debugging experience can be // as a prototype that aims to validate whether the debugging experience can
// improved for userland code that uses custom schedulers. // be improved for userland code that uses custom schedulers.
int64_t m_taskIdCounter = 0; int64_t m_taskIdCounter = 0;
std::map<int64_t, int*> m_asyncTaskIds; std::map<int64_t, AsyncTaskInfo> m_asyncTaskIds;
}; };
} // namespace v8_inspector } // namespace v8_inspector