[turbolizer] Wasm integration

This CL allows selection/highlighting of wasm source when a graph node
is clicked.

Bug: v8:7327
Change-Id: I4a3347a83c8a38804feabffefaefd761596005c3
Reviewed-on: https://chromium-review.googlesource.com/1092712
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53636}
This commit is contained in:
Sigurd Schneider 2018-06-11 13:56:45 +02:00 committed by Commit Bot
parent 43fb4c4a77
commit 3f8607bfc8
7 changed files with 121 additions and 34 deletions

View File

@ -14,7 +14,6 @@ class CodeView extends View {
source: Source;
sourceResolver: SourceResolver;
codeMode: CodeMode;
lineToSourcePositions: Map<string, Array<SourcePosition>>;
sourcePositionToHtmlElement: Map<string, HTMLElement>;
showAdditionalInliningPosition: boolean;
selectionHandler: SelectionHandler;
@ -34,7 +33,6 @@ class CodeView extends View {
view.sourceResolver = sourceResolver;
view.source = sourceFunction;
view.codeMode = codeMode;
this.lineToSourcePositions = new Map();
this.sourcePositionToHtmlElement = new Map();
this.showAdditionalInliningPosition = false;
@ -75,14 +73,6 @@ class CodeView extends View {
this.initializeCode();
}
addSourcePositionToLine(lineNumber, sourcePosition) {
const lineNumberString = anyToString(lineNumber);
if (!this.lineToSourcePositions.has(lineNumberString)) {
this.lineToSourcePositions.set(lineNumberString, []);
}
this.lineToSourcePositions.get(lineNumberString).push(sourcePosition);
}
addHtmlElementToSourcePosition(sourcePosition, element) {
const key = sourcePositionToStringKey(sourcePosition);
if (this.sourcePositionToHtmlElement.has(key)) {
@ -122,13 +112,15 @@ class CodeView extends View {
return ordereList.childNodes as NodeListOf<HTMLElement>;
}
onSelectLine(lineNumber, doClear) {
const sourcePositions = this.lineToSourcePositions.get(anyToString(lineNumber));
onSelectLine(lineNumber:number, doClear:boolean) {
const key = anyToString(lineNumber);
if (doClear) {
this.selectionHandler.clear();
}
if (!sourcePositions) return;
this.selectionHandler.select(sourcePositions, undefined);
const positions = this.sourceResolver.linetoSourcePositions(lineNumber - 1);
if (positions !== undefined) {
this.selectionHandler.select(positions, undefined);
}
}
onSelectSourcePosition(sourcePosition, doClear) {
@ -225,7 +217,7 @@ class CodeView extends View {
const view = this;
const sps = this.sourceResolver.sourcePositionsInRange(this.source.sourceId, pos - adjust, end);
for (const sourcePosition of sps) {
view.addSourcePositionToLine(lineNumber, sourcePosition);
this.sourceResolver.addAnyPositionToLine(lineNumber, sourcePosition);
const textnode = currentSpan.tagName == 'SPAN' ? currentSpan.firstChild : currentSpan;
const replacementNode = textnode.splitText(Math.max(0, sourcePosition.scriptOffset - pos));
const span = document.createElement('span');
@ -255,12 +247,18 @@ class CodeView extends View {
const view = this;
const lineNumberElement = document.createElement("div");
lineNumberElement.classList.add("line-number");
lineNumberElement.dataset.lineNumber = lineNumber;
lineNumberElement.innerText = lineNumber;
lineNumberElement.onclick = function (e) {
e.stopPropagation();
view.onSelectLine(lineNumber, !e.shiftKey);
}
lineElement.insertBefore(lineNumberElement, lineElement.firstChild)
// Don't add lines to source positions of not in backwardsCompatibility mode.
if (typeof this.source['backwardsCompatibility'] === undefined) return;
for (const sourcePosition of this.sourceResolver.linetoSourcePositions(lineNumber - 1)) {
view.addHtmlElementToSourcePosition(sourcePosition, lineElement);
}
}
deleteContent() { }

View File

@ -91,6 +91,9 @@ class GraphView extends View implements PhaseView {
if (node.sourcePosition) {
locations.push(node.sourcePosition);
}
if (node.origin && node.origin.bytecodePosition) {
locations.push({bytecodePosition: node.origin.bytecodePosition});
}
}
graph.state.selection.select(nodes, selected);
broker.broadcastSourcePositionSelect(this, locations, selected);

View File

@ -12,6 +12,16 @@ function isNodeInitiallyVisible(node) {
return node.cfg;
}
function formatOrigin(origin) {
if (origin.nodeId) {
return `#${origin.nodeId} in phase ${origin.phase}/${origin.reducer}`;
}
if (origin.bytecodePosition) {
return `Bytecode line ${origin.bytecodePosition} in phase ${origin.phase}/${origin.reducer}`;
}
return "unknown origin";
}
class GNode {
control: boolean;
opcode: string;
@ -79,7 +89,7 @@ class GNode {
}
let title = this.title + "\n" + propsString + "\n" + this.opinfo;
if (this.origin) {
title += `\nOrigin: #${this.origin.nodeId} in phase ${this.origin.phase}/${this.origin.reducer}`;
title += `\nOrigin: ${formatOrigin(this.origin)}`;
}
return title;
}

View File

@ -30,8 +30,7 @@ class SelectionBroker {
broadcastSourcePositionSelect(from, sourcePositions, selected) {
let broker = this;
sourcePositions = sourcePositions.filter((l) => {
if (typeof l.scriptOffset == 'undefined'
|| typeof l.inliningId == 'undefined') {
if (!sourcePositionValid(l)) {
console.log("Warning: invalid source position");
return false;
}

View File

@ -14,9 +14,18 @@ function sourcePositionEq(a, b) {
a.scriptOffset == b.scriptOffset;
}
function sourcePositionToStringKey(sourcePosition) {
function sourcePositionToStringKey(sourcePosition): string {
if (!sourcePosition) return "undefined";
return "" + sourcePosition.inliningId + ":" + sourcePosition.scriptOffset;
if (sourcePosition.inliningId && sourcePosition.scriptOffset)
return "SP:" + sourcePosition.inliningId + ":" + sourcePosition.scriptOffset;
if (sourcePosition.bytecodePosition)
return "BCP:" + sourcePosition.bytecodePosition;
return "undefined";
}
function sourcePositionValid(l) {
return (typeof l.scriptOffset !== undefined
&& typeof l.inliningId !== undefined) || typeof l.bytecodePosition != undefined;
}
interface SourcePosition {
@ -24,6 +33,25 @@ interface SourcePosition {
inliningId: number;
}
interface TurboFanOrigin {
phase: string;
reducer: string;
}
interface NodeOrigin {
nodeId: number;
}
interface BytecodePosition {
bytecodePosition: number;
}
type Origin = NodeOrigin | BytecodePosition;
type TurboFanNodeOrigin = NodeOrigin & TurboFanOrigin;
type TurboFanBytecodeOrigin = BytecodePosition & TurboFanOrigin;
type AnyPosition = SourcePosition | BytecodePosition;
interface Source {
sourcePositions: Array<SourcePosition>;
sourceName: string;
@ -46,14 +74,8 @@ interface Schedule {
nodes: Array<any>;
}
interface NodeOrigin {
nodeId: number;
phase: string;
reducer: string;
}
class SourceResolver {
nodePositionMap: Array<SourcePosition>;
nodePositionMap: Array<AnyPosition>;
sources: Array<Source>;
inlinings: Array<Inlining>;
inliningsMap: Map<string, Inlining>;
@ -61,6 +83,8 @@ class SourceResolver {
phases: Array<Phase>;
phaseNames: Map<string, number>;
disassemblyPhase: Phase;
lineToSourcePositions: Map<string, Array<AnyPosition>>;
constructor() {
// Maps node ids to source positions.
@ -79,6 +103,8 @@ class SourceResolver {
this.phaseNames = new Map();
// The disassembly phase is stored separately.
this.disassemblyPhase = undefined;
// Maps line numbers to source positions
this.lineToSourcePositions = new Map();
}
setSources(sources, mainBackup) {
@ -153,7 +179,7 @@ class SourceResolver {
return nodeIds;
}
nodeIdsToSourcePositions(nodeIds) {
nodeIdsToSourcePositions(nodeIds): Array<AnyPosition> {
const sourcePositions = new Map();
for (const nodeId of nodeIds) {
let sp = this.nodePositionMap[nodeId];
@ -255,6 +281,23 @@ class SourceResolver {
return inliningStack;
}
recordOrigins(phase) {
if (phase.type != "graph") return;
for (const node of phase.data.nodes) {
if (node.origin != undefined &&
node.origin.bytecodePosition != undefined) {
const position = {bytecodePosition: node.origin.bytecodePosition};
this.nodePositionMap[node.id] = position;
let key = sourcePositionToStringKey(position);
if (!this.positionToNodes.has(key)) {
this.positionToNodes.set(key, []);
}
const A = this.positionToNodes.get(key);
if (!A.includes(node.id)) A.push("" + node.id);
}
}
}
parsePhases(phases) {
for (const [phaseId, phase] of Object.entries<Phase>(phases)) {
if (phase.type == 'disassembly') {
@ -264,6 +307,7 @@ class SourceResolver {
this.phaseNames.set(phase.name, this.phases.length);
} else {
this.phases.push(phase);
this.recordOrigins(phase);
this.phaseNames.set(phase.name, this.phases.length);
}
}
@ -285,6 +329,28 @@ class SourceResolver {
this.phases.forEach(f);
}
addAnyPositionToLine(lineNumber:number|String, sourcePosition:AnyPosition) {
const lineNumberString = anyToString(lineNumber);
if (!this.lineToSourcePositions.has(lineNumberString)) {
this.lineToSourcePositions.set(lineNumberString, []);
}
const A = this.lineToSourcePositions.get(lineNumberString);
if (!A.includes(sourcePosition)) A.push(sourcePosition);
}
setSourceLineToBytecodePosition(sourceLineToBytecodePosition:Array<number>|undefined) {
if (!sourceLineToBytecodePosition) return;
sourceLineToBytecodePosition.forEach((pos, i) => {
this.addAnyPositionToLine(i, {bytecodePosition: pos});
});
}
linetoSourcePositions(lineNumber:number|String) {
const positions = this.lineToSourcePositions.get(anyToString(lineNumber));
if (positions === undefined) return [];
return positions;
}
parseSchedule(phase) {
function createNode(state, match) {
let inputs = [];

View File

@ -226,11 +226,13 @@ window.onload = function () {
sourceId: -1,
startPosition: jsonObj.sourcePosition,
endPosition: jsonObj.sourcePosition + jsonObj.source.length,
sourceText: jsonObj.source
sourceText: jsonObj.source,
backwardsCompatibility: true
};
}
sourceResolver.setInlinings(jsonObj.inlinings);
sourceResolver.setSourceLineToBytecodePosition(jsonObj.sourceLineToBytecodePosition);
sourceResolver.setSources(jsonObj.sources, fnc)
sourceResolver.setNodePositionMap(jsonObj.nodePositions);
sourceResolver.parsePhases(jsonObj.phases);

View File

@ -45,7 +45,6 @@
display: none;
}
.selected {
background-color: #FFFF33;
}
@ -64,19 +63,29 @@ ol.linenums {
display:inline-block;
min-width: 3ex;
text-align: right;
color: gray;
padding-right:1ex;
font-size: 10px;
color: #444444;
margin-right: 0.5ex;
padding-right: 0.5ex;
background: #EEEEEE;
/* font-size: 80%; */
user-select: none;
height: 120%;
}
.line-number:hover {
background-color: #CCCCCC;
}
.prettyprint ol.linenums > li.selected {
background-color: #FFFF33 !important;
}
li.selected .line-number {
background-color: #FFFF33;
}
.prettyprint ol.linenums > li {
list-style-type: decimal;
padding-top: 3px;
display: block;
}