Commit 43a5f208 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Fix system-analyzer deopt position

Associate DeoptLogEntry with both, the function's source position and
the deopt location's source position.

Also fixes the list-panel click handler to support all clickable entry
types.

Bug: v8:10644, v8:10754
Change-Id: If10272a926d5dad10b29322e237610900715b9dd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2584955
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71732}
parent c2e10ac6
......@@ -219,6 +219,7 @@ class App {
await this._startupPromise;
try {
const processor = new Processor(e.detail);
this._state.profile = processor.profile;
const mapTimeline = processor.mapTimeline;
const icTimeline = processor.icTimeline;
const deoptTimeline = processor.deoptTimeline;
......
......@@ -5,15 +5,17 @@ import {LogEntry} from './log.mjs';
export class DeoptLogEntry extends LogEntry {
constructor(
type, time, deoptReason, deoptLocation, scriptOffset, instructionStart,
codeSize, inliningId) {
type, time, entry, deoptReason, deoptLocation, scriptOffset,
instructionStart, codeSize, inliningId) {
super(type, time);
this._entry = entry;
this._reason = deoptReason;
this._location = deoptLocation;
this._scriptOffset = scriptOffset;
this._instructionStart = instructionStart;
this._codeSize = codeSize;
this._inliningId = inliningId;
this.fileSourcePosition = undefined;
}
get reason() {
......@@ -24,6 +26,14 @@ export class DeoptLogEntry extends LogEntry {
return this._location;
}
get entry() {
return this._entry;
}
get functionName() {
return this._entry.functionName;
}
toString() {
return `Deopt(${this.type})`;
}
......@@ -33,7 +43,10 @@ export class DeoptLogEntry extends LogEntry {
}
static get propertyNames() {
return ['type', 'reason', 'sourcePosition', 'script'];
return [
'type', 'reason', 'functionName', 'sourcePosition',
'functionSourcePosition', 'script'
];
}
}
......@@ -60,10 +73,6 @@ export class CodeLogEntry extends LogEntry {
return this._entry.size;
}
get script() {
return this.sourcePosition?.script;
}
get source() {
return this._entry?.getSourceCode() ?? '';
}
......
......@@ -225,11 +225,25 @@ export class Processor extends LogReader {
timestamp, codeSize, instructionStart, inliningId, scriptOffset,
deoptKind, deoptLocation, deoptReason) {
this._lastTimestamp = timestamp;
const codeEntry = this._profile.findEntry(instructionStart);
const logEntry = new DeoptLogEntry(
deoptKind, timestamp, deoptReason, deoptLocation, scriptOffset,
instructionStart, codeSize, inliningId);
deoptKind, timestamp, codeEntry, deoptReason, deoptLocation,
scriptOffset, instructionStart, codeSize, inliningId);
this._deoptTimeline.push(logEntry);
this.addSourcePosition(this._profile.findEntry(instructionStart), logEntry);
this.addSourcePosition(codeEntry, logEntry);
logEntry.functionSourcePosition = logEntry.sourcePosition;
// custom parse deopt location
if (deoptLocation !== '<unknown>') {
const colSeparator = deoptLocation.lastIndexOf(':');
const rowSeparator = deoptLocation.lastIndexOf(':', colSeparator - 1);
const script = this.getScript(deoptLocation.substring(1, rowSeparator));
const line =
parseInt(deoptLocation.substring(rowSeparator + 1, colSeparator));
const column = parseInt(
deoptLocation.substring(colSeparator + 1, deoptLocation.length - 1));
logEntry.sourcePosition =
script.addSourcePosition(line, column, logEntry);
}
}
processScriptSource(scriptId, url, source) {
......@@ -430,4 +444,8 @@ export class Processor extends LogReader {
get scripts() {
return this._profile.scripts_.filter(script => script !== undefined);
}
get profile() {
return this._profile;
}
}
......@@ -6,6 +6,9 @@ found in the LICENSE file. -->
<link href="./index.css" rel="stylesheet">
</head>
<style>
#sourceCode {
white-space: pre-line;
}
</style>
<div class="panel">
<h2>Code Panel</h2>
......
......@@ -3,8 +3,7 @@
// found in the LICENSE file.
import {SourcePosition} from '../../profile.mjs';
import {IcLogEntry} from '../log/ic.mjs';
import {MapLogEntry} from '../log/map.mjs';
import {LogEntry} from '../log/log.mjs';
import {FocusEvent, SelectionEvent, SelectTimeEvent} from './events.mjs';
import {groupBy, LazyTable} from './helper.mjs';
......@@ -18,8 +17,7 @@ DOM.defineCustomElement('view/list-panel',
_timeline;
_detailsClickHandler = this._handleDetailsClick.bind(this);
_mapClickHandler = this._handleMapClick.bind(this);
_fileClickHandler = this._handleFilePositionClick.bind(this);
_logEntryClickHandler = this._handleLogEntryClick.bind(this);
constructor() {
super(templateText);
......@@ -118,15 +116,9 @@ DOM.defineCustomElement('view/list-panel',
return map;
}
_handleMapClick(e) {
_handleLogEntryClick(e) {
const group = e.currentTarget.group;
this.dispatchEvent(new FocusEvent(group.entries[0].map));
}
_handleFilePositionClick(e) {
const group = e.currentTarget.group;
const sourcePosition = group.entries[0].sourcePosition;
this.dispatchEvent(new FocusEvent(sourcePosition));
this.dispatchEvent(new FocusEvent(group.key));
}
_handleDetailsClick(event) {
......@@ -186,14 +178,17 @@ DOM.defineCustomElement('view/list-panel',
tr.appendChild(DOM.td(`${group.percent.toFixed(2)}%`, 'percentage'));
tr.appendChild(DOM.td(group.count, 'count'));
const valueTd = tr.appendChild(DOM.td(`${group.key}`, 'key'));
if (group.key instanceof MapLogEntry) {
tr.onclick = this._mapClickHandler;
if (this._isClickable(group.key)) {
tr.onclick = this._logEntryClickHandler;
valueTd.classList.add('clickable');
} else if (group.key instanceof SourcePosition) {
valueTd.classList.add('clickable');
tr.onclick = this._fileClickHandler;
}
return tr;
}, 10);
}
_isClickable(object) {
if (typeof object !== 'object') return false;
if (object instanceof LogEntry) return true;
return object instanceof SourcePosition;
}
});
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