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

[turbolizer] Turboshaft custom blocks/nodes data

Bug: v8:7327
Change-Id: I41faceac568a87cec4ae47ce2e4fc2c03822ddca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3794649
Commit-Queue: Danylo Boiko <danielboyko02@gmail.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82421}
parent 57308457
......@@ -165,6 +165,7 @@ body {
display: flex;
flex-direction: row;
width: 100vw;
height: 100vh;
}
p {
......@@ -357,8 +358,11 @@ input:hover,
display: inline-flex;
}
.viewpane {
#multiview {
height: 100vh;
}
.viewpane {
background-color: #FFFFFF;
display: flex;
flex-direction: column;
......@@ -792,3 +796,7 @@ svg.history-svg-container .history-item-record tspan:hover {
fill: #606060;
cursor: pointer;
}
svg.history-svg-container .current-history-item tspan {
font-weight: bold;
}
......@@ -73,8 +73,8 @@ g.loop rect {
fill: var(--select);
}
.inline-node-properties tspan, .block-collapsed-label tspan {
fill: #ca48f6;
.inline-node-custom-data tspan, .block-collapsed-label tspan {
fill: #c34ce8;
}
g.turboshaft-node.input .inline-node-label tspan {
......@@ -85,8 +85,8 @@ g.turboshaft-node.output .inline-node-label tspan {
fill: var(--output);
}
#layout-type-select {
box-sizing: border-box;
#custom-data-select {
height: 1.5em;
margin-left: 5px;
margin: 0 3px;
}
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
......@@ -20,6 +20,7 @@ export abstract class Phase {
export enum PhaseType {
Graph = "graph",
TurboshaftGraph = "turboshaft_graph",
TurboshaftCustomData = "turboshaft_custom_data",
Disassembly = "disassembly",
Instructions = "instructions",
Sequence = "sequence",
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { Phase, PhaseType } from "./phase";
export class TurboshaftCustomDataPhase extends Phase {
dataTarget: DataTarget;
data: Array<string>;
constructor(name: string, dataTarget: DataTarget, dataJSON) {
super(name, PhaseType.TurboshaftCustomData);
this.dataTarget = dataTarget;
this.data = new Array<string>();
this.parseDataFromJSON(dataJSON);
}
private parseDataFromJSON(dataJSON): void {
if (!dataJSON) return;
for (const item of dataJSON) {
this.data[item.key] = item.value;
}
}
}
export enum DataTarget {
Nodes = "operations",
Blocks = "blocks"
}
......@@ -13,7 +13,7 @@ export class TurboshaftGraphBlock extends Node<TurboshaftGraphEdge<TurboshaftGra
deferred: boolean;
predecessors: Array<string>;
nodes: Array<TurboshaftGraphNode>;
showProperties: boolean;
showCustomData: boolean;
collapsed: boolean;
collapsedLabel: string;
collapsedLabelBox: { width: number, height: number };
......@@ -30,14 +30,14 @@ export class TurboshaftGraphBlock extends Node<TurboshaftGraphEdge<TurboshaftGra
this.visible = true;
}
public getHeight(showProperties: boolean): number {
public getHeight(showCustomData: boolean): number {
if (this.collapsed) return this.labelBox.height + this.collapsedLabelBox.height;
if (this.showProperties != showProperties) {
if (this.showCustomData != showCustomData) {
this.height = this.nodes.reduce<number>((accumulator: number, node: TurboshaftGraphNode) => {
return accumulator + node.getHeight(showProperties);
return accumulator + node.getHeight(showCustomData);
}, this.labelBox.height);
this.showProperties = showProperties;
this.showCustomData = showCustomData;
}
return this.height;
......@@ -58,7 +58,7 @@ export class TurboshaftGraphBlock extends Node<TurboshaftGraphEdge<TurboshaftGra
public compressHeight(): void {
if (this.collapsed) {
this.height = this.getHeight(null);
this.showProperties = null;
this.showCustomData = null;
}
}
......
......@@ -12,32 +12,25 @@ export class TurboshaftGraphNode extends Node<TurboshaftGraphEdge<TurboshaftGrap
title: string;
block: TurboshaftGraphBlock;
opPropertiesType: OpPropertiesType;
properties: string;
propertiesBox: { width: number, height: number };
constructor(id: number, title: string, block: TurboshaftGraphBlock,
opPropertiesType: OpPropertiesType, properties: string) {
opPropertiesType: OpPropertiesType) {
super(id);
this.title = title;
this.block = block;
this.opPropertiesType = opPropertiesType;
this.properties = properties;
this.propertiesBox = measureText(this.properties);
this.visible = true;
}
public getHeight(showProperties: boolean): number {
if (this.properties && showProperties) {
return this.labelBox.height + this.propertiesBox.height;
}
return this.labelBox.height;
public getHeight(showCustomData: boolean): number {
return showCustomData ? this.labelBox.height * 2 : this.labelBox.height;
}
public getWidth(): number {
return Math.max(this.inputs.length * C.NODE_INPUT_WIDTH, this.labelBox.width);
}
public initDisplayLabel() {
public initDisplayLabel(): void {
this.displayLabel = this.getInlineLabel();
this.labelBox = measureText(this.displayLabel);
}
......@@ -50,21 +43,13 @@ export class TurboshaftGraphNode extends Node<TurboshaftGraphEdge<TurboshaftGrap
if (this.outputs.length > 0) {
title += `\nOutputs: ${this.outputs.map(i => i.target.id).join(", ")}`;
}
const opPropertiesStr = this.properties.length > 0 ? this.properties : "No op properties";
return `${title}\n${opPropertiesStr}`;
return title;
}
public getInlineLabel(): string {
if (this.inputs.length == 0) return `${this.id} ${this.title}`;
return `${this.id} ${this.title}(${this.inputs.map(i => i.source.id).join(",")})`;
}
public getReadableProperties(blockWidth: number): string {
if (blockWidth > this.propertiesBox.width) return this.properties;
const widthOfOneSymbol = Math.floor(this.propertiesBox.width / this.properties.length);
const lengthOfReadableProperties = Math.floor(blockWidth / widthOfOneSymbol);
return `${this.properties.slice(0, lengthOfReadableProperties - 3)}..`;
}
}
export enum OpPropertiesType {
......
......@@ -6,19 +6,22 @@ import { GraphStateType, Phase, PhaseType } from "../phase";
import { TurboshaftGraphNode } from "./turboshaft-graph-node";
import { TurboshaftGraphEdge } from "./turboshaft-graph-edge";
import { TurboshaftGraphBlock } from "./turboshaft-graph-block";
import { DataTarget, TurboshaftCustomDataPhase } from "../turboshaft-custom-data-phase";
export class TurboshaftGraphPhase extends Phase {
data: TurboshaftGraphData;
customData: TurboshaftCustomData;
stateType: GraphStateType;
nodeIdToNodeMap: Array<TurboshaftGraphNode>;
blockIdToBlockMap: Array<TurboshaftGraphBlock>;
rendered: boolean;
propertiesShowed: boolean;
customDataShowed: boolean;
transform: { x: number, y: number, scale: number };
constructor(name: string, dataJson) {
super(name, PhaseType.TurboshaftGraph);
this.stateType = GraphStateType.NeedToFullRebuild;
this.customData = new TurboshaftCustomData();
this.nodeIdToNodeMap = new Array<TurboshaftGraphNode>();
this.blockIdToBlockMap = new Array<TurboshaftGraphBlock>();
this.rendered = false;
......@@ -53,7 +56,7 @@ export class TurboshaftGraphPhase extends Phase {
for (const nodeJson of nodesJson) {
const block = this.blockIdToBlockMap[nodeJson.block_id];
const node = new TurboshaftGraphNode(nodeJson.id, nodeJson.title,
block, nodeJson.op_properties_type, nodeJson.properties);
block, nodeJson.op_properties_type);
block.nodes.push(node);
this.data.nodes.push(node);
this.nodeIdToNodeMap[node.identifier()] = node;
......@@ -89,3 +92,43 @@ export class TurboshaftGraphData {
this.blocks = new Array<TurboshaftGraphBlock>();
}
}
export class TurboshaftCustomData {
nodes: Map<string, TurboshaftCustomDataPhase>;
blocks: Map<string, TurboshaftCustomDataPhase>;
constructor() {
this.nodes = new Map<string, TurboshaftCustomDataPhase>();
this.blocks = new Map<string, TurboshaftCustomDataPhase>();
}
public addCustomData(customDataPhase: TurboshaftCustomDataPhase): void {
switch (customDataPhase.dataTarget) {
case DataTarget.Nodes:
this.nodes.set(customDataPhase.name, customDataPhase);
break;
case DataTarget.Blocks:
this.blocks.set(customDataPhase.name, customDataPhase);
break;
default:
throw "Unsupported turboshaft custom data target type";
}
}
public getTitle(key: number, dataTarget: DataTarget): string {
switch (dataTarget) {
case DataTarget.Nodes:
return this.concatCustomData(key, this.nodes);
case DataTarget.Blocks:
return this.concatCustomData(key, this.blocks);
}
}
private concatCustomData(key: number, items: Map<string, TurboshaftCustomDataPhase>): string {
let customData = "";
for (const [name, dataPhase] of items.entries()) {
customData += `\n${name}: ${dataPhase.data[key] ?? ""}`;
}
return customData;
}
}
......@@ -13,11 +13,12 @@ import { SequencePhase } from "./phases/sequence-phase";
import { BytecodeOrigin } from "./origin";
import { Source } from "./source";
import { NodeLabel } from "./node-label";
import { TurboshaftCustomDataPhase } from "./phases/turboshaft-custom-data-phase";
import { TurboshaftGraphPhase } from "./phases/turboshaft-graph-phase/turboshaft-graph-phase";
export type GenericPosition = SourcePosition | BytecodePosition;
export type GenericPhase = GraphPhase | TurboshaftGraphPhase | DisassemblyPhase
| InstructionsPhase | SchedulePhase | SequencePhase;
export type GenericPhase = GraphPhase | TurboshaftGraphPhase | TurboshaftCustomDataPhase
| DisassemblyPhase | InstructionsPhase | SchedulePhase | SequencePhase;
export class SourceResolver {
nodePositionMap: Array<GenericPosition>;
......@@ -129,6 +130,7 @@ export class SourceResolver {
public parsePhases(phasesJson): void {
const nodeLabelMap = new Array<NodeLabel>();
let lastTurboshaftGraphPhase: TurboshaftGraphPhase = null;
for (const [, genericPhase] of Object.entries<GenericPhase>(phasesJson)) {
switch (genericPhase.type) {
case PhaseType.Disassembly:
......@@ -179,6 +181,13 @@ export class SourceResolver {
castedTurboshaftGraph.data);
this.phaseNames.set(turboshaftGraphPhase.name, this.phases.length);
this.phases.push(turboshaftGraphPhase);
lastTurboshaftGraphPhase = turboshaftGraphPhase;
break;
case PhaseType.TurboshaftCustomData:
const castedCustomData = camelize(genericPhase) as TurboshaftCustomDataPhase;
const customDataPhase = new TurboshaftCustomDataPhase(castedCustomData.name,
castedCustomData.dataTarget, castedCustomData.data);
lastTurboshaftGraphPhase?.customData?.addCustomData(customDataPhase);
break;
default:
throw "Unsupported phase type";
......
......@@ -102,7 +102,7 @@ window.onload = function () {
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?`)) {
`error: ${err} \nDo you want to clear session storage?`)) {
window.sessionStorage.clear();
}
return;
......
......@@ -21,10 +21,10 @@ export class TurboshaftGraphLayout {
this.maxRank = 0;
}
public rebuild(showProperties: boolean): void {
public rebuild(showCustomData: boolean): void {
switch (this.graph.graphPhase.stateType) {
case GraphStateType.NeedToFullRebuild:
this.fullRebuild(showProperties);
this.fullRebuild(showCustomData);
break;
case GraphStateType.Cached:
this.cachedRebuild();
......@@ -35,7 +35,7 @@ export class TurboshaftGraphLayout {
this.graph.graphPhase.rendered = true;
}
private fullRebuild(showProperties: boolean): void {
private fullRebuild(showCustomData: boolean): void {
this.startTime = performance.now();
this.maxRank = 0;
this.visitOrderWithinRank = 0;
......@@ -46,8 +46,8 @@ export class TurboshaftGraphLayout {
const visited = new Array<boolean>();
blocks.forEach((block: TurboshaftGraphBlock) => this.dfsRankOrder(visited, block));
const rankSets = this.getRankSets(showProperties);
this.placeBlocks(rankSets, showProperties);
const rankSets = this.getRankSets(showCustomData);
this.placeBlocks(rankSets, showCustomData);
this.calculateBackEdgeNumbers();
this.graph.graphPhase.stateType = GraphStateType.Cached;
}
......@@ -133,8 +133,8 @@ export class TurboshaftGraphLayout {
}
}
private getRankSets(showProperties: boolean): Array<Array<TurboshaftGraphBlock>> {
const ranksMaxBlockHeight = this.graph.getRanksMaxBlockHeight(showProperties);
private getRankSets(showCustomData: boolean): Array<Array<TurboshaftGraphBlock>> {
const ranksMaxBlockHeight = this.graph.getRanksMaxBlockHeight(showCustomData);
const rankSets = new Array<Array<TurboshaftGraphBlock>>();
for (const block of this.graph.blocks()) {
block.y = ranksMaxBlockHeight.slice(1, block.rank).reduce<number>((accumulator, current) => {
......@@ -149,13 +149,13 @@ export class TurboshaftGraphLayout {
return rankSets;
}
private placeBlocks(rankSets: Array<Array<TurboshaftGraphBlock>>, showProperties: boolean): void {
private placeBlocks(rankSets: Array<Array<TurboshaftGraphBlock>>, showCustomData: boolean): void {
// Iterate backwards from highest to lowest rank, placing blocks so that they
// spread out from the "center" as much as possible while still being
// compact and not overlapping live input lines.
rankSets.reverse().forEach((rankSet: Array<TurboshaftGraphBlock>) => {
for (const block of rankSet) {
this.layoutOccupation.clearOutputs(block, showProperties);
this.layoutOccupation.clearOutputs(block, showCustomData);
}
this.traceOccupation("After clearing outputs");
......@@ -178,7 +178,7 @@ export class TurboshaftGraphLayout {
this.traceOccupation("After clearing blocks");
for (const block of rankSet) {
this.layoutOccupation.occupyInputs(block, showProperties);
this.layoutOccupation.occupyInputs(block, showCustomData);
}
this.traceOccupation("After occupying inputs and determining bounding box");
......
......@@ -4,19 +4,25 @@
import * as C from "./common/constants";
import { MovableContainer } from "./movable-container";
import { TurboshaftGraphPhase } from "./phases/turboshaft-graph-phase/turboshaft-graph-phase";
import { TurboshaftGraphNode } from "./phases/turboshaft-graph-phase/turboshaft-graph-node";
import { TurboshaftGraphBlock } from "./phases/turboshaft-graph-phase/turboshaft-graph-block";
import { TurboshaftGraphEdge } from "./phases/turboshaft-graph-phase/turboshaft-graph-edge";
import { DataTarget } from "./phases/turboshaft-custom-data-phase";
import {
TurboshaftCustomData,
TurboshaftGraphPhase
} from "./phases/turboshaft-graph-phase/turboshaft-graph-phase";
export class TurboshaftGraph extends MovableContainer<TurboshaftGraphPhase> {
blockMap: Array<TurboshaftGraphBlock>;
nodeMap: Array<TurboshaftGraphNode>;
customData: TurboshaftCustomData;
constructor(graphPhase: TurboshaftGraphPhase) {
super(graphPhase);
this.blockMap = graphPhase.blockIdToBlockMap;
this.nodeMap = graphPhase.nodeIdToNodeMap;
this.customData = graphPhase.customData;
}
public *blocks(func = (b: TurboshaftGraphBlock) => true) {
......@@ -53,7 +59,7 @@ export class TurboshaftGraph extends MovableContainer<TurboshaftGraphPhase> {
}
}
public redetermineGraphBoundingBox(showProperties: boolean):
public redetermineGraphBoundingBox(showCustomData: boolean):
[[number, number], [number, number]] {
this.minGraphX = 0;
this.maxGraphNodeX = 1;
......@@ -65,7 +71,7 @@ export class TurboshaftGraph extends MovableContainer<TurboshaftGraphPhase> {
this.maxGraphNodeX = Math.max(this.maxGraphNodeX, block.x + block.getWidth());
this.minGraphY = Math.min(this.minGraphY, block.y - C.NODE_INPUT_WIDTH);
this.maxGraphY = Math.max(this.maxGraphY, block.y + block.getHeight(showProperties)
this.maxGraphY = Math.max(this.maxGraphY, block.y + block.getHeight(showCustomData)
+ C.NODE_INPUT_WIDTH);
}
......@@ -80,12 +86,30 @@ export class TurboshaftGraph extends MovableContainer<TurboshaftGraphPhase> {
];
}
public getRanksMaxBlockHeight(showProperties: boolean): Array<number> {
public hasCustomData(customData: string, dataTarget: DataTarget): boolean {
switch (dataTarget) {
case DataTarget.Nodes:
return this.customData.nodes.has(customData);
case DataTarget.Blocks:
return this.customData.blocks.has(customData);
}
}
public getCustomData(customData: string, key: number, dataTarget: DataTarget): string {
switch (dataTarget) {
case DataTarget.Nodes:
return this.customData.nodes.get(customData).data[key];
case DataTarget.Blocks:
return this.customData.blocks.get(customData).data[key];
}
}
public getRanksMaxBlockHeight(showCustomData: boolean): Array<number> {
const ranksMaxBlockHeight = new Array<number>();
for (const block of this.blocks()) {
ranksMaxBlockHeight[block.rank] = Math.max(ranksMaxBlockHeight[block.rank] ?? 0,
block.getHeight(showProperties));
block.getHeight(showCustomData));
}
return ranksMaxBlockHeight;
......
......@@ -181,6 +181,7 @@ export class HistoryView extends View {
this.historyList
.append("text")
.classed("history-item history-item-record", true)
.classed("current-history-item", record.changes.has(HistoryChange.Current))
.attr("dy", recordY)
.attr("dx", this.labelBox.height * 0.75)
.append("tspan")
......@@ -389,7 +390,11 @@ export class HistoryView extends View {
this.phaseIdToHistory.set(phaseId, new PhaseHistory(phaseId));
}
this.phaseIdToHistory.get(phaseId).addChange(node, change);
this.maxNodeWidth = Math.max(this.maxNodeWidth, node.labelBox.width);
if (change == HistoryChange.Current) {
this.maxNodeWidth = Math.max(this.maxNodeWidth, node.labelBox.width * 1.07);
} else {
this.maxNodeWidth = Math.max(this.maxNodeWidth, node.labelBox.width);
}
}
private clear(): void {
......
......@@ -252,6 +252,13 @@ export abstract class MovableView<GraphType extends Graph | TurboshaftGraph> ext
})];
}
protected createImgToggleInput(id: string, title: string, initState: boolean, onClick):
HTMLElement {
const input = this.createImgInput(id, title, onClick);
input.classList.toggle("button-input-toggled", initState);
return input;
}
private deleteContent(): void {
for (const item of this.toolbox.querySelectorAll(".graph-toolbox-item")) {
item.parentElement.removeChild(item);
......@@ -283,13 +290,6 @@ export abstract class MovableView<GraphType extends Graph | TurboshaftGraph> ext
input.addEventListener("click", onClick);
return input;
}
private createImgToggleInput(id: string, title: string, initState: boolean, onClick):
HTMLElement {
const input = this.createImgInput(id, title, onClick);
input.classList.toggle("button-input-toggled", initState);
return input;
}
}
export class MovableViewState {
......@@ -312,12 +312,12 @@ export class MovableViewState {
storageSetItem("toggle-types", value);
}
public get showProperties(): boolean {
return storageGetItem("toggle-properties", false);
public get showCustomData(): boolean {
return storageGetItem("toggle-custom-data", false);
}
public set showProperties(value: boolean) {
storageSetItem("toggle-properties", value);
public set showCustomData(value: boolean) {
storageSetItem("toggle-custom-data", value);
}
public get cacheLayout(): boolean {
......
......@@ -29,6 +29,7 @@
"src/phases/phase.ts",
"src/phases/schedule-phase.ts",
"src/phases/sequence-phase.ts",
"src/phases/turboshaft-custom-data-phase.ts",
"src/selection/selection-storage.ts",
"src/selection/selection-map.ts",
"src/selection/selection-broker.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