Commit 07e7da14 authored by Danylo Boiko's avatar Danylo Boiko Committed by V8 LUCI CQ

[turbolizer] TurboFan nodes history (beta)

Bug: v8:7327
Change-Id: I233173b92ab2acd6e6184abf2769a607df7b6a48
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3779695
Commit-Queue: Danylo Boiko <danielboyko02@gmail.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82088}
parent 3a35d903
:root {
--tspan-font-size: 500%;
--history-tspan-font-size: 120%;
--history-item-tspan-font-size: 100%;
}
.visible-transition {
transition-delay: 0s;
transition-duration: 1s;
......@@ -417,7 +423,7 @@ input:hover,
}
tspan {
font-size: 500%;
font-size: var(--tspan-font-size);
font-family: sans-serif;
}
......@@ -755,3 +761,29 @@ div.highlight-gap-instructions [data-instruction-kind="deoptimization-exits"] {
div.highlight-gap-instructions [data-instruction-kind].selected {
background-color: yellow;
}
svg.history-svg-container {
position: absolute;
z-index: 20;
border-radius: 10px;
background: #f1f1f1;
}
svg.history-svg-container .history-label tspan {
font-size: var(--history-tspan-font-size);
fill: #494848;
}
svg.history-svg-container .close-button {
fill: red;
cursor: pointer;
}
svg.history-svg-container .history-content-scroll {
fill: #a09c9c;
stroke: none;
}
svg.history-svg-container .history-item tspan {
font-size: var(--history-item-tspan-font-size);
}
......@@ -15,6 +15,7 @@ code is governed by a BSD-style license that can be found in the LICENSE file.
</head>
<body>
<div id="history" class="content"></div>
<div id="left" class="content"></div>
<div id="resizer-left" class="resizer"></div>
<div id="middle">
......
......@@ -61,6 +61,10 @@
<td>u</td>
<td>Hide unselected nodes</td>
</tr>
<tr>
<td>h</td>
<td>Show hovered node's history</td>
</tr>
</table>
</div>
</div>
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
export const TRACE_LAYOUT = false;
export const TRACE_HISTORY = false;
export const MAX_RANK_SENTINEL = 0;
export const BEZIER_CONSTANT = 0.3;
......@@ -23,6 +24,10 @@ export const SOURCE_PANE_DEFAULT_PERCENT = 1 / 4;
export const DISASSEMBLY_PANE_DEFAULT_PERCENT = 3 / 4;
export const RANGES_PANE_HEIGHT_DEFAULT_PERCENT = 3 / 4;
export const RANGES_PANE_WIDTH_DEFAULT_PERCENT = 1 / 2;
export const HISTORY_DEFAULT_HEIGHT_PERCENT = 1 / 5;
export const HISTORY_CONTENT_INDENT = 8;
export const HISTORY_SCROLLBAR_WIDTH = 6;
export const CLOSE_BUTTON_RADIUS = 25;
export const RESIZER_RANGES_HEIGHT_BUFFER_PERCENTAGE = 5;
export const ROW_GROUP_SIZE = 20;
export const POSITIONS_PER_INSTRUCTION = 4;
......@@ -31,6 +36,7 @@ export const SESSION_STORAGE_PREFIX = "ranges-setting-";
export const INTERVAL_TEXT_FOR_NONE = "none";
export const INTERVAL_TEXT_FOR_CONST = "const";
export const INTERVAL_TEXT_FOR_STACK = "stack:";
export const HISTORY_ID = "history";
export const MULTIVIEW_ID = "multiview";
export const RESIZER_RANGES_ID = "resizer-ranges";
export const SHOW_HIDE_RANGES_ID = "show-hide-ranges";
......
......@@ -52,13 +52,14 @@ export function alignUp(raw: number, multiple: number): number {
return Math.floor((raw + multiple - 1) / multiple) * multiple;
}
export function measureText(text: string): { width: number, height: number } {
export function measureText(text: string, coefficient: number = 1):
{ width: number, height: number } {
const textMeasure = document.getElementById("text-measure");
if (textMeasure instanceof SVGTSpanElement) {
textMeasure.textContent = text;
return {
width: textMeasure.getBBox().width,
height: textMeasure.getBBox().height,
width: textMeasure.getBBox().width * coefficient,
height: textMeasure.getBBox().height * coefficient,
};
}
return { width: 0, height: 0 };
......@@ -94,3 +95,8 @@ export function copyToClipboard(text: string): void {
if (!text || text.length == 0) return;
navigator.clipboard.writeText(text);
}
export function getNumericCssValue(varName: string): number {
const propertyValue = getComputedStyle(document.body).getPropertyValue(varName);
return parseFloat(propertyValue.match(/[+-]?\d+(\.\d+)?/g)[0]);
}
......@@ -35,7 +35,7 @@ export class GraphMultiView extends View {
selectMenu: HTMLSelectElement;
currentPhaseView: PhaseView;
constructor(id, selectionBroker, sourceResolver) {
constructor(id: string, selectionBroker: SelectionBroker, sourceResolver: SourceResolver) {
super(id);
const view = this;
view.sourceResolver = sourceResolver;
......
......@@ -109,4 +109,9 @@ export class GraphNode extends Node<GraphEdge> {
this.nodeLabel.opcode === "InductionVariablePhi") &&
this.inputs[this.inputs.length - 1].source.nodeLabel.opcode === "Loop");
}
public equals(that?: GraphNode): boolean {
if (!that) return false;
return this.nodeLabel.equals(that.nodeLabel);
}
}
......@@ -13,6 +13,7 @@ export class TurboshaftGraphPhase extends Phase {
nodeIdToNodeMap: Array<TurboshaftGraphNode>;
blockIdToBlockMap: Array<TurboshaftGraphBlock>;
rendered: boolean;
propertiesShowed: boolean;
transform: { x: number, y: number, scale: number };
constructor(name: string, dataJson) {
......
......@@ -3,18 +3,21 @@
// found in the LICENSE file.
import { GenericPosition, SourceResolver } from "../source-resolver";
import { GraphNode } from "../phases/graph-phase/graph-node";
import {
ClearableHandler,
SourcePositionSelectionHandler,
NodeSelectionHandler,
BlockSelectionHandler,
InstructionSelectionHandler,
RegisterAllocationSelectionHandler
RegisterAllocationSelectionHandler,
HistoryHandler
} from "./selection-handler";
export class SelectionBroker {
sourceResolver: SourceResolver;
allHandlers: Array<ClearableHandler>;
historyHandlers: Array<HistoryHandler>;
nodeHandlers: Array<NodeSelectionHandler>;
blockHandlers: Array<BlockSelectionHandler>;
instructionHandlers: Array<InstructionSelectionHandler>;
......@@ -24,6 +27,7 @@ export class SelectionBroker {
constructor(sourceResolver: SourceResolver) {
this.sourceResolver = sourceResolver;
this.allHandlers = new Array<ClearableHandler>();
this.historyHandlers = new Array<HistoryHandler>();
this.nodeHandlers = new Array<NodeSelectionHandler>();
this.blockHandlers = new Array<BlockSelectionHandler>();
this.instructionHandlers = new Array<InstructionSelectionHandler>();
......@@ -31,6 +35,14 @@ export class SelectionBroker {
this.registerAllocationHandlers = new Array<RegisterAllocationSelectionHandler>();
}
public addHistoryHandler(handler: HistoryHandler): void {
this.historyHandlers.push(handler);
}
public deleteHistoryHandler(handler: HistoryHandler): void {
this.historyHandlers = this.historyHandlers.filter(h => h != handler);
}
public addNodeHandler(handler: NodeSelectionHandler & ClearableHandler): void {
this.allHandlers.push(handler);
this.nodeHandlers.push(handler);
......@@ -68,6 +80,12 @@ export class SelectionBroker {
this.registerAllocationHandlers.push(handler);
}
public broadcastHistoryShow(from, node: GraphNode, phaseName: string): void {
for (const handler of this.historyHandlers) {
if (handler != from) handler.showTurbofanNodeHistory(node, phaseName);
}
}
// TODO (danylo boiko) Add instructionOffsets type
public broadcastInstructionSelect(from, instructionOffsets, selected: boolean): void {
// Select the lines from the disassembly (right panel)
......
......@@ -11,6 +11,10 @@ export interface ClearableHandler {
brokeredClear(): void;
}
export interface HistoryHandler {
showTurbofanNodeHistory(node: GraphNode, phaseName: string): void;
}
export interface NodeSelectionHandler {
select(nodes: Iterable<TurboshaftGraphNode | GraphNode | string | number>, selected: boolean):
void;
......
......@@ -259,6 +259,10 @@ export class SourceResolver {
return this.phases[phaseId];
}
public getPhaseNameById(phaseId: number): string {
return this.getPhase(phaseId).name;
}
public getPhaseIdByName(phaseName: string): number {
return this.phaseNames.get(phaseName);
}
......
......@@ -11,11 +11,13 @@ import { CodeMode, CodeView } from "./views/code-view";
import { Tabs } from "./tabs";
import { Resizer } from "./resizer";
import { InfoView } from "./views/info-view";
import { HistoryView } from "./views/history-view";
window.onload = function () {
let multiview: GraphMultiView;
let disassemblyView: DisassemblyView;
let sourceViews: Array<CodeView> = new Array<CodeView>();
let historyView: HistoryView;
let selectionBroker: SelectionBroker;
let sourceResolver: SourceResolver;
......@@ -51,6 +53,7 @@ window.onload = function () {
document.getElementById("ranges").style.visibility = "hidden";
document.getElementById("show-hide-ranges").style.visibility = "hidden";
disassemblyView?.hide();
historyView?.hide();
sourceViews = new Array<CodeView>();
sourceResolver = new SourceResolver();
selectionBroker = new SelectionBroker(sourceResolver);
......@@ -93,6 +96,9 @@ window.onload = function () {
multiview = new GraphMultiView(C.INTERMEDIATE_PANE_ID, selectionBroker, sourceResolver);
multiview.show();
historyView = new HistoryView(C.HISTORY_ID, selectionBroker, sourceResolver);
historyView.show();
} catch (err) {
if (window.confirm("Error: Exception during load of TurboFan JSON file:\n" +
`error: ${err.message} \nDo you want to clear session storage?`)) {
......
......@@ -166,6 +166,7 @@ export class GraphView extends MovableView<Graph> {
const adjOutputNodes = adjOutputEdges.data().map(edge => edge.target);
visibleNodes.data<GraphNode>(adjOutputNodes, node => node.toString())
.attr("relToHover", "output");
view.hoveredNodeIdentifier = node.identifier();
view.updateGraphVisibility();
})
.on("mouseleave", node => {
......@@ -176,6 +177,7 @@ export class GraphView extends MovableView<Graph> {
.concat(adjEdges.data().map(edge => edge.source));
const visibleNodes = view.visibleNodes.selectAll<SVGPathElement, GraphNode>("g");
visibleNodes.data(adjNodes, node => node.toString()).attr("relToHover", "none");
view.hoveredNodeIdentifier = null;
view.updateGraphVisibility();
})
.on("click", node => {
......@@ -230,7 +232,7 @@ export class GraphView extends MovableView<Graph> {
.select("rect")
.attr("height", node => node.getHeight(view.state.showTypes));
view.visibleBubbles = d3.selectAll("circle");
view.visibleBubbles = view.svg.selectAll("circle");
view.updateInputAndOutputBubbles();
......@@ -241,6 +243,10 @@ export class GraphView extends MovableView<Graph> {
public svgKeyDown(): void {
let eventHandled = true; // unless the below switch defaults
switch (d3.event.keyCode) {
case 38: // UP
case 40: // DOWN
this.showSelectionFrontierNodes(d3.event.keyCode == 38, undefined, true);
break;
case 49:
case 50:
case 51:
......@@ -254,18 +260,8 @@ export class GraphView extends MovableView<Graph> {
(edge: GraphEdge, index: number) => index == (d3.event.keyCode - 49),
!d3.event.ctrlKey);
break;
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105: // 'numpad 1'-'numpad 9'
this.showSelectionFrontierNodes(true,
(edge: GraphEdge, index) => index == (d3.event.keyCode - 97),
!d3.event.ctrlKey);
case 65: // 'a'
this.selectAllNodes();
break;
case 67: // 'c'
this.showSelectionFrontierNodes(d3.event.altKey,
......@@ -277,8 +273,8 @@ export class GraphView extends MovableView<Graph> {
(edge: GraphEdge) => edge.type === "effect",
true);
break;
case 79: // 'o'
this.showSelectionFrontierNodes(false, undefined, false);
case 72: // 'h'
this.showHoveredNodeHistory();
break;
case 73: // 'i'
if (!d3.event.ctrlKey && !d3.event.shiftKey) {
......@@ -287,12 +283,11 @@ export class GraphView extends MovableView<Graph> {
eventHandled = false;
}
break;
case 65: // 'a'
this.selectAllNodes();
case 79: // 'o'
this.showSelectionFrontierNodes(false, undefined, false);
break;
case 38: // UP
case 40: // DOWN
this.showSelectionFrontierNodes(d3.event.keyCode == 38, undefined, true);
case 80: // 'p'
this.selectOrigins();
break;
case 82: // 'r'
if (!d3.event.ctrlKey && !d3.event.shiftKey) {
......@@ -301,9 +296,6 @@ export class GraphView extends MovableView<Graph> {
eventHandled = false;
}
break;
case 80: // 'p'
this.selectOrigins();
break;
case 83: // 's'
if (!d3.event.ctrlKey && !d3.event.shiftKey) {
this.hideSelectedAction(this);
......@@ -318,6 +310,19 @@ export class GraphView extends MovableView<Graph> {
eventHandled = false;
}
break;
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105: // 'numpad 1'-'numpad 9'
this.showSelectionFrontierNodes(true,
(edge: GraphEdge, index) => index == (d3.event.keyCode - 97),
!d3.event.ctrlKey);
break;
default:
eventHandled = false;
break;
......@@ -699,6 +704,12 @@ export class GraphView extends MovableView<Graph> {
this.updateGraphVisibility();
}
public showHoveredNodeHistory(): void {
const node = this.graph.nodeMap[this.hoveredNodeIdentifier];
if (!node) return;
this.broker.broadcastHistoryShow(null, node, this.phaseName);
}
private selectOrigins(): void {
const origins = new Array<GraphNode>();
let phase = this.phaseName;
......
This diff is collapsed.
......@@ -29,6 +29,7 @@ export abstract class MovableView<GraphType extends Graph | TurboshaftGraph> ext
graphElement: d3.Selection<any, any, any, any>;
svg: d3.Selection<any, any, any, any>;
panZoom: d3.ZoomBehavior<SVGElement, any>;
hoveredNodeIdentifier: string;
public abstract updateGraphVisibility(): void;
public abstract svgKeyDown(): void;
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
import * as C from "../common/constants";
import { createElement, storageGetItem, storageSetItem } from "../common/util";
import { createElement, getNumericCssValue, storageGetItem, storageSetItem } from "../common/util";
import { SequenceView } from "./sequence-view";
import { Interval } from "../interval";
import { ChildRange, Range, SequenceBlock } from "../phases/sequence-phase";
......@@ -106,13 +106,8 @@ class CSSVariables {
blockBorderWidth: number;
constructor() {
this.positionWidth = this.getNumericValue("--range-position-width");
this.blockBorderWidth = this.getNumericValue("--range-block-border");
}
private getNumericValue(varName: string): number {
const propertyValue = getComputedStyle(document.body).getPropertyValue(varName);
return parseFloat(propertyValue.match(/[+-]?\d+(\.\d+)?/g)[0]);
this.positionWidth = getNumericCssValue("--range-position-width");
this.blockBorderWidth = getNumericCssValue("--range-block-border");
}
}
......
......@@ -33,7 +33,6 @@ export class TurboshaftGraphView extends MovableView<TurboshaftGraph> {
visibleEdges: d3.Selection<any, TurboshaftGraphEdge<TurboshaftGraphBlock>, any, any>;
visibleBubbles: d3.Selection<any, any, any, any>;
blockDrag: d3.DragBehavior<any, TurboshaftGraphBlock, TurboshaftGraphBlock>;
hoveredNodeIdentifier: string;
constructor(idOrContainer: string | HTMLElement, broker: SelectionBroker,
showPhaseByName: (name: string) => void, toolbox: HTMLElement) {
......@@ -99,6 +98,10 @@ export class TurboshaftGraphView extends MovableView<TurboshaftGraph> {
this.viewWholeGraph();
}
}
if (this.graphLayout.graph.graphPhase.propertiesShowed != this.state.showProperties) {
this.compressLayoutAction(this);
}
}
public updateGraphVisibility(): void {
......@@ -189,6 +192,7 @@ export class TurboshaftGraphView extends MovableView<TurboshaftGraph> {
}
public hide(): void {
this.graphLayout.graph.graphPhase.propertiesShowed = this.state.showProperties;
this.broker.deleteBlockHandler(this.blockSelectionHandler);
super.hide();
}
......
......@@ -36,6 +36,7 @@
"src/views/view.ts",
"src/views/code-view.ts",
"src/views/graph-view.ts",
"src/views/history-view.ts",
"src/views/schedule-view.ts",
"src/views/disassembly-view.ts",
"src/views/text-view.ts",
......
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