Bug 1925972 - Add innerWindowIDs to the frames of JS Execution Tracer backend r=dthayer,profiler-reviewers,arai,aabh

Differential Revision: https://phabricator.services.mozilla.com/D226300
This commit is contained in:
Nazım Can Altınova 2024-10-29 14:52:11 +00:00
parent 369c797ff7
commit c909f87013
5 changed files with 32 additions and 3 deletions

View File

@ -117,6 +117,10 @@ struct ExecutionTrace {
// and/or scripts)
uint32_t scriptId;
// ID to the realm that the frame was in. It's used for finding which
// frame comes from which window/page.
uint64_t realmID;
// Keys into the thread's atoms HashMap. This key can be missing from
// the HashMap as well (see comment above scriptId)
uint32_t functionNameId;

View File

@ -151,6 +151,8 @@ bool ExecutionTracer::writeFunctionFrame(JSContext* cx,
inlineData_.write(fn->baseScript()->lineno());
inlineData_.write(fn->baseScript()->column().oneOriginValue());
inlineData_.write(scriptSourceId);
inlineData_.write(
fn->baseScript()->realm()->creationOptions().profilerRealmID());
} else {
// In the case of no baseScript, we just fill it out with 0s. 0 is an
// invalid script source ID, so it is distinguishable from a real one
@ -256,6 +258,7 @@ bool ExecutionTracer::readFunctionFrame(
inlineData_.read(&event.functionEvent.lineNumber);
inlineData_.read(&event.functionEvent.column);
inlineData_.read(&event.functionEvent.scriptId);
inlineData_.read(&event.functionEvent.realmID);
inlineData_.read(&event.functionEvent.functionNameId);
inlineData_.read(&implementation);
inlineData_.read(&event.time);

View File

@ -51,6 +51,7 @@ assertEq(events[0].lineNumber, 1);
assertEq(events[0].columnNumber, 20);
assertEq(events[0].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[0].script.endsWith(" > eval"), true);
assertEq(typeof events[0].realmID, "number");
assertEq(events[0].name, "f1");
assertEq(events[1].kind, "FunctionLeave");
@ -58,6 +59,7 @@ assertEq(events[1].lineNumber, 1);
assertEq(events[1].columnNumber, 20);
assertEq(events[1].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[1].script.endsWith(" > eval"), true);
assertEq(typeof events[1].realmID, "number");
assertEq(events[1].name, "f1");
assertEq(events[2].kind, "FunctionEnter");
@ -65,6 +67,7 @@ assertEq(events[2].lineNumber, 1);
assertEq(events[2].columnNumber, 21);
assertEq(events[2].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[2].script.endsWith(" > eval"), true);
assertEq(typeof events[2].realmID, "number");
assertEq(events[2].name, "f2");
assertEq(events[3].kind, "FunctionLeave");
@ -72,6 +75,7 @@ assertEq(events[3].lineNumber, 1);
assertEq(events[3].columnNumber, 21);
assertEq(events[3].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[3].script.endsWith(" > eval"), true);
assertEq(typeof events[3].realmID, "number");
assertEq(events[3].name, "f2");
assertEq(events[4].kind, "FunctionEnter");
@ -79,6 +83,7 @@ assertEq(events[4].lineNumber, 1);
assertEq(events[4].columnNumber, 22);
assertEq(events[4].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[4].script.endsWith(" > eval"), true);
assertEq(typeof events[4].realmID, "number");
assertEq(events[4].name, "f3");
assertEq(events[5].kind, "FunctionLeave");
@ -86,6 +91,7 @@ assertEq(events[5].lineNumber, 1);
assertEq(events[5].columnNumber, 22);
assertEq(events[5].script.includes("ExecutionTracer-coverage-exclusive.js"), true);
assertEq(events[5].script.endsWith(" > eval"), true);
assertEq(typeof events[5].realmID, "number");
assertEq(events[5].name, "f3");
// Enabling/disabling the execution trace should fail while the code coverage

View File

@ -9532,6 +9532,12 @@ static bool GetExecutionTrace(JSContext* cx, unsigned argc, JS::Value* vp) {
JS::Rooted<JS::PropertyKey> scriptId(cx, NameToId(cx->names().script));
JS::Rooted<JS::PropertyKey> nameId(cx, NameToId(cx->names().name));
JS::Rooted<JS::PropertyKey> labelId(cx, NameToId(cx->names().label));
JS::Rooted<JSString*> realmIDStr(cx, JS_AtomizeString(cx, "realmID"));
if (!realmIDStr) {
return false;
}
JS::Rooted<JS::PropertyKey> realmIDId(
cx, JS::PropertyKey::NonIntAtom(realmIDStr));
JS::Rooted<JSObject*> contextObj(cx);
JS::Rooted<ArrayObject*> eventsArray(cx);
@ -9639,6 +9645,16 @@ static bool GetExecutionTrace(JSContext* cx, unsigned argc, JS::Value* vp) {
}
}
if (!JS_DefinePropertyById(
cx, eventObj, realmIDId,
// We are converting a uint64_t into double which is lossy. But
// this is okay because Firefox makes sure to only use 53 bits
// so it can be converted to and from a JS value without loss of
// precision. Additionally we don't set the realmID in JS shell.
double(event.functionEvent.realmID), JSPROP_ENUMERATE)) {
return false;
}
if (auto p = context.atoms.lookup(event.functionEvent.functionNameId)) {
str = JS_NewStringCopyUTF8Z(
cx, JS::ConstUTF8CharsZ(trace.stringBuffer.begin() + p->value()));

View File

@ -1121,9 +1121,9 @@ void ProfileBuffer::MaybeStreamExecutionTraceToJSON(
break;
}
UniqueStacks::FrameKey newFrame(nsCString(name.get()), true, false, 0,
Nothing{}, Nothing{},
Some(categoryPair));
UniqueStacks::FrameKey newFrame(nsCString(name.get()), true, false,
event.functionEvent.realmID, Nothing{},
Nothing{}, Some(categoryPair));
maybeStack = uniqueStacks.AppendFrame(stack, newFrame);
if (!maybeStack) {
writer.SetFailure("AppendFrame failure");