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

[turbolizer] Phases layer initial commit

- Added separate layer for phases
- Moved json parsing logic to new layer

Change-Id: I16289b1f4f62d011c1801fbc37bac49ff911e61e
Bug: v8:7327
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3695566
Commit-Queue: Danylo Boiko <danielboyko02@gmail.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81081}
parent dd6d96c8
......@@ -6,6 +6,27 @@ export function anyToString(x: any): string {
return `${x}`;
}
export function snakeToCamel(str: string): string {
return str.toLowerCase().replace(/([-_][a-z])/g, group =>
group
.toUpperCase()
.replace('-', '')
.replace('_', ''));
}
export function camelize(obj: any): any {
if (Array.isArray(obj)) {
return obj.map(value => camelize(value));
} else if (obj !== null && obj.constructor === Object) {
return Object.keys(obj).reduce((result, key) => ({
...result,
[snakeToCamel(key)]: camelize(obj[key])
}), {},
);
}
return obj;
}
export function sortUnique<T>(arr: Array<T>, f: (a: T, b: T) => number, equal: (a: T, b: T) => boolean): Array<T> {
if (arr.length == 0) return arr;
arr = arr.sort(f);
......
import { GNode, MINIMUM_EDGE_SEPARATION } from "./node";
import { Edge } from "./edge";
import { GraphPhase } from "./phases/graph-phase";
export class Graph {
nodeMap: Array<GNode>;
......@@ -12,7 +13,7 @@ export class Graph {
width: number;
height: number;
constructor(data: any) {
constructor(graphPhase: GraphPhase) {
this.nodeMap = [];
this.minGraphX = 0;
......@@ -22,13 +23,13 @@ export class Graph {
this.width = 1;
this.height = 1;
data.nodes.forEach((jsonNode: any) => {
graphPhase.data.nodes.forEach((jsonNode: GNode) => {
this.nodeMap[jsonNode.id] = new GNode(jsonNode.nodeLabel);
});
data.edges.forEach((e: any) => {
const t = this.nodeMap[e.target];
const s = this.nodeMap[e.source];
graphPhase.data.edges.forEach((e: any) => {
const t = this.nodeMap[e.target.id];
const s = this.nodeMap[e.source.id];
const newEdge = new Edge(t, e.index, s, e.type);
t.inputs.push(newEdge);
s.outputs.push(newEdge);
......@@ -37,7 +38,6 @@ export class Graph {
s.cfg = true;
}
});
}
*nodes(p = (n: GNode) => true) {
......
......@@ -7,8 +7,9 @@ import { ScheduleView } from "./views/schedule-view";
import { SequenceView } from "./views/sequence-view";
import { SourceResolver } from "./source-resolver";
import { SelectionBroker } from "./selection/selection-broker";
import { View, PhaseView } from "./views/view";
import { PhaseView, View } from "./views/view";
import { GNode } from "./node";
import { GraphPhase } from "./phases/graph-phase";
const multiviewID = "multiview";
......@@ -83,7 +84,7 @@ export class GraphMultiView extends View {
view.sourceResolver.forEachPhase(phase => {
const optionElement = document.createElement("option");
let maxNodeId = "";
if (phase.type == "graph" && phase.highestNodeId != 0) {
if (phase instanceof GraphPhase && phase.highestNodeId != 0) {
maxNodeId = ` ${phase.highestNodeId}`;
}
optionElement.text = `${phase.name}${maxNodeId}`;
......
......@@ -176,6 +176,8 @@ export class GNode {
((this.nodeLabel.opcode == "Phi" || this.nodeLabel.opcode == "EffectPhi" || this.nodeLabel.opcode == "InductionVariablePhi") &&
this.inputs[this.inputs.length - 1].source.nodeLabel.opcode == "Loop");
}
public identifier = (): string => `${this.id}`;
}
export const nodeToStr = (n: GNode) => "N" + n.id;
// 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.
export abstract class Origin {
phase: string;
reducer: string;
constructor(phase: string, reducer: string) {
this.phase = phase;
this.reducer = reducer;
}
}
export class NodeOrigin extends Origin {
nodeId: number;
constructor(nodeId: number, phase: string, reducer: string) {
super(phase, reducer);
this.nodeId = nodeId;
}
public identifier = (): string => `${this.nodeId}`;
public toString = (): string => `#${this.nodeId} in phase '${this.phase}/${this.reducer}'`;
}
export class BytecodeOrigin extends Origin {
bytecodePosition: number;
constructor(bytecodePosition: number, phase: string, reducer: string) {
super(phase, reducer);
this.bytecodePosition = bytecodePosition;
}
public identifier = (): string => `${this.bytecodePosition}`;
public toString = (): string => {
return `Bytecode line ${this.bytecodePosition} in phase '${this.phase}/${this.reducer}'`;
}
}
// 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 DisassemblyPhase extends Phase {
data: string;
blockIdToOffset: Array<number>;
blockStartPCtoBlockIds: Map<number, Array<number>>;
constructor(name: string, data: string) {
super(name, PhaseType.Disassembly);
this.data = data;
this.blockIdToOffset = new Array<number>() ;
this.blockStartPCtoBlockIds = new Map<number, Array<number>>();
}
public parseBlockIdToOffsetFromJSON(blockIdToOffsetJson): void {
if (!blockIdToOffsetJson) return;
for (const [blockId, offset] of Object.entries<number>(blockIdToOffsetJson)) {
this.blockIdToOffset[blockId] = offset;
if (!this.blockStartPCtoBlockIds.has(offset)) {
this.blockStartPCtoBlockIds.set(offset, new Array<number>());
}
this.blockStartPCtoBlockIds.get(offset).push(Number(blockId));
}
}
}
// 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";
import { NodeLabel } from "../node-label";
import { GNode } from "../node";
import { Edge } from "../edge";
import { BytecodeOrigin, NodeOrigin } from "../origin";
import { SourcePosition } from "../position";
export class GraphPhase extends Phase {
data: GraphData;
highestNodeId: number;
nodeLabelMap: Array<NodeLabel>;
nodeIdToNodeMap: Array<GNode>;
constructor(name: string, highestNodeId: number, data?: GraphData,
nodeLabelMap?: Array<NodeLabel>, nodeIdToNodeMap?: Array<GNode>) {
super(name, PhaseType.Graph);
this.highestNodeId = highestNodeId;
this.data = data ?? new GraphData();
this.nodeLabelMap = nodeLabelMap ?? new Array<NodeLabel>();
this.nodeIdToNodeMap = nodeIdToNodeMap ?? new Array<GNode>();
}
public parseDataFromJSON(dataJson, nodeLabelMap: Array<NodeLabel>): void {
this.nodeIdToNodeMap = this.parseNodesFromJSON(dataJson.nodes, nodeLabelMap);
this.parseEdgesFromJSON(dataJson.edges);
}
private parseNodesFromJSON(nodesJSON, nodeLabelMap: Array<NodeLabel>): Array<GNode> {
const nodeIdToNodeMap = new Array<GNode>();
for (const node of nodesJSON) {
let origin: NodeOrigin | BytecodeOrigin = null;
const jsonOrigin = node.origin;
if (jsonOrigin) {
if (jsonOrigin.nodeId) {
origin = new NodeOrigin(jsonOrigin.nodeId, jsonOrigin.reducer, jsonOrigin.phase);
} else {
origin = new BytecodeOrigin(jsonOrigin.bytecodePosition, jsonOrigin.reducer,
jsonOrigin.phase);
}
}
let sourcePosition: SourcePosition = null;
if (node.sourcePosition) {
const scriptOffset = node.sourcePosition.scriptOffset;
const inliningId = node.sourcePosition.inliningId;
sourcePosition = new SourcePosition(scriptOffset, inliningId);
}
const label = new NodeLabel(node.id, node.label, node.title, node.live, node.properties,
sourcePosition, origin, node.opcode, node.control, node.opinfo, node.type);
const previous = nodeLabelMap[label.id];
if (!label.equals(previous)) {
if (previous !== undefined) {
label.setInplaceUpdatePhase(this.name);
}
nodeLabelMap[label.id] = label;
}
const newNode = new GNode(label);
this.data.nodes.push(newNode);
nodeIdToNodeMap[newNode.id] = newNode;
}
return nodeIdToNodeMap;
}
private parseEdgesFromJSON(edgesJSON): void {
for (const edge of edgesJSON) {
const target = this.nodeIdToNodeMap[edge.target];
const source = this.nodeIdToNodeMap[edge.source];
const newEdge = new Edge(target, edge.index, source, edge.type);
this.data.edges.push(newEdge);
target.inputs.push(newEdge);
source.outputs.push(newEdge);
if (edge.type === "control") {
source.cfg = true;
}
}
}
}
export class GraphData {
nodes: Array<GNode>;
edges: Array<Edge>;
constructor(nodes?: Array<GNode>, edges?: Array<Edge>) {
this.nodes = nodes ?? new Array<GNode>();
this.edges = edges ?? new Array<Edge>();
}
}
// 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 InstructionsPhase extends Phase {
// Maps node ids to instruction ranges.
nodeIdToInstructionRange?: Array<[number, number]>;
// Maps block ids to instruction ranges.
blockIdToInstructionRange?: Array<[number, number]>;
instructionOffsetToPCOffset?: Array<[number, number]>;
codeOffsetsInfo?: CodeOffsetsInfo;
// Maps instruction numbers to PC offsets.
instructionToPCOffset: Array<TurbolizerInstructionStartInfo>;
// Maps PC offsets to instructions.
pcOffsetToInstructions: Map<number, Array<number>>;
pcOffsets: Array<number>;
constructor(name: string, nodeIdToInstructionRange?: Array<[number, number]>,
blockIdToInstructionRange?: Array<[number, number]>,
codeOffsetsInfo?: CodeOffsetsInfo) {
super(name, PhaseType.Instructions);
this.nodeIdToInstructionRange = nodeIdToInstructionRange ?? new Array<[number, number]>();
this.blockIdToInstructionRange = blockIdToInstructionRange ?? new Array<[number, number]>();
this.codeOffsetsInfo = codeOffsetsInfo;
this.instructionToPCOffset = new Array<TurbolizerInstructionStartInfo>();
this.pcOffsetToInstructions = new Map<number, Array<number>>();
this.pcOffsets = new Array<number>();
}
public parseNodeIdToInstructionRangeFromJSON(nodeIdToInstructionJson): void {
if (!nodeIdToInstructionJson) return;
for (const [nodeId, range] of Object.entries<[number, number]>(nodeIdToInstructionJson)) {
this.nodeIdToInstructionRange[nodeId] = range;
}
}
public parseBlockIdToInstructionRangeFromJSON(blockIdToInstructionRangeJson): void {
if (!blockIdToInstructionRangeJson) return;
for (const [blockId, range] of
Object.entries<[number, number]>(blockIdToInstructionRangeJson)) {
this.blockIdToInstructionRange[blockId] = range;
}
}
public parseInstructionOffsetToPCOffsetFromJSON(instructionOffsetToPCOffsetJson): void {
if (!instructionOffsetToPCOffsetJson) return;
for (const [instruction, numberOrInfo] of Object.entries<number |
TurbolizerInstructionStartInfo>(instructionOffsetToPCOffsetJson)) {
let info: TurbolizerInstructionStartInfo = null;
if (typeof numberOrInfo === "number") {
info = new TurbolizerInstructionStartInfo(numberOrInfo, numberOrInfo, numberOrInfo);
} else {
info = new TurbolizerInstructionStartInfo(numberOrInfo.gap, numberOrInfo.arch,
numberOrInfo.condition);
}
this.instructionToPCOffset[instruction] = info;
if (!this.pcOffsetToInstructions.has(info.gap)) {
this.pcOffsetToInstructions.set(info.gap, new Array<number>());
}
this.pcOffsetToInstructions.get(info.gap).push(Number(instruction));
}
this.pcOffsets = Array.from(this.pcOffsetToInstructions.keys()).sort((a, b) => b - a);
}
public parseCodeOffsetsInfoFromJSON(codeOffsetsInfoJson: CodeOffsetsInfo): void {
if (!codeOffsetsInfoJson) return;
this.codeOffsetsInfo = new CodeOffsetsInfo(codeOffsetsInfoJson.codeStartRegisterCheck,
codeOffsetsInfoJson.deoptCheck, codeOffsetsInfoJson.initPoison,
codeOffsetsInfoJson.blocksStart, codeOffsetsInfoJson.outOfLineCode,
codeOffsetsInfoJson.deoptimizationExits, codeOffsetsInfoJson.pools,
codeOffsetsInfoJson.jumpTables);
}
}
export class CodeOffsetsInfo {
codeStartRegisterCheck: number;
deoptCheck: number;
initPoison: number;
blocksStart: number;
outOfLineCode: number;
deoptimizationExits: number;
pools: number;
jumpTables: number;
constructor(codeStartRegisterCheck: number, deoptCheck: number, initPoison: number,
blocksStart: number, outOfLineCode: number, deoptimizationExits: number,
pools: number, jumpTables: number) {
this.codeStartRegisterCheck = codeStartRegisterCheck;
this.deoptCheck = deoptCheck;
this.initPoison = initPoison;
this.blocksStart = blocksStart;
this.outOfLineCode = outOfLineCode;
this.deoptimizationExits = deoptimizationExits;
this.pools = pools;
this.jumpTables = jumpTables;
}
}
export class TurbolizerInstructionStartInfo {
gap: number;
arch: number;
condition: number;
constructor(gap: number, arch: number, condition: number) {
this.gap = gap;
this.arch = arch;
this.condition = condition;
}
}
// 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.
export abstract class Phase {
name: string;
type: PhaseType;
constructor(name, type: PhaseType) {
this.name = name;
this.type = type;
}
}
export enum PhaseType {
Graph = "graph",
TurboshaftGraph = "turboshaft_graph",
Disassembly = "disassembly",
Instructions = "instructions",
Sequence = "sequence",
Schedule = "schedule"
}
// 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 SchedulePhase extends Phase {
data: string;
schedule: { currentBlock, blocks: Array<any>, nodes: Array<any> };
constructor(name: string, data: string, schedule?: any) {
super(name, PhaseType.Schedule);
this.data = data;
this.schedule = schedule ?? {
currentBlock: undefined,
blocks: new Array<any>(),
nodes: new Array<any>()
};
}
public parseScheduleFromJSON(scheduleDataJson): void {
const lines = scheduleDataJson.split(/[\n]/);
nextLine:
for (const line of lines) {
for (const rule of this.parsingRules) {
for (const lineRegexp of rule.lineRegexps) {
const match = line.match(lineRegexp);
if (match) {
rule.process(match);
continue nextLine;
}
}
}
console.warn(`Unmatched schedule line \"${line}\"`);
}
}
private createNode = match => {
let inputs = [];
if (match.groups.args) {
const nodeIdsString = match.groups.args.replace(/\s/g, '');
const nodeIdStrings = nodeIdsString.split(',');
inputs = nodeIdStrings.map(n => Number.parseInt(n, 10));
}
const node = {
id: Number.parseInt(match.groups.id, 10),
label: match.groups.label,
inputs: inputs
};
if (match.groups.blocks) {
const nodeIdsString = match.groups.blocks.replace(/\s/g, '').replace(/B/g, '');
const nodeIdStrings = nodeIdsString.split(',');
this.schedule.currentBlock.succ = nodeIdStrings.map(n => Number.parseInt(n, 10));
}
this.schedule.nodes[node.id] = node;
this.schedule.currentBlock.nodes.push(node);
}
private createBlock = match => {
let predecessors = [];
if (match.groups.in) {
const blockIdsString = match.groups.in.replace(/\s/g, '').replace(/B/g, '');
const blockIdStrings = blockIdsString.split(',');
predecessors = blockIdStrings.map(n => Number.parseInt(n, 10));
}
const block = {
id: Number.parseInt(match.groups.id, 10),
isDeferred: match.groups.deferred != undefined,
pred: predecessors.sort(),
succ: [],
nodes: []
};
this.schedule.blocks[block.id] = block;
this.schedule.currentBlock = block;
}
private setGotoSuccessor = match => {
this.schedule.currentBlock.succ = [Number.parseInt(match.groups.successor.replace(/\s/g, ''), 10)];
}
private parsingRules = [
{
lineRegexps: [
/^\s*(?<id>\d+):\ (?<label>.*)\((?<args>.*)\)$/,
/^\s*(?<id>\d+):\ (?<label>.*)\((?<args>.*)\)\ ->\ (?<blocks>.*)$/,
/^\s*(?<id>\d+):\ (?<label>.*)$/
],
process: this.createNode
},
{
lineRegexps: [/^\s*---\s*BLOCK\ B(?<id>\d+)\s*(?<deferred>\(deferred\))?(\ <-\ )?(?<in>[^-]*)?\ ---$/],
process: this.createBlock
},
{
lineRegexps: [/^\s*Goto\s*->\s*B(?<successor>\d+)\s*$/],
process: this.setGotoSuccessor
}
];
}
// 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 SequencePhase extends Phase {
blocks: Array<any>;
registerAllocation: RegisterAllocation;
constructor(name: string, blocks: Array<any>, registerAllocation?: RegisterAllocation) {
super(name, PhaseType.Sequence);
this.blocks = blocks;
this.registerAllocation = registerAllocation;
}
}
export interface RegisterAllocation {
fixedDoubleLiveRanges: Map<string, Range>;
fixedLiveRanges: Map<string, Range>;
liveRanges: Map<string, Range>;
}
export interface Range {
childRanges: Array<ChildRange>;
isDeferred: boolean;
}
export interface ChildRange {
id: string;
type: string;
op: any;
intervals: Array<[number, number]>;
uses: Array<number>;
}
// 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 TurboshaftGraphPhase extends Phase {
constructor(name: string) {
super(name, PhaseType.TurboshaftGraph);
// To be continued ...
}
}
// 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.
export class InliningPosition {
sourceId: number;
inliningPosition: SourcePosition;
constructor(sourceId: number, inliningPosition: SourcePosition) {
this.sourceId = sourceId;
this.inliningPosition = inliningPosition;
}
}
export class SourcePosition {
scriptOffset: number;
inliningId: number;
constructor(scriptOffset: number, inliningId: number) {
this.scriptOffset = scriptOffset;
this.inliningId = inliningId;
}
public lessOrEquals(other: SourcePosition): number {
if (this.inliningId == other.inliningId) {
return this.scriptOffset - other.scriptOffset;
}
return this.inliningId - other.inliningId;
}
public equals(other: SourcePosition): boolean {
if (this.scriptOffset != other.scriptOffset) return false;
return this.inliningId == other.inliningId;
}
public isValid(): boolean {
return typeof this.scriptOffset !== undefined && typeof this.inliningId !== undefined;
}
public toString = (): string => `SP:${this.inliningId}:${this.scriptOffset}`;
}
export class BytecodePosition {
bytecodePosition: number;
constructor(bytecodePosition: number) {
this.bytecodePosition = bytecodePosition;
}
public isValid(): boolean {
return typeof this.bytecodePosition !== undefined;
}
public toString = (): string => `BCP:${this.bytecodePosition}`;
}
This diff is collapsed.
// 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 { SourcePosition } from "./position";
export class Source {
sourceName: string;
functionName: string;
sourceText: string;
sourceId: number;
backwardsCompatibility: boolean;
sourcePositions: Array<SourcePosition>;
startPosition?: number;
endPosition?: number;
constructor(sourceName: string, functionName: string, sourceText: string, sourceId: number,
backwardsCompatibility: boolean, sourcePositions?: Array<SourcePosition>,
startPosition?: number, endPosition?: number) {
this.sourceName = sourceName;
this.functionName = functionName;
this.sourceText = sourceText;
this.sourceId = sourceId;
this.backwardsCompatibility = backwardsCompatibility;
this.sourcePositions = sourcePositions ?? new Array<SourcePosition>();
this.startPosition = startPosition;
this.endPosition = endPosition;
}
public toString = (): string => `${this.sourceName}:${this.functionName}`;
}
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { Source } from "../source";
interface PR {
prettyPrint(_: unknown, el: HTMLElement): void;
}
......@@ -10,7 +12,7 @@ declare global {
const PR: PR;
}
import { Source, SourceResolver, sourcePositionToStringKey } from "../source-resolver";
import { SourceResolver, sourcePositionToStringKey } from "../source-resolver";
import { SelectionBroker } from "../selection/selection-broker";
import { View } from "./view";
import { MySelection } from "../selection/selection";
......
......@@ -264,7 +264,7 @@ export class GraphView extends PhaseView {
const adaptedSelection = this.adaptSelectionToCurrentPhase(data.data, rememberedSelection);
this.phaseName = data.name;
this.createGraph(data.data, adaptedSelection);
this.createGraph(data, adaptedSelection);
this.broker.addNodeHandler(this.selectionHandler);
if (adaptedSelection != null && adaptedSelection.size > 0) {
......
......@@ -4,7 +4,8 @@
import { createElement } from "../common/util";
import { SequenceView } from "./sequence-view";
import { RegisterAllocation, Range, ChildRange, Interval } from "../source-resolver";
import { Interval } from "../source-resolver";
import { ChildRange, Range, RegisterAllocation } from "../phases/sequence-phase";
class Constants {
// Determines how many rows each div group holds for the purposes of
......@@ -300,7 +301,7 @@ class Helper {
}
static fixedRegisterName(range: Range) {
return range.child_ranges[0].op.text;
return range.childRanges[0].op.text;
}
static getPositionElementsFromInterval(interval: HTMLElement) {
......@@ -321,7 +322,7 @@ class Helper {
const entry = fixedRegisterMap.get(registerName);
entry.ranges[1] = range;
// Only use the deferred register index if no normal index exists.
if (!range.is_deferred) {
if (!range.isDeferred) {
entry.registerIndex = parseInt(registerIndex, 10);
}
} else {
......@@ -394,7 +395,7 @@ class RowConstructor {
const intervalMap = new Map<number, HTMLElement>();
let tooltip = "";
ranges.forEachRange((range: Range) => {
for (const childRange of range.child_ranges) {
for (const childRange of range.childRanges) {
switch (childRange.type) {
case "none":
tooltip = Constants.INTERVAL_TEXT_FOR_NONE;
......@@ -417,7 +418,7 @@ class RowConstructor {
childRange.intervals.forEach((intervalNums, index) => {
const interval = new Interval(intervalNums);
const intervalEl = this.elementForInterval(childRange, interval, tooltip,
index, range.is_deferred);
index, range.isDeferred);
intervalMap.set(interval.start, intervalEl);
});
}
......@@ -490,7 +491,7 @@ class RowConstructor {
}
private setUses(grid: Grid, row: number, range: Range) {
for (const liveRange of range.child_ranges) {
for (const liveRange of range.childRanges) {
if (liveRange.uses) {
for (const use of liveRange.uses) {
grid.getCell(row, use).classList.toggle("range-use", true);
......@@ -570,7 +571,7 @@ class RangeViewConstructor {
}
private addVirtualRanges(row: number) {
const source = this.view.sequenceView.sequence.register_allocation;
const source = this.view.sequenceView.sequence.registerAllocation;
for (const [registerIndex, range] of source.liveRanges) {
const registerName = Helper.virtualRegisterName(registerIndex);
const registerEl = this.elementForVirtualRegister(registerName);
......@@ -583,7 +584,7 @@ class RangeViewConstructor {
}
private addFixedRanges(row: number) {
row = Helper.forEachFixedRange(this.view.sequenceView.sequence.register_allocation, row,
row = Helper.forEachFixedRange(this.view.sequenceView.sequence.registerAllocation, row,
(registerIndex: string, row: number,
registerName: string, ranges: RangePair) => {
const registerEl = this.elementForFixedRegister(registerName);
......@@ -765,14 +766,14 @@ class PhaseChangeHandler {
const currentGrid = this.view.gridAccessor.getAnyGrid();
const newGrid = new Grid();
this.view.gridAccessor.addGrid(newGrid);
const source = this.view.sequenceView.sequence.register_allocation;
const source = this.view.sequenceView.sequence.registerAllocation;
let row = 0;
for (const [registerIndex, range] of source.liveRanges) {
this.addnewIntervalsInRange(currentGrid, newGrid, row, registerIndex,
new RangePair([range, undefined]));
++row;
}
Helper.forEachFixedRange(this.view.sequenceView.sequence.register_allocation, row,
Helper.forEachFixedRange(this.view.sequenceView.sequence.registerAllocation, row,
(registerIndex, row, _, ranges) => {
this.addnewIntervalsInRange(currentGrid, newGrid, row, registerIndex, ranges);
});
......
......@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { Schedule, SourceResolver } from "../source-resolver";
import { SourceResolver } from "../source-resolver";
import { TextView } from "./text-view";
import { SchedulePhase } from "../phases/schedule-phase";
export class ScheduleView extends TextView {
schedule: Schedule;
schedule: SchedulePhase;
sourceResolver: SourceResolver;
createViewElement() {
......@@ -178,7 +179,7 @@ export class ScheduleView extends TextView {
const select = [];
window.sessionStorage.setItem("lastSearch", query);
const reg = new RegExp(query);
for (const node of this.schedule.nodes) {
for (const node of this.schedule.schedule.nodes) {
if (node === undefined) continue;
if (reg.exec(this.lineString(node)) != null) {
select.push(node.id);
......
......@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { Sequence } from "../source-resolver";
import { createElement } from "../common/util";
import { TextView } from "./text-view";
import { RangeView } from "./range-view";
import { SequencePhase } from "../phases/sequence-phase";
export class SequenceView extends TextView {
sequence: Sequence;
sequence: SequencePhase;
searchInfo: Array<any>;
phaseSelect: HTMLSelectElement;
numInstructions: number;
......@@ -80,9 +80,9 @@ export class SequenceView extends TextView {
if (this.showRangeView) this.rangeView.onresize();
}
initializeContent(data, rememberedSelection) {
initializeContent(sequence, rememberedSelection) {
this.divNode.innerHTML = '';
this.sequence = data.sequence;
this.sequence = sequence;
this.searchInfo = [];
this.divNode.onclick = (e: MouseEvent) => {
if (!(e.target instanceof HTMLElement)) return;
......@@ -93,7 +93,6 @@ export class SequenceView extends TextView {
};
this.phaseSelect = (document.getElementById('phase-select') as HTMLSelectElement);
this.currentPhaseIndex = this.phaseSelect.selectedIndex;
this.addBlocks(this.sequence.blocks);
const lastBlock = this.sequence.blocks[this.sequence.blocks.length - 1];
this.numInstructions = lastBlock.instructions[lastBlock.instructions.length - 1].id + 1;
......@@ -313,11 +312,11 @@ export class SequenceView extends TextView {
this.toggleRangeViewEl.setAttribute("title", reason);
};
if (this.sequence.register_allocation) {
if (this.sequence.registerAllocation) {
if (!this.rangeView) {
this.rangeView = new RangeView(this);
}
const source = this.sequence.register_allocation;
const source = this.sequence.registerAllocation;
if (source.fixedLiveRanges.size == 0 && source.liveRanges.size == 0) {
preventRangeView("No live ranges to show");
} else if (this.numInstructions >= 249) {
......
......@@ -17,6 +17,13 @@
"src/common/util.ts",
"src/common/constants.ts",
"src/common/view-elements.ts",
"src/phases/disassembly-phase.ts",
"src/phases/graph-phase.ts",
"src/phases/instructions-phase.ts",
"src/phases/phase.ts",
"src/phases/schedule-phase.ts",
"src/phases/sequence-phase.ts",
"src/phases/turboshaft-graph-phase.ts",
"src/selection/selection.ts",
"src/selection/selection-broker.ts",
"src/selection/selection-handler.ts",
......@@ -27,6 +34,9 @@
"src/views/disassembly-view.ts",
"src/views/text-view.ts",
"src/views/info-view.ts",
"src/origin.ts",
"src/position.ts",
"src/source.ts",
"src/node.ts",
"src/edge.ts",
"src/graph.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