Give the frameTable a lib column - #6258
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6258 +/- ##
==========================================
+ Coverage 83.73% 83.79% +0.05%
==========================================
Files 350 350
Lines 37523 37583 +60
Branches 10543 10459 -84
==========================================
+ Hits 31420 31492 +72
+ Misses 5676 5664 -12
Partials 427 427 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
a2d6fdc to
ea3fdb5
Compare
canova
left a comment
There was a problem hiding this comment.
Thanks, looks pretty good to me. I added some comments, it looks like the Int32Array conversion doesn't happen properly, r+ with them fixed.
| // The library is stored per frame rather than being reached via the frame's | ||
| // resource (frame -> func -> resource -> lib) so that resources and libraries | ||
| // can vary independently. Multiple libraries can share one resource: a | ||
| // comparison profile of two libxul.so builds has one resource named | ||
| // "libxul.so" but a separate lib for each build, and a profile which combines | ||
| // several Firefox runs has one webhost resource per origin but a separate | ||
| // jitdump lib per run. Keeping them separate also leaves room for resources | ||
| // that describe something other than a library, such as a Rust crate, without | ||
| // breaking the frame-to-library association. |
There was a problem hiding this comment.
Hmm, is it useful to give the historical context here? I think we can trim it down a bit.
There was a problem hiding this comment.
Oh dear. Trimmed down.
| // The library of this function, if any. | ||
| // Note that, these days, funcs can be associated with multiple | ||
| // libraries, so this isn't the best representation anymore. In those | ||
| // cases this will be set to one of them, but it's arbitrary which one. |
There was a problem hiding this comment.
Could you file an issue for this?
| @@ -4466,12 +4467,8 @@ export function findAddressProofForFile( | |||
| if (address === null) { | |||
There was a problem hiding this comment.
Oh noticed while looking at this function, but I think we missed this check while changing address. I think this check should be if (address === -1) too now. But it's unrelated to this PR.
There was a problem hiding this comment.
Good catch, fixed in a separate commit.
| // comparison profile). Use the library of the first frame that has one. | ||
| let libIndex: IndexIntoLibs | null = null; | ||
| for (const frameIndex of callNodeFramePerStack.values()) { | ||
| const frameLib = frameTable.lib[frameIndex]; |
There was a problem hiding this comment.
frameIndex can be -1 for the stacks outside the call node's subtree. We should check that too otherwise frameLib will be undefined for those
There was a problem hiding this comment.
I realized that this libIndex was completely unused. I added a commit to remove it.
|
|
||
| This decouples resources from libraries. | ||
|
|
||
| The `lib` column can optionally be stored as an `Int32Array`, for profiles loaded from [JsonSlabs](https://github.com/mstange/json-slabs/) files (.jslb, .jslb.gz). Regular JS / JSON arrays are still accepted - but note that `-1` (not `null`) must be used regardless of format. |
There was a problem hiding this comment.
I was checking where we do this lib array to Int32Array conversion and couldn't find it. I think this needs to happen in finishRawFrameTableBuilder and convertSharedTablesEligibleColumns.
In the past, the way to get the library for a frame would be to go frame -> func -> resource -> lib. For native frames, the resource is of type Library and points at the lib. This had the following implications: - Native frames cannot ever have a resource of a non-Library type. - If two native frames want to share a func, they must also share the same library - otherwise they'll be in a different resource, and different resource means different func. This makes it hard to represent a few cases: - JS JIT frames with assembly. To have assembly, we must have a native library, but we also want JIT frames to have a JS file as their resource, and we want JITted frames for a JS function to share the func with non-JITted frames (interpreter frames) of the same JS function. - Comparison profiles / the "diff" thread for different builds, with assembly code. For example if you have two Firefox builds, one with and one without a patch, they'll have different libxul.so libraries, but you still want to combine C++ functions of the same name in the diffed tree. - Resources for Rust crates (not implemented here): We might want to assign different Rust frames from the same native binary to different resources, with one resource per Rust crate. This commit makes it so that frames now point at their library directly, and removes the lib column from the resourceTable. A resource of type Library only carries the library's name; several libs can share one. mergeLibs used to key on name + debugName, which collapsed two builds of the same library into one lib (and one resource). Now it keeps the libs separate but still collapses the resources by name. For func-only contexts there is no longer a func -> lib edge. formatFunctionNameWithLibrary and the new getLibNameForFunc read the name off the func's resource, which is all they ever needed. profile-query's functionInfo, which wants the full Lib record, scans the frame table once per query.
frameTable.address uses -1 rather than null for "no address", so the existing null check was always useless.
ea3fdb5 to
9203f11
Compare
Main | Deploy preview
In the past, the way to get the library for a frame would be to go frame -> func -> resource -> lib. For native frames, the resource is of type Library and points at the lib.
This had the following implications:
This makes it hard to represent a few cases:
This commit makes it so that frames now point at their library directly, and removes the lib column from the resourceTable. A resource of type Library only carries the library's name; several libs can share one.
mergeLibs used to key on name + debugName, which collapsed two builds of the same library into one lib (and one resource). Now it keeps the libs separate but still collapses the resources by name.
For func-only contexts there is no longer a func -> lib edge. formatFunctionNameWithLibrary and the new getLibNameForFunc read the name off the func's resource, which is all they ever needed. profile-query's functionInfo, which wants the full Lib record, scans the frame table once per query.