Commit 79896eeb authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Add code-creation timeline track to system-analyzer

Drive-by-fix:
- better handle tooltip text

Bug: v8:10644
Change-Id: Ibe20a1e0a0ebd298855afcbdc6f28e6fa4d1e64e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2563660
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71479}
parent f5950e25
......@@ -26,7 +26,7 @@ group("v8_mjsunit") {
"../../tools/profile_view.mjs",
"../../tools/splaytree.mjs",
"../../tools/system-analyzer/helper.mjs",
"../../tools/system-analyzer/log/deopt.mjs",
"../../tools/system-analyzer/log/code.mjs",
"../../tools/system-analyzer/log/ic.mjs",
"../../tools/system-analyzer/log/log.mjs",
"../../tools/system-analyzer/log/map.mjs",
......
......@@ -232,7 +232,7 @@ export class Profile {
}
}
deoptCode( timestamp, code, inliningId, scriptOffset, bailoutType,
deoptCode(timestamp, code, inliningId, scriptOffset, bailoutType,
sourcePositionText, deoptReasonText) {
}
......
......@@ -9,17 +9,21 @@ class State {
_selectedMapLogEntries;
_selectedIcLogEntries;
_selectedDeoptLogEntries;
_selecteCodeLogEntries;
_selectedSourcePositions;
_nofChunks;
_chunks;
_icTimeline;
_mapTimeline;
_deoptTimeline;
_codeTimeline;
_minStartTime = Number.POSITIVE_INFINITY;
_maxEndTime = Number.NEGATIVE_INFINITY;
get minStartTime() {
return this._minStartTime;
}
get maxEndTime() {
return this._maxEndTime;
}
......@@ -30,15 +34,20 @@ class State {
this._icTimeline.selectTimeRange(start, end);
this._mapTimeline.selectTimeRange(start, end);
this._deoptTimeline.selectTimeRange(start, end);
this._codeTimeline.selectTimeRange(start, end);
}
_updateTimeRange() {
for (let timeline of this.timelines) {
setTimelines(mapTimeline, icTimeline, deoptTimeline, codeTimeline) {
this._mapTimeline = mapTimeline;
this._icTimeline = icTimeline;
this._deoptTimeline = deoptTimeline;
this._codeTimeline = codeTimeline;
for (let timeline of arguments) {
if (timeline === undefined) return;
this._minStartTime = Math.min(this._minStartTime, timeline.startTime);
this._maxEndTime = Math.max(this._maxEndTime, timeline.endTime);
}
for (let timeline of this.timelines) {
for (let timeline of arguments) {
timeline.startTime = this._minStartTime;
timeline.endTime = this._maxEndTime;
}
......@@ -47,37 +56,35 @@ class State {
get mapTimeline() {
return this._mapTimeline;
}
set mapTimeline(timeline) {
this._mapTimeline = timeline;
this._updateTimeRange();
}
get icTimeline() {
return this._icTimeline;
}
set icTimeline(timeline) {
this._icTimeline = timeline;
this._updateTimeRange();
}
get deoptTimeline() {
return this._deoptTimeline;
}
set deoptTimeline(timeline) {
this._deoptTimeline = timeline;
this._updateTimeRange();
get codeTimeline() {
return this._codeTimeline;
}
get timelines() {
return [this.mapTimeline, this.icTimeline, this.deoptTimeline];
return [
this.mapTimeline, this.icTimeline, this.deoptTimeline, this.codeTimeline
];
}
set chunks(value) {
// TODO(zcankara) split up between maps and ics, and every timeline track
this._chunks = value;
}
get chunks() {
// TODO(zcankara) split up between maps and ics, and every timeline track
return this._chunks;
}
get nofChunks() {
return this._nofChunks;
}
......
......@@ -20,7 +20,7 @@ found in the LICENSE file. -->
let module = await import('./index.mjs');
globalThis.app = new module.App("#log-file-reader", "#map-panel", "#map-stats-panel",
"#timeline-panel", "#ic-panel", "#map-track", "#ic-track", "#deopt-track",
"#source-panel", "#tool-tip");
"#code-track", "#source-panel", "#tool-tip");
})();
</script>
......@@ -103,6 +103,7 @@ found in the LICENSE file. -->
<timeline-track id="map-track"></timeline-track>
<timeline-track id="ic-track"></timeline-track>
<timeline-track id="deopt-track"></timeline-track>
<timeline-track id="code-track"></timeline-track>
</timeline-panel>
<div class="panels">
<map-panel id="map-panel"></map-panel>
......
......@@ -18,7 +18,8 @@ class App {
_startupPromise;
constructor(
fileReaderId, mapPanelId, mapStatsPanelId, timelinePanelId, icPanelId,
mapTrackId, icTrackId, deoptTrackId, sourcePanelId, toolTipId) {
mapTrackId, icTrackId, deoptTrackId, codeTrackId, sourcePanelId,
toolTipId) {
this._view = {
__proto__: null,
logFileReader: $(fileReaderId),
......@@ -29,6 +30,7 @@ class App {
mapTrack: $(mapTrackId),
icTrack: $(icTrackId),
deoptTrack: $(deoptTrackId),
codeTrack: $(codeTrackId),
sourcePanel: $(sourcePanelId),
toolTip: $(toolTipId),
};
......@@ -73,18 +75,28 @@ class App {
}
e.stopPropagation();
}
showMapEntries(entries) {
this._state.selectedMapLogEntries = entries;
this._view.mapPanel.selectedMapLogEntries = entries;
this._view.mapStatsPanel.selectedLogEntries = entries;
}
showIcEntries(entries) {
this._state.selectedIcLogEntries = entries;
this._view.icPanel.selectedLogEntries = entries;
}
showDeoptEntries(entries) {
// TODO: creat list panel.
this._state.selectedDeoptLogEntries = entries;
}
showCodeEntries(entries) {
// TODO: creat list panel
this._state.selectedCodeLogEntries = entries;
}
showSourcePositionEntries(entries) {
// TODO: Handle multiple source position selection events
this._view.sourcePanel.selectedSourcePositions = entries
......@@ -100,6 +112,7 @@ class App {
this.showMapEntries(this._state.mapTimeline.selection);
this.showIcEntries(this._state.icTimeline.selection);
this.showDeoptEntries(this._state.deoptTimeline.selection);
this.showCodeEntries(this._state.codeTimeline.selection);
this._view.timelinePanel.timeSelection = {start, end};
}
......@@ -115,15 +128,18 @@ class App {
}
e.stopPropagation();
}
selectMapLogEntry(entry) {
this._state.map = entry;
this._view.mapTrack.selectedEntry = entry;
this._view.mapPanel.map = entry;
}
selectICLogEntry(entry) {
this._state.ic = entry;
this._view.icPanel.selectedLogEntries = [entry];
}
selectSourcePosition(sourcePositions) {
if (!sourcePositions.script) return;
this._view.sourcePanel.selectedSourcePositions = [sourcePositions];
......@@ -151,19 +167,17 @@ class App {
const mapTimeline = processor.mapTimeline;
const icTimeline = processor.icTimeline;
const deoptTimeline = processor.deoptTimeline;
this._state.mapTimeline = mapTimeline;
this._state.icTimeline = icTimeline;
this._state.deoptTimeline = deoptTimeline;
const codeTimeline = processor.codeTimeline;
this._state.setTimelines(
mapTimeline, icTimeline, deoptTimeline, codeTimeline);
// Transitions must be set before timeline for stats panel.
this._view.mapPanel.timeline = mapTimeline;
this._view.mapTrack.data = mapTimeline;
this._view.mapStatsPanel.transitions =
this._state.mapTimeline.transitions;
this._view.mapStatsPanel.timeline = mapTimeline;
this._view.icPanel.timeline = icTimeline;
this._view.icTrack.data = icTimeline;
this._view.deoptTrack.data = deoptTimeline;
this._view.sourcePanel.data = processor.scripts
this._view.sourcePanel.data =
processor.scripts this.refreshTimelineTrackView();
} catch (e) {
this._view.logFileReader.error = 'Log file contains errors!'
throw (e);
......@@ -177,6 +191,7 @@ class App {
this._view.mapTrack.data = this._state.mapTimeline;
this._view.icTrack.data = this._state.icTimeline;
this._view.deoptTrack.data = this._state.deoptTimeline;
this._view.codeTrack.data = this._state.codeTimeline;
}
switchTheme(event) {
......
......@@ -4,10 +4,29 @@
import {LogEntry} from './log.mjs';
export class DeoptLogEntry extends LogEntry {
constructor(type, time) {
constructor(
type, time, deoptReason, deoptLocation, scriptOffset, instructionStart,
codeSize, inliningId) {
super(type, time);
this._deoptReason = deoptReason;
this._deoptLocation = deoptLocation;
this._scriptOffset = scriptOffset;
this._instructionStart = instructionStart;
this._codeSize = codeSize;
this._inliningId = inliningId;
}
toString() {
return `Deopt(${this.type})`;
return `Deopt(${this.type})${this._deoptReason}: ${this._deoptLocation}`;
}
}
export class CodeLogEntry extends LogEntry {
constructor(type, time, kind, entry) {
super(type, time);
this._kind = kind;
this._entry = entry;
}
toString() {
return `Code(${this.type}): ${this._entry.toString()}`;
}
}
......@@ -5,7 +5,7 @@
import {LogReader, parseString, parseVarArgs} from '../logreader.mjs';
import {Profile} from '../profile.mjs';
import {DeoptLogEntry} from './log/deopt.mjs';
import {CodeLogEntry, DeoptLogEntry} from './log/code.mjs';
import {IcLogEntry} from './log/ic.mjs';
import {Edge, MapLogEntry} from './log/map.mjs';
import {Timeline} from './timeline.mjs';
......@@ -17,6 +17,7 @@ export class Processor extends LogReader {
_mapTimeline = new Timeline();
_icTimeline = new Timeline();
_deoptTimeline = new Timeline();
_codeTimeline = new Timeline();
_formatPCRegexp = /(.*):[0-9]+:[0-9]+$/;
MAJOR_VERSION = 7;
MINOR_VERSION = 6;
......@@ -182,20 +183,24 @@ export class Processor extends LogReader {
}
processCodeCreation(type, kind, timestamp, start, size, name, maybe_func) {
let entry;
if (maybe_func.length) {
const funcAddr = parseInt(maybe_func[0]);
const state = this.parseState(maybe_func[1]);
this._profile.addFuncCode(
entry = this._profile.addFuncCode(
type, name, timestamp, start, size, funcAddr, state);
} else {
this._profile.addCode(type, name, timestamp, start, size);
entry = this._profile.addCode(type, name, timestamp, start, size);
}
this._codeTimeline.push(new CodeLogEntry(type, timestamp, kind, entry));
}
processCodeDeopt(
timestamp, codeSize, instructionStart, inliningId, scriptOffset,
deoptKind, deoptLocation, deoptReason) {
this._deoptTimeline.push(new DeoptLogEntry(deoptKind, timestamp));
this._deoptTimeline.push(new DeoptLogEntry(
deoptKind, timestamp, deoptReason, deoptLocation, scriptOffset,
instructionStart, codeSize, inliningId));
}
processV8Version(majorVersion, minorVersion) {
......@@ -352,6 +357,10 @@ export class Processor extends LogReader {
return this._deoptTimeline;
}
get codeTimeline() {
return this._codeTimeline;
}
get scripts() {
return this._profile.scripts_.filter(script => script !== undefined);
}
......
......@@ -18,6 +18,14 @@ found in the LICENSE file. -->
min-height: 100px;
padding: 10px;
box-shadow: 0px 0px 10px rgba(0,0,0,0.5);
width: auto;
}
.textContent {
font-family: monospace;
white-space: pre;
overflow-x: hidden;
max-width: 500px;
}
#body {
......
......@@ -79,10 +79,11 @@ DOM.defineCustomElement(
this.show();
if (typeof content === 'string') {
this.contentNode.innerHTML = content;
this.contentNode.className = 'textContent';
} else {
const newContent = DOM.div();
newContent.appendChild(content);
this.contentNode.replaceWih(newContent);
this.contentNode.replaceWith(newContent);
newContent.id = 'content';
}
}
......
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