When collecting stacks for the profiler, include line + column information for JIT frames
Categories
(Core :: JavaScript Engine, enhancement, P3)
Tracking
()
People
(Reporter: mstange, Assigned: canova)
References
(Blocks 1 open bug)
Details
Attachments
(14 files, 1 obsolete file)
|
59 bytes,
text/x-review-board-request
|
Details | |
|
59 bytes,
text/x-review-board-request
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
| Comment hidden (mozreview-request) |
| Comment hidden (mozreview-request) |
Updated•7 years ago
|
Updated•7 years ago
|
| Reporter | ||
Updated•5 years ago
|
Comment 3•5 years ago
|
||
One of the problem I see is that we are doing code relocation with LICM, or share pieces of code with GVN, but we should have a non-precise form of this information at least stored in snapshots.
| Reporter | ||
Comment 4•4 years ago
|
||
The Firefox profiler is now adding a built-in source view, and will display this type of information for C++ code. It would be great to have the same information for JavaScript code.
Comment 5•4 years ago
|
||
Thanks Markus for the link with C++ / Rust examples, these are awesome!
One thing I noticed with the crashing patch, is that the RootedScript is assumed to be non-null. While this might be frequently the case this is not guaranteed, for multiple reasons:
- We have trampoline functions, which are C++/JIT calls wrapper to convert from the system ABI to an ABI which makes things easy for the GC.
- We have shared Inline Caches, which might not be associated with a script.
- We have WebAssembly, which does not use JSScript.
I think the JS team can find someone to help design a proper API which can be used by the Gecko Profiler.
I will raise this topic in our next SpiderMonkey meeting.
| Reporter | ||
Comment 6•4 years ago
|
||
Thanks, Nicolas!
Comment 7•4 years ago
|
||
The lasted patches bit-rot since the last time. However, I have a few comments to revive the current set of patches.
The current patches are adding ProfiledFrameHandle::lookupScriptAndPc, or renaming an existing function to this new name. Since the function got removed,as some clean-up went by. This is not a big deal, the js::jit::JitcodeGlobalEntry still has the information provided by js::jit::JitcodeGlobalEntry::callStackAtAddr. The second patch adds a way to query the ProfiledFrameHandle using lookupScriptAndPc, but this is no longer an option, as the function got removed.
One thing to note is how the ProfiledFrameEntry aJITFrame flows into StreamJITFrame. StreamJITFrame is called by JSONForJITFrame and JitFrameInfo::AddInfoForRange, which iterates over the ProfiledFrameEntry. As a result of iterating over the ProfiledFrameRange returned by JS::GetProfiledFrames.
The remarkable point, is that JS::GetProfiledFrames calls the other overload of js::jit::JitcodeGlobalEntry::callStackAtAddr.
callStackAtAddr has 2 definitions:
- A first definition with an out-param to return the
BytecodeLocationVector, which is what we are interested in to get the line information. - A second definition with an out-param to return the names of the functions, which is what
JS::GetProfiledFramesreturns.
To rebase the patches, a simple fix might be to change the ProfiledFrameRange to hold a BytecodeLocationVector, as well as adding a BytecodeLocation field to the ProfiledFrameEntry.
Then we should be able to query the line number in StreamJITFrame using the aJITFrame argument.
This does not tell us whether the same crash will occur or not, but this should reduce the risk as we will no longer be doing an extra lookup.
Later on, we might want to merge both callStackAtAddr with 2 out-param.
Comment 8•4 years ago
|
||
One thing to note, is that the BytecodeLocation carry some information which might be useful for JS Engine developers, which is the opcode which is executed. While most of these would be calls, it might be interesting to distinguish the opcode in the profiler.
| Reporter | ||
Comment 9•4 years ago
|
||
This all sounds great!
Comment 10•4 years ago
|
||
This patch changes the function callStackAtAddr to output both the Bytecode
location as well as the associated Script pointer. Unfortunately, we cannot use
the BytecodeLocation abstraction as it is link to too many other parts of the
JavaScript engine that we prefer not to expose.
With this modification, we are now able to annotate JIT frame within the
profiler, with line number information. The line number information can later be
used by the profiler interface to display the associated code.
Comment 11•4 years ago
|
||
I had local failures locally which did not seem related to the profiler. Thus, I pushed the new patch to try.
There are failures which are suggesting a follow-up issue related to AddJitInfoForRange.
| Reporter | ||
Comment 12•3 years ago
|
||
What's the next step here? Pushing to try again and debugging the failures?
Comment 13•3 years ago
|
||
(In reply to Markus Stange [:mstange] from comment #12)
What's the next step here? Pushing to try again and debugging the failures?
Ideally someone from the profiler team should resume working on this feature, on top of the patch I rebased, fixing the issues which are remaining in the Profiler.
Updated•3 years ago
|
| Reporter | ||
Comment 14•6 months ago
|
||
Bug 1969435 removed the script pointer from the table entry, but I think we'll need it to map the pc to the right line.
| Reporter | ||
Comment 15•6 months ago
|
||
Nazim recently landed bug 1979114. If you go to about:profiling and enable the "JS Sources" feature, you can now have a working JS source view when you capture profiles in Firefox.
However, double-clicking a JS function often opens the source view at the wrong spot, and the per-line sample counts are incorrect, due to this bug. So now would be a great time to look into this bug again. Nazim has a patch which undoes some of bug 1969435 and which gives us some line information, but the information we get doesn't seem very accurate, so more investigation is needed.
| Assignee | ||
Comment 16•6 months ago
|
||
| Assignee | ||
Comment 17•5 months ago
|
||
This patch does a partial backout of https://phabricator.services.mozilla.com/D255393
because we removed the JSScript at first thinking that we don't need it
while we are profiling. But we need it to be able to get the line and
column information for JIT frames. See the following patch to see how we
use the JSScript inside callStackAtAddr.
It looks like there is another way to get this line/column information
which is using utilizing the data that we keep for PerfSpewer. But
unfortunately that doesn't work well for us for now because PerfSpewer
doesn't know about the inlined JIT frames. If we add this information to
PerfSpewer, then we can potentially revert this patch again. But I would
like to work on this iteratively, by having this information first, and
then improving it later.
Updated•5 months ago
|
| Assignee | ||
Comment 18•5 months ago
|
||
Previously we were keeping the fields of CallStackFrameInfo one by one
in the ProfiledFrameHandle. But since we added this struct now, we can
simply pass it and keep it around instead. This is going to be useful
when we add more values to this struct like the line and column number.
Updated•5 months ago
|
| Assignee | ||
Comment 19•5 months ago
|
||
In some cases, baseline frame line numbers were attributed to either
loop head or the function signature because the profiler had no valid
recorded return address once baseline jumped into IC/native stubs, so
JSJitProfilingFrameIterator fell back to an earlier point in the
JSScript while stackwalking.
Note that ion already avoids this by enabling
masm.enableProfilingInstrumentation() and wrapping every call with the
profiler RAII helper. This patch does the same for baseline:
- It turns on masm.enableProfilingInstrumentation() whenever we generate
baseline code while the Gecko profiler is enabled. - Introduces emitProfilerCallSiteInstrumentation() and calls it before
every baseline JS call opcode so each masm.call records its return
address. This is a bit different compared to ion (calls masm.callJit
which handles the profiler call site directly), because it wasn't as
straightforward as ion to convert masm.call calls into callJit. Also,
even though that method uses an RAII class, weirdly it doesn't
actually have anything in its destructor. That's why it's fine to use
it this way. - Exposes a MacroAssembler::instrumentProfilerCallSite() helper so we
can still instrument the profiler call site from baseline. - Switches baseline’s VM calls to callJit so they too update
lastProfilingCallSite.
With these changes, the sampler always lands on a real baseline return
address, the existing RetAddr table can map it back to the correct
pc/line, and profiler listings show the actual call site instead of the
top of the function.
I'm adding a test in the following patches as it requires some changes
in the shell.
| Assignee | ||
Comment 20•5 months ago
|
||
This patch adds line and column number information to the frames in the
return object of readGeckoProfilingStack JS shell function. It will be
needed in the next commit for writing a test for it.
| Assignee | ||
Comment 21•5 months ago
|
||
Now that we have fixed the profiler JIT line number attribution
properly, let's add a test to verify this.
This patch simulates the failure case that I was experiencing with the
baseline frames in one of my demo websites. The failure case had a
for-of loop and had a 3-4 calls inside of it that calls different DOM
APIs etc. The line numbers for all of these calls inside the for loop
were attributed to the for loop header itself, assuming because we had
profiler call sites emitted for iterator .next, but not for the others.
This test was failing before my commit that fixes the baseline profiler
call sites.
| Assignee | ||
Comment 22•5 months ago
|
||
It appears that we've removed the definitions of these methods and uses
of them, but not the declarations. This patch removes these too.
| Assignee | ||
Comment 23•5 months ago
|
||
This patch introduces IonScriptData, which holds both
ScriptSourceAndExtent and RefPtr<SharedImmutableScriptData>, and stores
it inside IonEntry. This is needed for later patches, where we will use
it to fetch line and column number information from Ion entries instead
of keeping a reference to JSScript.
Note that we don’t need a reference to SharedImmutableScriptData for
BaselineEntry, because we will be using PerfSpewer directly for those
entries. It’s not possible to use PerfSpewer for IonEntry yet, as it
does not support inline frames. Ideally, we should add inline frame
support and then remove the SharedImmutableScriptData RefPtr from this
entry in the future.
| Assignee | ||
Comment 24•5 months ago
|
||
This partially reverts commit b62582b (D226645) and removes some unused
parts of it with minor code changes.
This API will be used by the profiler in the later patches to fetch the
line and column numbers for the JIT frames.
Co-authored-by: Denis Palmeiro <dpalmeiro@mozilla.com>
| Assignee | ||
Comment 25•5 months ago
|
||
This reduces the memory usage of the PerfSpewer profiler source entries
and improves the binary search performance at the same time.
From my very scientific(?) testing, it reduces the memory usage of
the source entries by ~70%.
Updated•5 months ago
|
| Assignee | ||
Comment 26•4 months ago
|
||
I noticed that sometimes some jit-tests were failing in CI because we
weren't handling the OOM cases here. After these changes, jit-tests
pass as expected.
Comment 27•4 months ago
|
||
Comment 28•4 months ago
|
||
Comment 29•4 months ago
|
||
Backed out for causing leaks at js_pod_arena_malloc.
Backout link: https://hg.mozilla.org/integration/autoland/rev/4b2fd156db417b2726ccd2e8e313f82dc74f7a5b
Failure log: https://treeherder.mozilla.org/logviewer?job_id=543748812&repo=autoland&task=Qk2nwqXLRlG2d-Sv0_WScg.0&lineNumber=8940
| Assignee | ||
Comment 30•3 months ago
|
||
I got a memory leak on some profiler tests after I started to use
PerfSpewer inside the profiler codebase.
It appears that the PerfSpewer objects are mostly allocated using a Lifo
allocator, and their destructors don't run because of this. Using the
system allocator inside an object allocated with a lifo allocator was
essentially causing a memory leak for the objects that were created with
the system allocator because their memory needs to be handled
explicitly by freeing them.
Instead of system allocator, this patch uses LifoAlloc for all the
allocated objects that are inside PerfSpewer.
Updated•3 months ago
|
Comment 31•3 months ago
|
||
Comment 32•3 months ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/261db6e0a49b
https://hg.mozilla.org/mozilla-central/rev/dc2fe4b5559b
https://hg.mozilla.org/mozilla-central/rev/16a7d61f77fc
https://hg.mozilla.org/mozilla-central/rev/35d56c4a23aa
https://hg.mozilla.org/mozilla-central/rev/6662163e154a
https://hg.mozilla.org/mozilla-central/rev/f801c0f9aad7
https://hg.mozilla.org/mozilla-central/rev/7331db6f0682
https://hg.mozilla.org/mozilla-central/rev/093475c22347
https://hg.mozilla.org/mozilla-central/rev/8db3637cf8c9
https://hg.mozilla.org/mozilla-central/rev/011e66d46bfd
https://hg.mozilla.org/mozilla-central/rev/c879ccfd1702
Comment 33•3 months ago
|
||
Comment 34•3 months ago
|
||
Backed out on request for causing https://bugzilla.mozilla.org/show_bug.cgi?id=2012244
https://hg.mozilla.org/integration/autoland/rev/292320f4a2f72a12ccc954e7e71fb7b88fc13686
| Assignee | ||
Updated•3 months ago
|
Comment 35•3 months ago
|
||
Comment 36•3 months ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/3f967d6e031c
https://hg.mozilla.org/mozilla-central/rev/04eb44addd8d
https://hg.mozilla.org/mozilla-central/rev/3756372b4877
https://hg.mozilla.org/mozilla-central/rev/7a5e006b184c
https://hg.mozilla.org/mozilla-central/rev/780d089dd9dc
https://hg.mozilla.org/mozilla-central/rev/75c72ea59c71
https://hg.mozilla.org/mozilla-central/rev/24027d1285d0
https://hg.mozilla.org/mozilla-central/rev/224a75d71e2a
https://hg.mozilla.org/mozilla-central/rev/87a65876bd9a
https://hg.mozilla.org/mozilla-central/rev/7a2d9442ccd0
https://hg.mozilla.org/mozilla-central/rev/fe715578792e
Updated•2 months ago
|
Updated•1 month ago
|
Description
•