Commit f60ccbf5 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Use profiler code-source-info in processor.mjs

Attach SourcePositionInfo objects to existing code entries if we find
code-source-info log entries. This improves fixes finding scripts for
anonymous functions.

Bug: v8:10644
Change-Id: I6fc1e029b17107cacce89dc74a67d4d448d9a979
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2562672
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71482}
parent 571e35e8
...@@ -31,19 +31,25 @@ import { ...@@ -31,19 +31,25 @@ import {
[288,{size:1, [288,{size:1,
name:'v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)', name:'v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)',
type:'CPP', type:'CPP',
nameUpdated_:false} nameUpdated_:false,
source: undefined,
}
]); ]);
assertEquals(staticEntries[1], assertEquals(staticEntries[1],
[272,{size:1, [272,{size:1,
name:'v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::internal::Object>, unsigned int)', name:'v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::internal::Object>, unsigned int)',
type:'CPP', type:'CPP',
nameUpdated_:false} nameUpdated_:false,
source: undefined,
}
]); ]);
assertEquals(staticEntries[2], assertEquals(staticEntries[2],
[256,{size:1, [256,{size:1,
name:'v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Arguments)', name:'v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Arguments)',
type:'CPP', type:'CPP',
nameUpdated_:false} nameUpdated_:false,
source: undefined,
}
]); ]);
UnixCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols; UnixCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols;
......
...@@ -266,6 +266,7 @@ export class CodeMap { ...@@ -266,6 +266,7 @@ export class CodeMap {
* @param {number} size Code entry size in bytes. * @param {number} size Code entry size in bytes.
* @param {string} opt_name Code entry name. * @param {string} opt_name Code entry name.
* @param {string} opt_type Code entry type, e.g. SHARED_LIB, CPP. * @param {string} opt_type Code entry type, e.g. SHARED_LIB, CPP.
* @param {object} source Optional source position information
* @constructor * @constructor
*/ */
export class CodeEntry { export class CodeEntry {
...@@ -274,6 +275,7 @@ export class CodeEntry { ...@@ -274,6 +275,7 @@ export class CodeEntry {
this.name = opt_name || ''; this.name = opt_name || '';
this.type = opt_type || ''; this.type = opt_type || '';
this.nameUpdated_ = false; this.nameUpdated_ = false;
this.source = undefined;
} }
getName() { getName() {
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
import { CodeMap, CodeEntry } from "./codemap.mjs"; import { CodeMap, CodeEntry } from "./codemap.mjs";
import { ConsArray } from "./consarray.mjs"; import { ConsArray } from "./consarray.mjs";
// Used to associate log entries with source positions in scripts.
// TODO: move to separate modules // TODO: move to separate modules
export class SourcePosition { export class SourcePosition {
constructor(script, line, column) { constructor(script, line, column) {
...@@ -42,13 +43,19 @@ export class SourcePosition { ...@@ -42,13 +43,19 @@ export class SourcePosition {
} }
export class Script { export class Script {
constructor(id, name, source) { name;
source;
// Map<line, Map<column, SourcePosition>>
lineToColumn = new Map();
constructor(id) {
this.id = id; this.id = id;
this.sourcePositions = [];
}
update(name, source) {
this.name = name; this.name = name;
this.source = source; this.source = source;
this.sourcePositions = [];
// Map<line, Map<column, SourcePosition>>
this.lineToColumn = new Map();
} }
get length() { get length() {
...@@ -78,6 +85,18 @@ export class Script { ...@@ -78,6 +85,18 @@ export class Script {
} }
} }
class SourcePositionInfo{
constructor(script, startPos, endPos, sourcePositionTable, inliningPositions, inlinedFunctions) {
this.script = script;
this.start = startPos;
this.end = endPos;
this.positions = sourcePositionTable;
this.inlined = inliningPositions;
this.fns = inlinedFunctions;
}
}
/** /**
* Creates a profile object for processing profiling-related events * Creates a profile object for processing profiling-related events
* and calculating function execution times. * and calculating function execution times.
...@@ -252,23 +271,52 @@ export class Profile { ...@@ -252,23 +271,52 @@ export class Profile {
/** /**
* Adds source positions for given code. * Adds source positions for given code.
*/ */
addSourcePositions(start, script, startPos, endPos, sourcePositions, addSourcePositions(start, scriptId, startPos, endPos, sourcePositionTable,
inliningPositions, inlinedFunctions) { inliningPositions, inlinedFunctions) {
// CLI does not need source code => ignore. const script = this.getOrCreateScript(scriptId);
const entry = this.codeMap_.findDynamicEntryByStartAddress(start);
if (!entry) return;
const codeId = entry.codeId;
// Resolve the inlined functions list.
if (inlinedFunctions.length > 0) {
inlinedFunctions = inlinedFunctions.substring(1).split("S");
for (let i = 0; i < inlinedFunctions.length; i++) {
const funcAddr = parseInt(inlinedFunctions[i]);
const func = this.codeMap_.findDynamicEntryByStartAddress(funcAddr);
if (!func || func.funcId === undefined) {
// TODO: fix
console.warn(`Could not find function ${inlinedFunctions[i]}`);
inlinedFunctions[i] = null;
} else {
inlinedFunctions[i] = func.funcId;
}
}
} else {
inlinedFunctions = [];
}
entry.source =
new SourcePositionInfo(
script, startPos, endPos, sourcePositionTable, inliningPositions,
inlinedFunctions);
} }
/**
* Adds script source code.
*/
addScriptSource(id, url, source) { addScriptSource(id, url, source) {
const script = new Script(id, url, source); const script = this.getOrCreateScript(id);
this.scripts_[id] = script; script.update(url, source);
this.urlToScript_.set(url, script); this.urlToScript_.set(url, script);
} }
/** getOrCreateScript(id) {
* Adds script source code. let script = this.scripts_[id];
*/ if (!script) {
script = new Script(id);
this.scripts_[id] = script;
}
return script;
}
getScript(url) { getScript(url) {
return this.urlToScript_.get(url); return this.urlToScript_.get(url);
} }
......
...@@ -23,12 +23,19 @@ export class Processor extends LogReader { ...@@ -23,12 +23,19 @@ export class Processor extends LogReader {
MINOR_VERSION = 6; MINOR_VERSION = 6;
constructor(logString) { constructor(logString) {
super(); super();
this.propertyICParser = [ const propertyICParser = [
parseInt, parseInt, parseInt, parseInt, parseString, parseString, parseInt, parseInt, parseInt, parseInt, parseString, parseString,
parseString, parseString, parseString, parseString parseString, parseString, parseString, parseString
]; ];
this.dispatchTable_ = { this.dispatchTable_ = {
__proto__: null, __proto__: null,
'v8-version': {
parsers: [
parseInt,
parseInt,
],
processor: this.processV8Version
},
'code-creation': { 'code-creation': {
parsers: [ parsers: [
parseString, parseInt, parseInt, parseInt, parseInt, parseString, parseString, parseInt, parseInt, parseInt, parseInt, parseString,
...@@ -43,20 +50,20 @@ export class Processor extends LogReader { ...@@ -43,20 +50,20 @@ export class Processor extends LogReader {
], ],
processor: this.processCodeDeopt processor: this.processCodeDeopt
}, },
'v8-version': { 'code-move':
{parsers: [parseInt, parseInt], processor: this.processCodeMove},
'code-delete': {parsers: [parseInt], processor: this.processCodeDelete},
'code-source-info': {
parsers: [ parsers: [
parseInt, parseInt, parseInt, parseInt, parseInt, parseString, parseString,
parseInt, parseString
], ],
processor: this.processV8Version processor: this.processCodeSourceInfo
}, },
'script-source': { 'script-source': {
parsers: [parseInt, parseString, parseString], parsers: [parseInt, parseString, parseString],
processor: this.processScriptSource processor: this.processScriptSource
}, },
'code-move':
{parsers: [parseInt, parseInt], processor: this.processCodeMove},
'code-delete': {parsers: [parseInt], processor: this.processCodeDelete},
'sfi-move': 'sfi-move':
{parsers: [parseInt, parseInt], processor: this.processFunctionMove}, {parsers: [parseInt, parseInt], processor: this.processFunctionMove},
'map-create': 'map-create':
...@@ -73,31 +80,31 @@ export class Processor extends LogReader { ...@@ -73,31 +80,31 @@ export class Processor extends LogReader {
processor: this.processMapDetails processor: this.processMapDetails
}, },
'LoadGlobalIC': { 'LoadGlobalIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'LoadGlobalIC') processor: this.processPropertyIC.bind(this, 'LoadGlobalIC')
}, },
'StoreGlobalIC': { 'StoreGlobalIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'StoreGlobalIC') processor: this.processPropertyIC.bind(this, 'StoreGlobalIC')
}, },
'LoadIC': { 'LoadIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'LoadIC') processor: this.processPropertyIC.bind(this, 'LoadIC')
}, },
'StoreIC': { 'StoreIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'StoreIC') processor: this.processPropertyIC.bind(this, 'StoreIC')
}, },
'KeyedLoadIC': { 'KeyedLoadIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'KeyedLoadIC') processor: this.processPropertyIC.bind(this, 'KeyedLoadIC')
}, },
'KeyedStoreIC': { 'KeyedStoreIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'KeyedStoreIC') processor: this.processPropertyIC.bind(this, 'KeyedStoreIC')
}, },
'StoreInArrayLiteralIC': { 'StoreInArrayLiteralIC': {
parsers: this.propertyICParser, parsers: propertyICParser,
processor: this.processPropertyIC.bind(this, 'StoreInArrayLiteralIC') processor: this.processPropertyIC.bind(this, 'StoreInArrayLiteralIC')
}, },
}; };
...@@ -229,22 +236,20 @@ export class Processor extends LogReader { ...@@ -229,22 +236,20 @@ export class Processor extends LogReader {
this._profile.moveFunc(from, to); this._profile.moveFunc(from, to);
} }
formatName(entry) { processCodeSourceInfo(
if (!entry) return '<unknown>'; start, script, startPos, endPos, sourcePositions, inliningPositions,
let name = entry.func.getName(); inlinedFunctions) {
let re = /(.*):[0-9]+:[0-9]+$/; this._profile.addSourcePositions(
let array = re.exec(name); start, script, startPos, endPos, sourcePositions, inliningPositions,
if (!array) return name; inlinedFunctions);
return entry.getState() + array[1];
} }
processPropertyIC( processPropertyIC(
type, pc, time, line, column, old_state, new_state, map, key, modifier, type, pc, time, line, column, old_state, new_state, map, key, modifier,
slow_reason) { slow_reason) {
let fnName = this.functionName(pc); let profileEntry = this._profile.findEntry(pc);
let parts = fnName.split(' '); let fnName = this.formatProfileEntry(profileEntry);
let fileName = parts[parts.length - 1]; let script = this.getProfileEntryScript(profileEntry);
let script = this.getScript(fileName);
// TODO: Use SourcePosition here directly // TODO: Use SourcePosition here directly
let entry = new IcLogEntry( let entry = new IcLogEntry(
type, fnName, time, line, column, key, old_state, new_state, map, type, fnName, time, line, column, key, old_state, new_state, map,
...@@ -255,33 +260,27 @@ export class Processor extends LogReader { ...@@ -255,33 +260,27 @@ export class Processor extends LogReader {
this._icTimeline.push(entry); this._icTimeline.push(entry);
} }
functionName(pc) { formatProfileEntry(profileEntry, line, column) {
let entry = this._profile.findEntry(pc); if (!profileEntry) return '<unknown>';
return this.formatName(entry); if (profileEntry.type === 'Builtin') return profileEntry.name;
} const name = profileEntry.func.getName();
formatPC(pc, line, column) { const array = this._formatPCRegexp.exec(name);
let entry = this._profile.findEntry(pc); const formatted =
if (!entry) return '<unknown>' (array === null) ? name : profileEntry.getState() + array[1];
if (entry.type === 'Builtin') { if (line === undefined || column === undefined) return formatted;
return entry.name; return `${formatted}:${line}:${column}`;
}
let name = entry.func.getName();
let array = this._formatPCRegexp.exec(name);
if (array === null) {
entry = name;
} else {
entry = entry.getState() + array[1];
}
return entry + ':' + line + ':' + column;
} }
processFileName(filePositionLine) { getProfileEntryScript(profileEntry) {
if (!filePositionLine.includes(' ')) return; if (!profileEntry) return undefined;
// Try to handle urls with file positions: https://foo.bar.com/:17:330" if (profileEntry.type === 'Builtin') return undefined;
filePositionLine = filePositionLine.split(' '); const script = profileEntry.source?.script;
let parts = filePositionLine[1].split(':'); if (script !== undefined) return script;
if (parts[0].length <= 5) return parts[0] + ':' + parts[1]; // Slow path, try to get the script from the url:
return parts[1]; const fnName = this.formatProfileEntry(profileEntry);
let parts = fnName.split(' ');
let fileName = parts[parts.length - 1];
return this.getScript(fileName);
} }
processMap(type, time, from, to, pc, line, column, reason, name) { processMap(type, time, from, to, pc, line, column, reason, name) {
...@@ -291,13 +290,11 @@ export class Processor extends LogReader { ...@@ -291,13 +290,11 @@ export class Processor extends LogReader {
let to_ = this.getExistingMapEntry(to, time_); let to_ = this.getExistingMapEntry(to, time_);
// TODO: use SourcePosition directly. // TODO: use SourcePosition directly.
let edge = new Edge(type, name, reason, time, from_, to_); let edge = new Edge(type, name, reason, time, from_, to_);
to_.filePosition = this.formatPC(pc, line, column); const profileEntry = this._profile.findEntry(pc)
let fileName = this.processFileName(to_.filePosition); to_.filePosition = this.formatProfileEntry(profileEntry, line, column);
// TODO: avoid undefined source positions. let script = this.getProfileEntryScript(profileEntry);
if (fileName !== undefined) { if (script) {
to_.script = this.getScript(fileName); to_.script = script;
}
if (to_.script) {
to_.sourcePosition = to_.script.addSourcePosition(line, column, to_) to_.sourcePosition = to_.script.addSourcePosition(line, column, to_)
} }
edge.finishSetup(); edge.finishSetup();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment