[tools] Support bigint addresses in the tickprocessor
- Rename useBigInt to useBigIntAddresses - Propagate useBigIntAddresses to more profile helpers - Add more tests with useBigIntAddresses - Add new --use-bigint-addresses flag for the tickprocesser Bug: v8:13440 Change-Id: If51c3d0e8c6ff8cd1aed0bd4dd857386caa835f0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4965425 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#90592}
This commit is contained in:
1 parent
fd0fbe29b3
commit
c75efb8fba
8 files changed
+199
-92
No files matched your search
@@ -34,8 +34,8 @@ const result = doWork();
|
||||
|
||||
const logString = d8.log.getAndStop();
|
||||
assertTrue(logString.length > 0);
|
||||
const useBigInts = true;
|
||||
const processor = new Processor(useBigInts);
|
||||
const useBigIntAddresses = true;
|
||||
const processor = new Processor(useBigIntAddresses);
|
||||
await processor.processChunk(logString);
|
||||
await processor.finalize();
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ await (async function testUnixCppEntriesProvider() {
|
||||
'081f08a0 00000004 B stdout\n'
|
||||
].join('\n'), ''];
|
||||
};
|
||||
|
||||
var shell_prov = new LinuxCppEntriesProvider();
|
||||
var shell_syms = [];
|
||||
await shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, 0,
|
||||
@@ -111,6 +112,21 @@ await (async function testUnixCppEntriesProvider() {
|
||||
['v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)', 0x0813a0b0, 0x0813a0b0 + 0x855],
|
||||
['v8::internal::RegExpMacroAssembler::CheckPosition(int, v8::internal::Label*)', 0x0818b220, 0x0818b220 + 0x36]],
|
||||
shell_syms);
|
||||
// With BigInts
|
||||
const useBigIntsArgs = [undefined, undefined, undefined, undefined, true]
|
||||
var shell_prov = new LinuxCppEntriesProvider(...useBigIntsArgs);
|
||||
var shell_syms = [];
|
||||
await shell_prov.parseVmSymbols('shell', 0x08048000n, 0x081ee000n, 0n,
|
||||
(...params) => shell_syms.push(params));
|
||||
assertEquals(
|
||||
[['_init', 0x08049790n, 0x08049f50n],
|
||||
['_start', 0x08049f50n, 0x08139150n],
|
||||
['v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Arguments)', 0x08139150n, 0x08139150n + 0xb4bn],
|
||||
['v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::internal::Object>, unsigned int)', 0x08139ca0n, 0x08139ca0n + 0x3f1n],
|
||||
['v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)', 0x0813a0b0n, 0x0813a0b0n + 0x855n],
|
||||
['v8::internal::RegExpMacroAssembler::CheckPosition(int, v8::internal::Label*)', 0x0818b220n, 0x0818b220n + 0x36n]],
|
||||
shell_syms);
|
||||
|
||||
|
||||
// libc library
|
||||
LinuxCppEntriesProvider.prototype.loadSymbols = function(libName) {
|
||||
@@ -175,6 +191,15 @@ await (async function testUnixCppEntriesProvider() {
|
||||
android_ref_syms[i][2] += 0xf7c5c000;
|
||||
}
|
||||
assertEquals(android_ref_syms, android_syms);
|
||||
// With BigInts
|
||||
var android_prov = new LinuxCppEntriesProvider(...useBigIntsArgs);
|
||||
var android_syms = [];
|
||||
await android_prov.parseVmSymbols('libmonochrome', 0xf7c5c000n, 0xf9c5c000n, 0n,
|
||||
(...params) => android_syms.push(params));
|
||||
var android_ref_syms_bigints = android_ref_syms.map(entry => [
|
||||
entry[0], BigInt(entry[1]), BigInt(entry[2])
|
||||
])
|
||||
assertEquals(android_ref_syms_bigints, android_syms);
|
||||
|
||||
LinuxCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols;
|
||||
})();
|
||||
@@ -230,6 +255,16 @@ await (async function testMacOSCppEntriesProvider() {
|
||||
stdc_ref_syms[i][2] += 0x95728fb4;
|
||||
}
|
||||
assertEquals(stdc_ref_syms, stdc_syms);
|
||||
// With BigInts
|
||||
const useBigIntsArgs = [undefined, undefined, undefined, undefined, true];
|
||||
var stdc_prov = new MacOSCppEntriesProvider(...useBigIntsArgs);
|
||||
var stdc_syms = [];
|
||||
await stdc_prov.parseVmSymbols('stdc++', 0x95728fb4n, 0x95770005n, 0n,
|
||||
(...params) => stdc_syms.push(params));
|
||||
var stdc_ref_syms_bigints = stdc_ref_syms.map(entry => [
|
||||
entry[0], BigInt(entry[1]), BigInt(entry[2])
|
||||
])
|
||||
assertEquals(stdc_ref_syms_bigints, stdc_syms);
|
||||
|
||||
MacOSCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols;
|
||||
})();
|
||||
@@ -269,6 +304,19 @@ await (async function testWindowsCppEntriesProvider() {
|
||||
['v8::DefaultFatalErrorHandler', 0x00401b70, 0x004020b0],
|
||||
['v8::EnsureInitialized', 0x004020b0, 0x0057c000]],
|
||||
shell_syms);
|
||||
// With BigInts
|
||||
const useBigIntsArgs = [undefined, undefined, undefined, undefined, true];
|
||||
var shell_prov = new WindowsCppEntriesProvider(...useBigIntsArgs);
|
||||
var shell_syms = [];
|
||||
await shell_prov.parseVmSymbols('shell.exe', 0x00400000n, 0x0057c000n, 0n,
|
||||
(...params) => shell_syms.push(params));
|
||||
assertEquals(
|
||||
[['ReadFile', 0x00401000n, 0x004010a0n],
|
||||
['Print', 0x004010a0n, 0x00402230n],
|
||||
['v8::String::?1Utf8Value', 0x00402230n, 0x004964ban],
|
||||
['v8::DefaultFatalErrorHandler', 0x00401b70n, 0x004020b0n],
|
||||
['v8::EnsureInitialized', 0x004020b0n, 0x0057c000n]],
|
||||
shell_syms);
|
||||
|
||||
WindowsCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols;
|
||||
})();
|
||||
@@ -305,6 +353,17 @@ await (async function testWindowsProcessExeAndDllMapFile() {
|
||||
[['RunMain', 0x00401780, 0x00401ac0],
|
||||
['_main', 0x00401ac0, 0x00472000]],
|
||||
exe_exe_syms, '.exe with .exe symbols');
|
||||
// With BigInts
|
||||
read = exeSymbols;
|
||||
const useBigIntsArgs = [undefined, undefined, undefined, undefined, true];
|
||||
var exe_exe_syms = [];
|
||||
await (new WindowsCppEntriesProvider(...useBigIntsArgs)).parseVmSymbols(
|
||||
'chrome.exe', 0x00400000n, 0x00472000n, 0n,
|
||||
(...params) => exe_exe_syms.push(params));
|
||||
assertEquals(
|
||||
[['RunMain', 0x00401780n, 0x00401ac0n],
|
||||
['_main', 0x00401ac0n, 0x00472000n]],
|
||||
exe_exe_syms, '.exe with .exe symbols');
|
||||
|
||||
read = dllSymbols;
|
||||
var exe_dll_syms = [];
|
||||
@@ -324,6 +383,16 @@ await (async function testWindowsProcessExeAndDllMapFile() {
|
||||
[['_DllMain@12', 0x01c31780, 0x01c31ac0],
|
||||
['___DllMainCRTStartup', 0x01c31ac0, 0x02b80000]],
|
||||
dll_dll_syms, '.dll with .dll symbols');
|
||||
// With BigInts
|
||||
read = dllSymbols;
|
||||
var dll_dll_syms = [];
|
||||
await (new WindowsCppEntriesProvider(...useBigIntsArgs)).parseVmSymbols(
|
||||
'chrome.dll', 0x01c30000n, 0x02b80000n, 0n,
|
||||
(...params) => dll_dll_syms.push(params));
|
||||
assertEquals(
|
||||
[['_DllMain@12', 0x01c31780n, 0x01c31ac0n],
|
||||
['___DllMainCRTStartup', 0x01c31ac0n, 0x02b80000n]],
|
||||
dll_dll_syms, '.dll with .dll symbols');
|
||||
|
||||
read = exeSymbols;
|
||||
var dll_exe_syms = [];
|
||||
@@ -339,15 +408,17 @@ await (async function testWindowsProcessExeAndDllMapFile() {
|
||||
|
||||
|
||||
class CppEntriesProviderMock {
|
||||
constructor(filename) {
|
||||
constructor(filename, useBigIntAddresses=false) {
|
||||
this.isLoaded = false;
|
||||
this.symbols = JSON.parse(d8.file.read(filename));
|
||||
this.parseAddr = useBigIntAddresses ? BigInt : parseInt;
|
||||
}
|
||||
parseVmSymbols(name, startAddr, endAddr, slideAddr, symbolAdder) {
|
||||
if (this.isLoaded) return;
|
||||
this.isLoaded = true;
|
||||
for (let symbol of this.symbols) {
|
||||
symbolAdder.apply(null, symbol);
|
||||
for (let symbolInfo of this.symbols) {
|
||||
const [name, start, end] = symbolInfo;
|
||||
symbolAdder.call(null, name, this.parseAddr(start), this.parseAddr(end))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,13 +510,22 @@ await (async function testProcessing() {
|
||||
'tickprocessor-test-large.log', 'tickprocessor-test-large.default'],
|
||||
};
|
||||
for (var testName in testData) {
|
||||
console.log('=== testProcessing-' + testName + ' ===');
|
||||
await testTickProcessor(...testData[testName]);
|
||||
await testTickProcessor(testName, ...testData[testName]);
|
||||
}
|
||||
})();
|
||||
|
||||
async function testTickProcessor(logInput, refOutput, args=[]) {
|
||||
// /foo/bar/tickprocesser.mjs => /foo/bar/
|
||||
async function testTickProcessor(testName, logInput, refOutput, args=[]) {
|
||||
console.log('=== testProcessing-' + testName + ' ===');
|
||||
await testTickProcessorBasic(logInput, refOutput, args);
|
||||
// Using BigInt address should not affect the output.
|
||||
console.log('=== testProcessing-' + testName + '-bigint-addresses ===');
|
||||
await testTickProcessorBasic(
|
||||
logInput, refOutput, [...args, '--use-bigint-addresses']);
|
||||
}
|
||||
|
||||
async function testTickProcessorBasic(
|
||||
logInput, refOutput, args=[]) {
|
||||
// /foo/bar/tickprocessor.mjs => /foo/bar/
|
||||
const dir = import.meta.url.split("/").slice(0, -1).join('/') + '/';
|
||||
const params = ArgumentsProcessor.process(args);
|
||||
await testExpectations(dir, logInput, refOutput, params);
|
||||
@@ -455,7 +535,8 @@ async function testTickProcessor(logInput, refOutput, args=[]) {
|
||||
|
||||
async function testExpectations(dir, logInput, refOutput, params) {
|
||||
const symbolsFile = dir + logInput + '.symbols.json';
|
||||
const cppEntries = new CppEntriesProviderMock(symbolsFile);
|
||||
const cppEntries = new CppEntriesProviderMock(
|
||||
symbolsFile, params.useBigIntAddresses);
|
||||
const tickProcessor = TickProcessor.fromParams(params, cppEntries);
|
||||
const printMonitor = new PrintMonitor(dir + refOutput);
|
||||
await tickProcessor.processLogFileInTest(dir + logInput);
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
export class BaseArgumentsProcessor {
|
||||
constructor(args) {
|
||||
this.args_ = args;
|
||||
this.args_ = args.slice();
|
||||
this.result_ = this.getDefaultResults();
|
||||
console.assert(this.result_ !== undefined)
|
||||
console.assert(this.result_.logFileName !== undefined);
|
||||
|
||||
+5
-5
@@ -65,11 +65,11 @@ export class CodeMap {
|
||||
*/
|
||||
pages_ = new Set();
|
||||
|
||||
constructor(useBigInt=false) {
|
||||
this.useBigInt = useBigInt;
|
||||
this.kPageSize = useBigInt ? BigInt(kPageSize) : kPageSize;
|
||||
this.kOne = useBigInt ? 1n : 1;
|
||||
this.kZero = useBigInt ? 0n : 0;
|
||||
constructor(useBigIntAddresses=false) {
|
||||
this.useBigIntAddresses = useBigIntAddresses;
|
||||
this.kPageSize = useBigIntAddresses ? BigInt(kPageSize) : kPageSize;
|
||||
this.kOne = useBigIntAddresses ? 1n : 1;
|
||||
this.kZero = useBigIntAddresses ? 0n : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-5
@@ -54,7 +54,8 @@ function containsUnsafeInts(fields) {
|
||||
* @constructor
|
||||
*/
|
||||
export class LogReader {
|
||||
constructor(timedRange=false, pairwiseTimedRange=false, useBigInt=false) {
|
||||
constructor(
|
||||
timedRange=false, pairwiseTimedRange=false, useBigIntAddresses=false) {
|
||||
this.dispatchTable_ = new Map();
|
||||
this.timedRange_ = timedRange;
|
||||
this.pairwiseTimedRange_ = pairwiseTimedRange;
|
||||
@@ -66,8 +67,8 @@ export class LogReader {
|
||||
this.logLinesSinceLastTimerMarker_ = [];
|
||||
// Flag to parse all numeric fields as BigInt to avoid arithmetic errors
|
||||
// caused by memory addresses being greater than MAX_SAFE_INTEGER
|
||||
this.useBigInt = useBigInt;
|
||||
this.parseFrame = useBigInt ? BigInt : parseInt;
|
||||
this.useBigIntAddresses = useBigIntAddresses;
|
||||
this.parseFrame = useBigIntAddresses ? BigInt : parseInt;
|
||||
this.hasSeenUnsafeIntegers = false;
|
||||
}
|
||||
|
||||
@@ -231,9 +232,9 @@ export class LogReader {
|
||||
parsedFields[i] = parser(fields[1 + i]);
|
||||
}
|
||||
}
|
||||
if (!this.useBigInt) {
|
||||
if (!this.useBigIntAddresses) {
|
||||
if (!this.hasSeenUnsafeIntegers && containsUnsafeInts(parsedFields)) {
|
||||
console.warn(`Log line containts unsafe integers: ${fields}`);
|
||||
console.warn(`Log line contains unsafe integers: ${fields}`);
|
||||
this.hasSeenUnsafeIntegers = true;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -316,9 +316,9 @@ export class Profile {
|
||||
urlToScript_ = new Map();
|
||||
warnings = new Set();
|
||||
|
||||
constructor(useBigInt=false) {
|
||||
this.useBigInt = useBigInt;
|
||||
this.codeMap_ = new CodeMap(useBigInt);
|
||||
constructor(useBigIntAddresses=false) {
|
||||
this.useBigIntAddresses = useBigIntAddresses;
|
||||
this.codeMap_ = new CodeMap(useBigIntAddresses);
|
||||
}
|
||||
|
||||
serializeVMSymbols() {
|
||||
@@ -523,7 +523,7 @@ export class Profile {
|
||||
// Overwrite any old (unused) code objects that overlap with the new SFI.
|
||||
const new_sfi_old_code = !(sfi instanceof SharedFunctionInfoEntry)
|
||||
if (sfi === null || new_sfi_old_code) {
|
||||
sfi = new SharedFunctionInfoEntry(name, this.useBigInt);
|
||||
sfi = new SharedFunctionInfoEntry(name, this.useBigIntAddresses);
|
||||
this.codeMap_.addCode(sfiAddr, sfi);
|
||||
} else if (sfi.name !== name) {
|
||||
// SFI object has been overwritten with a new one.
|
||||
@@ -971,8 +971,8 @@ class SharedFunctionInfoEntry extends CodeEntry {
|
||||
/** @type {Set<DynamicCodeEntry>} */
|
||||
_codeEntries = new Set();
|
||||
|
||||
constructor(name, useBigInt=false) {
|
||||
super(useBigInt ? 0n : 0, name);
|
||||
constructor(name, useBigIntAddresses=false) {
|
||||
super(useBigIntAddresses ? 0n : 0, name);
|
||||
const index = name.lastIndexOf(' ');
|
||||
this.functionName = 1 <= index ? name.substring(0, index) : '<anonymous>';
|
||||
}
|
||||
@@ -1256,8 +1256,8 @@ class CallTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
export function JsonProfile() {
|
||||
this.codeMap_ = new CodeMap();
|
||||
export function JsonProfile(useBigIntAddresses=false) {
|
||||
this.codeMap_ = new CodeMap(useBigIntAddresses);
|
||||
this.codeEntries_ = [];
|
||||
this.functionEntries_ = [];
|
||||
this.ticks_ = [];
|
||||
|
||||
@@ -69,14 +69,14 @@ export class Processor extends LogReader {
|
||||
|
||||
MAJOR_VERSION = 7;
|
||||
MINOR_VERSION = 6;
|
||||
constructor(useBigInt = false) {
|
||||
super(false, false, useBigInt);
|
||||
this.useBigInt = useBigInt;
|
||||
this.kZero = useBigInt ? 0n : 0;
|
||||
this.parseAddress = useBigInt ? BigInt : parseInt;
|
||||
constructor(useBigIntAddresses = false) {
|
||||
super(false, false, useBigIntAddresses);
|
||||
this.useBigIntAddresses = useBigIntAddresses;
|
||||
this.kZero = useBigIntAddresses ? 0n : 0;
|
||||
this.parseAddress = useBigIntAddresses ? BigInt : parseInt;
|
||||
this._chunkConsumer =
|
||||
new AsyncConsumer((chunk) => this._processChunk(chunk));
|
||||
this._profile = new Profile(useBigInt);
|
||||
this._profile = new Profile(useBigIntAddresses);
|
||||
const propertyICParser = [
|
||||
this.parseAddress, parseInt, parseInt, parseInt, parseString, parseString,
|
||||
parseString, parseString, parseString, parseString
|
||||
|
||||
+82
-57
@@ -41,8 +41,8 @@ class V8Profile extends Profile {
|
||||
static STUBS_RE = /^(Stub: )/;
|
||||
|
||||
constructor(separateIc, separateBytecodes, separateBuiltins, separateStubs,
|
||||
separateSparkplugHandlers) {
|
||||
super();
|
||||
separateSparkplugHandlers, useBigIntAddresses=false) {
|
||||
super(useBigIntAddresses);
|
||||
const regexps = [];
|
||||
if (!separateIc) regexps.push(V8Profile.IC_RE);
|
||||
if (!separateBytecodes) regexps.push(V8Profile.BYTECODES_RE);
|
||||
@@ -60,8 +60,13 @@ class V8Profile extends Profile {
|
||||
}
|
||||
|
||||
class CppEntriesProvider {
|
||||
constructor() {
|
||||
constructor(useBigIntAddresses=false) {
|
||||
this._isEnabled = true;
|
||||
this.parseAddr = useBigIntAddresses ? BigInt : parseInt;
|
||||
this.parseHexAddr = useBigIntAddresses ?
|
||||
(str) => BigInt(parseInt(str, 16)) :
|
||||
(str) => parseInt(str, 16);
|
||||
|
||||
}
|
||||
|
||||
inRange(funcInfo, start, end) {
|
||||
@@ -167,12 +172,14 @@ class CppEntriesProvider {
|
||||
}
|
||||
|
||||
export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
||||
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
||||
super();
|
||||
constructor(
|
||||
nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary,
|
||||
useBigIntAddresses=false) {
|
||||
super(useBigIntAddresses);
|
||||
this.symbols = [];
|
||||
// File offset of a symbol minus the virtual address of a symbol found in
|
||||
// the symbol table.
|
||||
this.fileOffsetMinusVma = 0;
|
||||
this.fileOffsetMinusVma = useBigIntAddresses ? 0n : 0;
|
||||
this.parsePos = 0;
|
||||
this.nmExec = nmExec;
|
||||
this.objdumpExec = objdumpExec;
|
||||
@@ -211,7 +218,8 @@ export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
||||
for (const line of objdumpOutput.split('\n')) {
|
||||
const [, sectionName, , vma, , fileOffset] = line.trim().split(/\s+/);
|
||||
if (sectionName === ".text") {
|
||||
this.fileOffsetMinusVma = parseInt(fileOffset, 16) - parseInt(vma, 16);
|
||||
this.fileOffsetMinusVma =
|
||||
this.parseHexAddr(fileOffset) - this.parseHexAddr(vma);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -232,12 +240,14 @@ export class LinuxCppEntriesProvider extends CppEntriesProvider {
|
||||
const line = this.symbols[0].substring(this.parsePos, lineEndPos);
|
||||
this.parsePos = lineEndPos + 1;
|
||||
const fields = line.match(this.FUNC_RE);
|
||||
let funcInfo = null;
|
||||
if (fields) {
|
||||
funcInfo = { name: fields[3], start: parseInt(fields[1], 16) + this.fileOffsetMinusVma };
|
||||
if (fields[2]) {
|
||||
funcInfo.size = parseInt(fields[2], 16);
|
||||
}
|
||||
if (fields === null) return null;
|
||||
|
||||
const funcInfo = {
|
||||
name: fields[3],
|
||||
start: this.parseHexAddr(fields[1]) + this.fileOffsetMinusVma
|
||||
};
|
||||
if (fields[2]) {
|
||||
funcInfo.size = this.parseHexAddr(fields[2]);
|
||||
}
|
||||
return funcInfo;
|
||||
}
|
||||
@@ -250,8 +260,12 @@ export class RemoteLinuxCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||
}
|
||||
|
||||
export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
|
||||
super(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary);
|
||||
constructor(
|
||||
nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary,
|
||||
useBigIntAddresses=false) {
|
||||
super(
|
||||
nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary,
|
||||
useBigIntAddresses);
|
||||
// Note an empty group. It is required, as LinuxCppEntriesProvider expects 3 groups.
|
||||
this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/;
|
||||
}
|
||||
@@ -264,8 +278,8 @@ export class MacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||
// "flat" display option flag.
|
||||
try {
|
||||
this.symbols = [
|
||||
os.system(this.nmExec, ['--demangle', '-n', libName], -1, -1),
|
||||
''];
|
||||
os.system(this.nmExec, ['--demangle', '-n', libName], -1, -1), ''
|
||||
];
|
||||
} catch (e) {
|
||||
// If the library cannot be found on this system let's not panic.
|
||||
this.symbols = '';
|
||||
@@ -281,26 +295,28 @@ export class RemoteMacOSCppEntriesProvider extends LinuxCppEntriesProvider {
|
||||
|
||||
|
||||
export class WindowsCppEntriesProvider extends CppEntriesProvider {
|
||||
constructor(_ignored_nmExec, _ignored_objdumpExec, targetRootFS,
|
||||
_ignored_apkEmbeddedLibrary) {
|
||||
super();
|
||||
this.targetRootFS = targetRootFS;
|
||||
this.symbols = '';
|
||||
this.parsePos = 0;
|
||||
}
|
||||
|
||||
static FILENAME_RE = /^(.*)\.([^.]+)$/;
|
||||
static FUNC_RE =
|
||||
/^\s+0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
|
||||
static IMAGE_BASE_RE =
|
||||
/^\s+0000:00000000\s+___ImageBase\s+([0-9a-fA-F]{8}).*$/;
|
||||
// This is almost a constant on Windows.
|
||||
static EXE_IMAGE_BASE = 0x00400000;
|
||||
|
||||
constructor(
|
||||
_ignored_nmExec, _ignored_objdumpExec, targetRootFS,
|
||||
_ignored_apkEmbeddedLibrary, useBigIntAddresses) {
|
||||
super(useBigIntAddresses);
|
||||
this.targetRootFS = targetRootFS;
|
||||
this.symbols = '';
|
||||
this.parsePos = 0;
|
||||
// This is almost a constant on Windows.
|
||||
this.EXE_IMAGE_BASE = this.parseAddr(0x00400000);
|
||||
}
|
||||
|
||||
loadSymbols(libName) {
|
||||
libName = this.targetRootFS + libName;
|
||||
const fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
|
||||
if (!fileNameFields) return;
|
||||
if (fileNameFields === null) return;
|
||||
const mapFileName = `${fileNameFields[1]}.map`;
|
||||
this.moduleType_ = fileNameFields[2].toLowerCase();
|
||||
try {
|
||||
@@ -313,7 +329,7 @@ export class WindowsCppEntriesProvider extends CppEntriesProvider {
|
||||
|
||||
parseNextLine() {
|
||||
const lineEndPos = this.symbols.indexOf('\r\n', this.parsePos);
|
||||
if (lineEndPos == -1) {
|
||||
if (lineEndPos === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -323,18 +339,20 @@ export class WindowsCppEntriesProvider extends CppEntriesProvider {
|
||||
// Image base entry is above all other symbols, so we can just
|
||||
// terminate parsing.
|
||||
const imageBaseFields = line.match(WindowsCppEntriesProvider.IMAGE_BASE_RE);
|
||||
if (imageBaseFields) {
|
||||
const imageBase = parseInt(imageBaseFields[1], 16);
|
||||
if ((this.moduleType_ == 'exe') !=
|
||||
(imageBase == WindowsCppEntriesProvider.EXE_IMAGE_BASE)) {
|
||||
if (imageBaseFields !== null) {
|
||||
const imageBase = this.parseHexAddr(imageBaseFields[1]);
|
||||
if ((this.moduleType_ === 'exe') !=
|
||||
(imageBase === this.EXE_IMAGE_BASE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const fields = line.match(WindowsCppEntriesProvider.FUNC_RE);
|
||||
return fields ?
|
||||
{ name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } :
|
||||
null;
|
||||
if (fields === null) return null
|
||||
return {
|
||||
name: this.unmangleName(fields[1]),
|
||||
start: this.parseHexAddr(fields[2])
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,7 +437,9 @@ export class ArgumentsProcessor extends BaseArgumentsProcessor {
|
||||
'--serialize-vm-symbols': ['serializeVMSymbols', true,
|
||||
'Print all C++ symbols and library addresses as JSON data'],
|
||||
'--preprocess': ['preprocessJson', true,
|
||||
'Preprocess for consumption with web interface']
|
||||
'Preprocess for consumption with web interface'],
|
||||
'--use-bigint-addresses': ['useBigIntAddresses', true,
|
||||
'Use slower BigInts to precisely handle large addresses.']
|
||||
};
|
||||
dispatch['--js'] = dispatch['-j'];
|
||||
dispatch['--gc'] = dispatch['-g'];
|
||||
@@ -427,6 +447,7 @@ export class ArgumentsProcessor extends BaseArgumentsProcessor {
|
||||
dispatch['--other'] = dispatch['-o'];
|
||||
dispatch['--external'] = dispatch['-e'];
|
||||
dispatch['--ptr'] = dispatch['--pairwise-timed-range'];
|
||||
dispatch['--bigint-addresses'] = dispatch['--use-bigint-addresses'];
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
@@ -454,6 +475,7 @@ export class ArgumentsProcessor extends BaseArgumentsProcessor {
|
||||
onlySummary: false,
|
||||
runtimeTimerFilter: null,
|
||||
serializeVMSymbols: false,
|
||||
useBigIntAddresses: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -489,7 +511,8 @@ export class TickProcessor extends LogReader {
|
||||
params.pairwiseTimedRange,
|
||||
params.onlySummary,
|
||||
params.runtimeTimerFilter,
|
||||
params.preprocessJson);
|
||||
params.preprocessJson,
|
||||
params.useBigIntAddresses);
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -509,30 +532,34 @@ export class TickProcessor extends LogReader {
|
||||
pairwiseTimedRange,
|
||||
onlySummary,
|
||||
runtimeTimerFilter,
|
||||
preprocessJson) {
|
||||
super(timedRange, pairwiseTimedRange);
|
||||
preprocessJson,
|
||||
useBigIntAddresses) {
|
||||
super(timedRange, pairwiseTimedRange, useBigIntAddresses);
|
||||
this.useBigIntAddresses = useBigIntAddresses;
|
||||
this.parseAddr = useBigIntAddresses ? BigInt : parseInt;
|
||||
this.parseSize = this.parseAddr;
|
||||
this.setDispatchTable({
|
||||
__proto__: null,
|
||||
'shared-library': {
|
||||
parsers: [parseString, parseInt, parseInt, parseInt],
|
||||
parsers: [parseString, this.parseAddr, this.parseAddr, parseInt],
|
||||
processor: this.processSharedLibrary
|
||||
},
|
||||
'code-creation': {
|
||||
parsers: [parseString, parseInt, parseInt, parseInt, parseInt,
|
||||
parseString, parseVarArgs],
|
||||
parsers: [parseString, parseInt, parseInt, this.parseAddr,
|
||||
this.parseSize, parseString, parseVarArgs],
|
||||
processor: this.processCodeCreation
|
||||
},
|
||||
'code-deopt': {
|
||||
parsers: [parseInt, parseInt, parseInt, parseInt, parseInt,
|
||||
parsers: [parseInt, this.parseSize, this.parseAddr, parseInt, parseInt,
|
||||
parseString, parseString, parseString],
|
||||
processor: this.processCodeDeopt
|
||||
},
|
||||
'code-move': {
|
||||
parsers: [parseInt, parseInt,],
|
||||
parsers: [this.parseAddr, this.parseAddr,],
|
||||
processor: this.processCodeMove
|
||||
},
|
||||
'code-source-info': {
|
||||
parsers: [parseInt, parseInt, parseInt, parseInt, parseString,
|
||||
parsers: [this.parseAddr, parseInt, parseInt, parseInt, parseString,
|
||||
parseString, parseString],
|
||||
processor: this.processCodeSourceInfo
|
||||
},
|
||||
@@ -541,7 +568,7 @@ export class TickProcessor extends LogReader {
|
||||
processor: this.processScriptSource
|
||||
},
|
||||
'sfi-move': {
|
||||
parsers: [parseInt, parseInt],
|
||||
parsers: [this.parseAddr, this.parseAddr],
|
||||
processor: this.processSFIMove
|
||||
},
|
||||
'active-runtime-timer': {
|
||||
@@ -549,8 +576,8 @@ export class TickProcessor extends LogReader {
|
||||
processor: this.processRuntimeTimerEvent
|
||||
},
|
||||
'tick': {
|
||||
parsers: [parseInt, parseInt, parseInt,
|
||||
parseInt, parseInt, parseVarArgs],
|
||||
parsers: [this.parseAddr, parseInt, parseInt,
|
||||
this.parseAddr, parseInt, parseVarArgs],
|
||||
processor: this.processTick
|
||||
},
|
||||
'heap-sample-begin': {
|
||||
@@ -625,10 +652,11 @@ export class TickProcessor extends LogReader {
|
||||
};
|
||||
|
||||
if (preprocessJson) {
|
||||
this.profile_ = new JsonProfile();
|
||||
this.profile_ = new JsonProfile(useBigIntAddresses);
|
||||
} else {
|
||||
this.profile_ = new V8Profile(separateIc, separateBytecodes,
|
||||
separateBuiltins, separateStubs, separateSparkplugHandlers);
|
||||
separateBuiltins, separateStubs, separateSparkplugHandlers,
|
||||
useBigIntAddresses);
|
||||
}
|
||||
this.codeTypes_ = {};
|
||||
// Count each tick as a time unit.
|
||||
@@ -723,7 +751,7 @@ export class TickProcessor extends LogReader {
|
||||
|
||||
processCodeCreation(type, kind, timestamp, start, size, name, maybe_func) {
|
||||
if (type != 'RegExp' && maybe_func.length) {
|
||||
const sfiAddr = parseInt(maybe_func[0]);
|
||||
const sfiAddr = this.parseAddr(maybe_func[0]);
|
||||
const state = Profile.parseState(maybe_func[1]);
|
||||
this.profile_.addFuncCode(type, name, timestamp, start, size, sfiAddr, state);
|
||||
} else {
|
||||
@@ -774,12 +802,9 @@ export class TickProcessor extends LogReader {
|
||||
this.currentRuntimeTimer = name;
|
||||
}
|
||||
|
||||
processTick(pc,
|
||||
ns_since_start,
|
||||
is_external_callback,
|
||||
tos_or_external_callback,
|
||||
vmState,
|
||||
stack) {
|
||||
processTick(
|
||||
pc, ns_since_start, is_external_callback, tos_or_external_callback,
|
||||
vmState, stack) {
|
||||
this.distortion += this.distortion_per_entry;
|
||||
ns_since_start -= this.distortion;
|
||||
if (ns_since_start < this.range_start || ns_since_start > this.range_end) {
|
||||
|
||||
Reference in new issue
Block a user