Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for "wasm-function" symbol maps #93

Merged
merged 1 commit into from
Jul 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {SortMethod, SortField, SortDirection} from './profile-table-view'
import {triangle} from './utils'
import {Color} from './color'
import {RowAtlas} from './row-atlas'
import {importAsmJsSymbolMap} from './asm-js'
import {importEmscriptenSymbolMap} from './emscripten'
import {SandwichView} from './sandwich-view'
import {saveToFile} from './file-format'

Expand Down Expand Up @@ -384,9 +384,9 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
// a symbol map. If that's the case, we want to parse it, and apply the symbol
// mapping to the already loaded profile. This can be use to take an opaque
// profile and make it readable.
const map = importAsmJsSymbolMap(reader.result)
const map = importEmscriptenSymbolMap(reader.result)
if (map) {
console.log('Importing as asm.js symbol map')
console.log('Importing as emscripten symbol map')
let profile = this.state.profile
profile.remapNames(name => map.get(name) || name)
return profile
Expand Down
26 changes: 0 additions & 26 deletions asm-js.ts

This file was deleted.

33 changes: 23 additions & 10 deletions asm-js.test.ts → emscripten.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {importAsmJsSymbolMap} from './asm-js'
import {importEmscriptenSymbolMap} from './emscripten'

test('importAsmJSSymbolMap', () => {
test('importEmscriptenSymbolMap', () => {
// Valid symbol map
expect(
importAsmJsSymbolMap(
importEmscriptenSymbolMap(
[
/* prettier: ignore */
'a:A',
Expand All @@ -15,7 +15,7 @@ test('importAsmJSSymbolMap', () => {

// Valid symbol map with trailing newline
expect(
importAsmJsSymbolMap(
importEmscriptenSymbolMap(
[
/* prettier: ignore */
'a:A',
Expand All @@ -27,14 +27,27 @@ test('importAsmJSSymbolMap', () => {
).toEqual(new Map([['a', 'A'], ['b', 'B'], ['c', 'C']]))

// Valid symbol map with non-alpha characters

expect(importAsmJsSymbolMap('u6:__ZN8tinyxml210XMLCommentD0Ev\n')).toEqual(
expect(importEmscriptenSymbolMap('u6:__ZN8tinyxml210XMLCommentD0Ev\n')).toEqual(
new Map([['u6', '__ZN8tinyxml210XMLCommentD0Ev']]),
)

// WebAssembly symbol map
expect(
importEmscriptenSymbolMap(
[
/* prettier: ignore */
'0:A',
'1:B',
'2:C',
].join('\n'),
),
).toEqual(
new Map([['wasm-function[0]', 'A'], ['wasm-function[1]', 'B'], ['wasm-function[2]', 'C']]),
)

// Invalid symbol map
expect(
importAsmJsSymbolMap(
importEmscriptenSymbolMap(
[
/* prettier: ignore */
'a:A',
Expand All @@ -47,7 +60,7 @@ test('importAsmJSSymbolMap', () => {

// Collapsed stack format should not be imported as an asm.js symbol map
expect(
importAsmJsSymbolMap(
importEmscriptenSymbolMap(
[
/* prettier: ignore */
'a;b 1',
Expand All @@ -58,6 +71,6 @@ test('importAsmJSSymbolMap', () => {
).toEqual(null)

// Unrelated files
expect(importAsmJsSymbolMap('')).toEqual(null)
expect(importAsmJsSymbolMap('\n')).toEqual(null)
expect(importEmscriptenSymbolMap('')).toEqual(null)
expect(importEmscriptenSymbolMap('\n')).toEqual(null)
})
39 changes: 39 additions & 0 deletions emscripten.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
type EmscriptenSymbolMap = Map<string, string>

// This imports symbol maps generated by emscripten using the "--emit-symbol-map" flag.
// It allows you to visualize a profile captured in a release build as long as you also
// have the associated symbol map. To do this, first drop the profile into speedscope
// and then drop the symbol map. After the second drop, the symbols will be remapped to
// their original names.
export function importEmscriptenSymbolMap(contents: string): EmscriptenSymbolMap | null {
const lines = contents.split('\n')
if (!lines.length) return null

// Remove a trailing blank line if there is one
if (lines[lines.length - 1] === '') lines.pop()
if (!lines.length) return null

const map: EmscriptenSymbolMap = new Map()
const intRegex = /^(\d+):([\$\w]+)$/
const idRegex = /^([\$\w]+):([\$\w]+)$/

for (const line of lines) {
// Match lines like "103:__ZN8tinyxml210XMLCommentD0Ev"
const intMatch = intRegex.exec(line)
if (intMatch) {
map.set(`wasm-function[${intMatch[1]}]`, intMatch[2])
continue
}

// Match lines like "u6:__ZN8tinyxml210XMLCommentD0Ev"
const idMatch = idRegex.exec(line)
if (idMatch) {
map.set(idMatch[1], idMatch[2])
continue
}

return null
}

return map
}