Skip to content

Commit c3726e1

Browse files
committed
Propagate isJS to inline frames during symbolication.
1 parent 04c2883 commit c3726e1

File tree

3 files changed

+86
-9
lines changed

3 files changed

+86
-9
lines changed

src/profile-logic/symbolication.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,8 +789,8 @@ function _partiallyApplySymbolicationStep(
789789
if (funcIndex === undefined) {
790790
// Need a new func.
791791
funcIndex = funcTable.length;
792-
funcTable.isJS[funcIndex] = false;
793-
funcTable.relevantForJS[funcIndex] = false;
792+
funcTable.isJS[funcIndex] = funcTable.isJS[oldFunc];
793+
funcTable.relevantForJS[funcIndex] = funcTable.relevantForJS[oldFunc];
794794
funcTable.resource[funcIndex] = resourceIndex;
795795
funcTable.source[funcIndex] = null;
796796
funcTable.lineNumber[funcIndex] = null;

src/test/fixtures/example-symbol-table.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,45 @@ export const partialSymbolTable: ExampleSymbolTable = {
280280

281281
export const completeSymbolTableAsTuple = completeSymbolTable.asTuple;
282282
export const partialSymbolTableAsTuple = partialSymbolTable.asTuple;
283+
284+
// A symbol table for a JIT dump file (e.g. jit-52344.dump), simulating JS
285+
// functions symbolicated from samply + jitdump. The outer function
286+
// "renderButton.js" has an inlined call to "useState.js" at address 0x000a.
287+
const jitDumpSyms = [
288+
{
289+
address: 0,
290+
name: 'renderButton.js',
291+
file: 'Button.tsx',
292+
lineRanges: [
293+
{
294+
startAddress: 0x0,
295+
line: 42,
296+
},
297+
{
298+
startAddress: 0x8,
299+
line: 45,
300+
inlinedCall: {
301+
name: 'useState.js',
302+
file: 'react.js',
303+
lineRanges: [
304+
{
305+
startAddress: 0x8,
306+
line: 100,
307+
},
308+
],
309+
},
310+
},
311+
],
312+
},
313+
{
314+
address: 0x2000,
315+
name: 'runJobs.js',
316+
file: 'scheduler.js',
317+
},
318+
];
319+
320+
export const jitDumpSymbolTable: ExampleSymbolTable = {
321+
symbols: jitDumpSyms,
322+
asTuple: _makeSymbolTableAsTuple(jitDumpSyms),
323+
getAddressResult: _makeGetAddressResultFunction(jitDumpSyms),
324+
};

src/test/store/symbolication.test.ts

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getProfileFromTextSamples } from '../fixtures/profiles/processed-profil
77
import {
88
completeSymbolTable,
99
partialSymbolTable,
10+
jitDumpSymbolTable,
1011
} from '../fixtures/example-symbol-table';
1112
import type { ExampleSymbolTable } from '../fixtures/example-symbol-table';
1213
import type { MarkerPayload } from 'firefox-profiler/types';
@@ -29,6 +30,7 @@ import { doSymbolicateProfile } from '../../actions/receive-profile';
2930
import {
3031
changeSelectedCallNode,
3132
changeExpandedCallNodes,
33+
changeImplementationFilter,
3234
} from '../../actions/profile-view';
3335
import { formatTree, formatStack } from '../fixtures/utils';
3436
import { assertSetContainsOnly } from '../fixtures/custom-assertions';
@@ -44,18 +46,17 @@ import { SymbolsNotFoundError } from '../../profile-logic/errors';
4446
*/
4547
describe('doSymbolicateProfile', function () {
4648
// Initialize a store, an unsymbolicated profile, and helper functions.
47-
function init() {
49+
function init(profile = _createUnsymbolicatedProfile()) {
4850
// The rejection in `requestSymbolsFromServer` outputs an error log, let's
4951
// silence it here. The fact that we call it is tested in
5052
// symbol-store.test.js.
5153
jest.spyOn(console, 'log').mockImplementation(() => {});
5254

53-
const profile = _createUnsymbolicatedProfile();
5455
const store = storeWithProfile(profile);
5556

56-
let symbolTable = completeSymbolTable;
57+
let firefoxSymbolTable = completeSymbolTable;
5758
function switchSymbolTable(otherSymbolTable: ExampleSymbolTable) {
58-
symbolTable = otherSymbolTable;
59+
firefoxSymbolTable = otherSymbolTable;
5960
}
6061
let symbolicationProviderMode: 'from-server' | 'from-browser' =
6162
'from-browser';
@@ -67,12 +68,19 @@ describe('doSymbolicateProfile', function () {
6768
requestSymbolsFromServer: async (requests: LibSymbolicationRequest[]) =>
6869
requests.map<LibSymbolicationResponse>((request) => {
6970
const { lib, addresses } = request;
70-
if (lib.debugName !== 'firefox.pdb') {
71+
72+
const symbolTables: Partial<Record<string, ExampleSymbolTable>> = {
73+
'firefox.pdb': firefoxSymbolTable,
74+
'jit-52344.dump': jitDumpSymbolTable,
75+
};
76+
77+
const symbolTable = symbolTables[lib.debugName];
78+
if (symbolTable === undefined) {
7179
return {
7280
type: 'ERROR' as const,
7381
request,
7482
error: new SymbolsNotFoundError(
75-
'Should only have lib called firefox.pdb',
83+
`Lib name ${lib.debugName} is not in the list of known names: ${Object.keys(symbolTables).join(', ')}`,
7684
lib
7785
),
7886
};
@@ -123,7 +131,7 @@ describe('doSymbolicateProfile', function () {
123131
}
124132
return readSymbolsFromSymbolTable(
125133
addresses,
126-
symbolTable.asTuple,
134+
firefoxSymbolTable.asTuple,
127135
(s: string) => s
128136
);
129137
},
@@ -478,6 +486,25 @@ describe('doSymbolicateProfile', function () {
478486
]);
479487
});
480488

489+
it('inline frames for JS functions appear in the JS-only call tree after symbolication', async () => {
490+
const {
491+
store: { dispatch, getState },
492+
profile,
493+
symbolStore,
494+
} = init(_createUnsymbolicatedJitProfile());
495+
496+
await doSymbolicateProfile(dispatch, profile, symbolStore);
497+
498+
// Check that the `useState.js` node shows up in the JS-only call tree.
499+
// This function is an inline frame from the jitdump symbol info.
500+
dispatch(changeImplementationFilter('js'));
501+
expect(formatTree(getCallTree(getState()))).toEqual([
502+
'- renderButton.js (total: 1, self: —)',
503+
' - useState.js (total: 1, self: 1)',
504+
'- runJobs.js (total: 1, self: 1)',
505+
]);
506+
});
507+
481508
it('can re-symbolicate a partially-symbolicated profile even if it needs to add funcs to the funcTable', async () => {
482509
const {
483510
store: { dispatch, getState },
@@ -623,3 +650,11 @@ function _createUnsymbolicatedProfile() {
623650

624651
return profile;
625652
}
653+
654+
function _createUnsymbolicatedJitProfile() {
655+
// See jitDumpSyms (in example-symbol-table.ts) for the corresponding symbols.
656+
const { profile } = getProfileFromTextSamples(`
657+
renderButton.js[lib:jit-52344.dump][address:a] runJobs.js[lib:jit-52344.dump][address:2000]
658+
`);
659+
return profile;
660+
}

0 commit comments

Comments
 (0)