[turbolizer] Move methods from source resolver to corresponding phases
- source resolver clean up - started inregration of turboshaft schedule phase Bug: v8:7327 Change-Id: I4335c275f4cfb2e313ac383a5b9fa12c7b9aa744 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3700078 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Danylo Boiko <danielboyko02@gmail.com> Cr-Commit-Position: refs/heads/main@{#81164}
This commit is contained in:
parent
00fe5f5e65
commit
9f7c28b805
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export function anyToString(x: any): string {
|
||||
return `${x}`;
|
||||
export function anyToString(obj: any): string {
|
||||
return `${obj}`;
|
||||
}
|
||||
|
||||
export function snakeToCamel(str: string): string {
|
||||
@ -18,7 +18,7 @@ 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) => ({
|
||||
return Object.keys(obj).reduce((result, key: string) => ({
|
||||
...result,
|
||||
[snakeToCamel(key)]: camelize(obj[key])
|
||||
}), {},
|
||||
|
13
tools/turbolizer/src/interval.ts
Normal file
13
tools/turbolizer/src/interval.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// 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 Interval {
|
||||
start: number;
|
||||
end: number;
|
||||
|
||||
constructor(numbers: [number, number]) {
|
||||
this.start = numbers[0];
|
||||
this.end = numbers[1];
|
||||
}
|
||||
}
|
@ -17,6 +17,14 @@ export class DisassemblyPhase extends Phase {
|
||||
this.blockStartPCtoBlockIds = new Map<number, Array<number>>();
|
||||
}
|
||||
|
||||
public hasBlockStartInfo(): boolean {
|
||||
return this.blockIdToOffset.length > 0;
|
||||
}
|
||||
|
||||
public getBlockIdsForOffset(offset: number): Array<number> {
|
||||
return this.blockStartPCtoBlockIds.get(offset);
|
||||
}
|
||||
|
||||
public parseBlockIdToOffsetFromJSON(blockIdToOffsetJson): void {
|
||||
if (!blockIdToOffsetJson) return;
|
||||
for (const [blockId, offset] of Object.entries<number>(blockIdToOffsetJson)) {
|
||||
|
@ -10,8 +10,8 @@ import { BytecodeOrigin, NodeOrigin } from "../origin";
|
||||
import { SourcePosition } from "../position";
|
||||
|
||||
export class GraphPhase extends Phase {
|
||||
data: GraphData;
|
||||
highestNodeId: number;
|
||||
data: GraphData;
|
||||
nodeLabelMap: Array<NodeLabel>;
|
||||
nodeIdToNodeMap: Array<GNode>;
|
||||
|
||||
|
@ -3,12 +3,14 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { Phase, PhaseType } from "./phase";
|
||||
import { anyToString } from "../common/util";
|
||||
|
||||
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]>;
|
||||
// Maps instruction offsets to PC offset.
|
||||
instructionOffsetToPCOffset?: Array<[number, number]>;
|
||||
codeOffsetsInfo?: CodeOffsetsInfo;
|
||||
|
||||
@ -31,6 +33,130 @@ export class InstructionsPhase extends Phase {
|
||||
this.pcOffsets = new Array<number>();
|
||||
}
|
||||
|
||||
public getKeyPcOffset(offset: number): number {
|
||||
if (this.pcOffsets.length === 0) return -1;
|
||||
for (const key of this.pcOffsets) {
|
||||
if (key <= offset) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public instructionToPcOffsets(instruction: number): TurbolizerInstructionStartInfo {
|
||||
return this.instructionToPCOffset[instruction];
|
||||
}
|
||||
|
||||
public instructionsToKeyPcOffsets(instructionIds: Iterable<number>): Array<number> {
|
||||
const keyPcOffsets = new Array<number>();
|
||||
for (const instructionId of instructionIds) {
|
||||
const pcOffset = this.instructionToPCOffset[instructionId];
|
||||
if (pcOffset !== undefined) keyPcOffsets.push(pcOffset.gap);
|
||||
}
|
||||
return keyPcOffsets;
|
||||
}
|
||||
|
||||
public nodesForPCOffset(offset: number): Array<string> {
|
||||
if (this.pcOffsets.length === 0) return new Array<string>();
|
||||
for (const key of this.pcOffsets) {
|
||||
if (key <= offset) {
|
||||
const instructions = this.pcOffsetToInstructions.get(key);
|
||||
const nodes = new Array<string>();
|
||||
for (const instruction of instructions) {
|
||||
for (const [nodeId, range] of this.nodeIdToInstructionRange.entries()) {
|
||||
if (!range) continue;
|
||||
const [start, end] = range;
|
||||
if (start == end && instruction == start) {
|
||||
nodes.push(anyToString(nodeId));
|
||||
}
|
||||
if (start <= instruction && instruction < end) {
|
||||
nodes.push(anyToString(nodeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
return new Array<string>();
|
||||
}
|
||||
|
||||
public nodesToKeyPcOffsets(nodeIds: Set<string>): Array<TurbolizerInstructionStartInfo> {
|
||||
let offsets = new Array<TurbolizerInstructionStartInfo>();
|
||||
for (const nodeId of nodeIds) {
|
||||
const range = this.nodeIdToInstructionRange[nodeId];
|
||||
if (!range) continue;
|
||||
offsets = offsets.concat(this.instructionRangeToKeyPcOffsets(range));
|
||||
}
|
||||
return offsets;
|
||||
}
|
||||
|
||||
public getInstruction(nodeId: number): [number, number] {
|
||||
return this.nodeIdToInstructionRange[nodeId] ?? [-1, -1];
|
||||
}
|
||||
|
||||
public getInstructionRangeForBlock(blockId: number): [number, number] {
|
||||
return this.blockIdToInstructionRange[blockId] ?? [-1, -1];
|
||||
}
|
||||
|
||||
public getInstructionKindForPCOffset(offset: number): InstructionKind {
|
||||
if (this.codeOffsetsInfo) {
|
||||
if (offset >= this.codeOffsetsInfo.deoptimizationExits) {
|
||||
if (offset >= this.codeOffsetsInfo.pools) {
|
||||
return InstructionKind.Pools;
|
||||
} else if (offset >= this.codeOffsetsInfo.jumpTables) {
|
||||
return InstructionKind.JumpTables;
|
||||
} else {
|
||||
return InstructionKind.DeoptimizationExits;
|
||||
}
|
||||
}
|
||||
if (offset < this.codeOffsetsInfo.deoptCheck) {
|
||||
return InstructionKind.CodeStartRegister;
|
||||
} else if (offset < this.codeOffsetsInfo.initPoison) {
|
||||
return InstructionKind.DeoptCheck;
|
||||
} else if (offset < this.codeOffsetsInfo.blocksStart) {
|
||||
return InstructionKind.InitPoison;
|
||||
}
|
||||
}
|
||||
const keyOffset = this.getKeyPcOffset(offset);
|
||||
if (keyOffset != -1) {
|
||||
const infos = this.pcOffsetToInstructions.get(keyOffset)
|
||||
.map(instrId => this.instructionToPCOffset[instrId])
|
||||
.filter(info => info.gap !== info.condition);
|
||||
if (infos.length > 0) {
|
||||
const info = infos[0];
|
||||
if (!info || info.gap == info.condition) return InstructionKind.Unknown;
|
||||
if (offset < info.arch) return InstructionKind.Gap;
|
||||
if (offset < info.condition) return InstructionKind.Arch;
|
||||
return InstructionKind.Condition;
|
||||
}
|
||||
}
|
||||
return InstructionKind.Unknown;
|
||||
}
|
||||
|
||||
public instructionKindToReadableName(instructionKind: InstructionKind): string {
|
||||
switch (instructionKind) {
|
||||
case InstructionKind.CodeStartRegister:
|
||||
return "Check code register for right value";
|
||||
case InstructionKind.DeoptCheck:
|
||||
return "Check if function was marked for deoptimization";
|
||||
case InstructionKind.InitPoison:
|
||||
return "Initialization of poison register";
|
||||
case InstructionKind.Gap:
|
||||
return "Instruction implementing a gap move";
|
||||
case InstructionKind.Arch:
|
||||
return "Instruction implementing the actual machine operation";
|
||||
case InstructionKind.Condition:
|
||||
return "Code implementing conditional after instruction";
|
||||
case InstructionKind.Pools:
|
||||
return "Data in a pool (e.g. constant pool)";
|
||||
case InstructionKind.JumpTables:
|
||||
return "Part of a jump table";
|
||||
case InstructionKind.DeoptimizationExits:
|
||||
return "Jump to deoptimization exit";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public parseNodeIdToInstructionRangeFromJSON(nodeIdToInstructionJson): void {
|
||||
if (!nodeIdToInstructionJson) return;
|
||||
for (const [nodeId, range] of Object.entries<[number, number]>(nodeIdToInstructionJson)) {
|
||||
@ -74,6 +200,12 @@ export class InstructionsPhase extends Phase {
|
||||
codeOffsetsInfoJson.deoptimizationExits, codeOffsetsInfoJson.pools,
|
||||
codeOffsetsInfoJson.jumpTables);
|
||||
}
|
||||
|
||||
private instructionRangeToKeyPcOffsets([start, end]: [number, number]):
|
||||
Array<TurbolizerInstructionStartInfo> {
|
||||
if (start == end) return [this.instructionToPCOffset[start]];
|
||||
return this.instructionToPCOffset.slice(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeOffsetsInfo {
|
||||
@ -111,3 +243,16 @@ export class TurbolizerInstructionStartInfo {
|
||||
this.condition = condition;
|
||||
}
|
||||
}
|
||||
|
||||
export enum InstructionKind {
|
||||
Pools = "pools",
|
||||
JumpTables = "jump-tables",
|
||||
DeoptimizationExits = "deoptimization-exits",
|
||||
CodeStartRegister = "code-start-register",
|
||||
DeoptCheck = "deopt-check",
|
||||
InitPoison = "init-poison",
|
||||
Gap = "gap",
|
||||
Arch = "arch",
|
||||
Condition = "condition",
|
||||
Unknown = "unknown"
|
||||
}
|
||||
|
@ -56,9 +56,10 @@ export class SelectionBroker {
|
||||
}
|
||||
|
||||
// Select the lines from the source panel (left panel)
|
||||
const pcOffsets = this.sourceResolver.instructionsToKeyPcOffsets(instructionOffsets);
|
||||
const pcOffsets = this.sourceResolver.instructionsPhase
|
||||
.instructionsToKeyPcOffsets(instructionOffsets);
|
||||
for (const offset of pcOffsets) {
|
||||
const nodes = this.sourceResolver.nodesForPCOffset(offset)[0];
|
||||
const nodes = this.sourceResolver.instructionsPhase.nodesForPCOffset(offset);
|
||||
const sourcePositions = this.sourceResolver.nodeIdsToSourcePositions(nodes);
|
||||
for (const b of this.sourcePositionHandlers) {
|
||||
if (b != from) b.brokeredSourcePositionSelect(sourcePositions, selected);
|
||||
@ -89,7 +90,8 @@ export class SelectionBroker {
|
||||
}
|
||||
|
||||
for (const node of nodes) {
|
||||
const instructionOffsets = this.sourceResolver.nodeIdToInstructionRange[node];
|
||||
const instructionOffsets = this.sourceResolver.instructionsPhase
|
||||
.nodeIdToInstructionRange[node];
|
||||
// Skip nodes which do not have an associated instruction range.
|
||||
if (instructionOffsets == undefined) continue;
|
||||
|
||||
@ -118,7 +120,8 @@ export class SelectionBroker {
|
||||
}
|
||||
|
||||
for (const node of nodes) {
|
||||
const instructionOffsets = this.sourceResolver.nodeIdToInstructionRange[node];
|
||||
const instructionOffsets = this.sourceResolver.instructionsPhase
|
||||
.nodeIdToInstructionRange[node];
|
||||
// Skip nodes which do not have an associated instruction range.
|
||||
if (instructionOffsets == undefined) continue;
|
||||
// Select the lines from the disassembly (right panel)
|
||||
|
@ -7,13 +7,13 @@ import { PhaseType } from "./phases/phase";
|
||||
import { GraphPhase } from "./phases/graph-phase";
|
||||
import { DisassemblyPhase } from "./phases/disassembly-phase";
|
||||
import { BytecodePosition, InliningPosition, SourcePosition } from "./position";
|
||||
import { CodeOffsetsInfo, InstructionsPhase,
|
||||
TurbolizerInstructionStartInfo } from "./phases/instructions-phase";
|
||||
import { InstructionsPhase } from "./phases/instructions-phase";
|
||||
import { SchedulePhase } from "./phases/schedule-phase";
|
||||
import { SequencePhase } from "./phases/sequence-phase";
|
||||
import { BytecodeOrigin } from "./origin";
|
||||
import { Source } from "./source";
|
||||
import { NodeLabel } from "./node-label";
|
||||
import { TurboshaftGraphPhase } from "./phases/turboshaft-graph-phase";
|
||||
|
||||
function sourcePositionLe(a, b) {
|
||||
if (a.inliningId == b.inliningId) {
|
||||
@ -44,18 +44,8 @@ export function sourcePositionValid(l) {
|
||||
}
|
||||
|
||||
type GenericPosition = SourcePosition | BytecodePosition;
|
||||
type GenericPhase = GraphPhase | DisassemblyPhase | InstructionsPhase
|
||||
| SchedulePhase | SequencePhase;
|
||||
|
||||
export class Interval {
|
||||
start: number;
|
||||
end: number;
|
||||
|
||||
constructor(numbers: [number, number]) {
|
||||
this.start = numbers[0];
|
||||
this.end = numbers[1];
|
||||
}
|
||||
}
|
||||
type GenericPhase = GraphPhase | TurboshaftGraphPhase | DisassemblyPhase
|
||||
| InstructionsPhase | SchedulePhase | SequencePhase;
|
||||
|
||||
export class SourceResolver {
|
||||
nodePositionMap: Array<GenericPosition>;
|
||||
@ -68,14 +58,6 @@ export class SourceResolver {
|
||||
disassemblyPhase: DisassemblyPhase;
|
||||
instructionsPhase: InstructionsPhase;
|
||||
linePositionMap: Map<string, Array<GenericPosition>>;
|
||||
nodeIdToInstructionRange: Array<[number, number]>;
|
||||
blockIdToInstructionRange: Array<[number, number]>;
|
||||
instructionToPCOffset: Array<TurbolizerInstructionStartInfo>;
|
||||
pcOffsetToInstructions: Map<number, Array<number>>;
|
||||
pcOffsets: Array<number>;
|
||||
blockIdToPCOffset: Array<number>;
|
||||
blockStartPCtoBlockIds: Map<number, Array<number>>;
|
||||
codeOffsetsInfo: CodeOffsetsInfo;
|
||||
|
||||
constructor() {
|
||||
// Maps node ids to source positions.
|
||||
@ -96,26 +78,6 @@ export class SourceResolver {
|
||||
this.disassemblyPhase = undefined;
|
||||
// Maps line numbers to source positions
|
||||
this.linePositionMap = new Map();
|
||||
// Maps node ids to instruction ranges.
|
||||
this.nodeIdToInstructionRange = [];
|
||||
// Maps block ids to instruction ranges.
|
||||
this.blockIdToInstructionRange = [];
|
||||
// Maps instruction numbers to PC offsets.
|
||||
this.instructionToPCOffset = [];
|
||||
// Maps PC offsets to instructions.
|
||||
this.pcOffsetToInstructions = new Map();
|
||||
this.pcOffsets = [];
|
||||
this.blockIdToPCOffset = [];
|
||||
this.blockStartPCtoBlockIds = new Map();
|
||||
this.codeOffsetsInfo = null;
|
||||
}
|
||||
|
||||
getBlockIdsForOffset(offset): Array<number> {
|
||||
return this.blockStartPCtoBlockIds.get(offset);
|
||||
}
|
||||
|
||||
hasBlockStartInfo() {
|
||||
return this.blockIdToPCOffset.length > 0;
|
||||
}
|
||||
|
||||
setSources(sources, mainBackup) {
|
||||
@ -310,133 +272,6 @@ export class SourceResolver {
|
||||
}
|
||||
}
|
||||
|
||||
getInstruction(nodeId: number): [number, number] {
|
||||
const X = this.nodeIdToInstructionRange[nodeId];
|
||||
if (X === undefined) return [-1, -1];
|
||||
return X;
|
||||
}
|
||||
|
||||
getInstructionRangeForBlock(blockId: number): [number, number] {
|
||||
const X = this.blockIdToInstructionRange[blockId];
|
||||
if (X === undefined) return [-1, -1];
|
||||
return X;
|
||||
}
|
||||
|
||||
hasPCOffsets() {
|
||||
return this.pcOffsetToInstructions.size > 0;
|
||||
}
|
||||
|
||||
getKeyPcOffset(offset: number): number {
|
||||
if (this.pcOffsets.length === 0) return -1;
|
||||
for (const key of this.pcOffsets) {
|
||||
if (key <= offset) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
getInstructionKindForPCOffset(offset: number) {
|
||||
if (this.codeOffsetsInfo) {
|
||||
if (offset >= this.codeOffsetsInfo.deoptimizationExits) {
|
||||
if (offset >= this.codeOffsetsInfo.pools) {
|
||||
return "pools";
|
||||
} else if (offset >= this.codeOffsetsInfo.jumpTables) {
|
||||
return "jump-tables";
|
||||
} else {
|
||||
return "deoptimization-exits";
|
||||
}
|
||||
}
|
||||
if (offset < this.codeOffsetsInfo.deoptCheck) {
|
||||
return "code-start-register";
|
||||
} else if (offset < this.codeOffsetsInfo.initPoison) {
|
||||
return "deopt-check";
|
||||
} else if (offset < this.codeOffsetsInfo.blocksStart) {
|
||||
return "init-poison";
|
||||
}
|
||||
}
|
||||
const keyOffset = this.getKeyPcOffset(offset);
|
||||
if (keyOffset != -1) {
|
||||
const infos = this.pcOffsetToInstructions.get(keyOffset).map(instrId => this.instructionToPCOffset[instrId]).filter(info => info.gap != info.condition);
|
||||
if (infos.length > 0) {
|
||||
const info = infos[0];
|
||||
if (!info || info.gap == info.condition) return "unknown";
|
||||
if (offset < info.arch) return "gap";
|
||||
if (offset < info.condition) return "arch";
|
||||
return "condition";
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
instructionKindToReadableName(instructionKind) {
|
||||
switch (instructionKind) {
|
||||
case "code-start-register": return "Check code register for right value";
|
||||
case "deopt-check": return "Check if function was marked for deoptimization";
|
||||
case "init-poison": return "Initialization of poison register";
|
||||
case "gap": return "Instruction implementing a gap move";
|
||||
case "arch": return "Instruction implementing the actual machine operation";
|
||||
case "condition": return "Code implementing conditional after instruction";
|
||||
case "pools": return "Data in a pool (e.g. constant pool)";
|
||||
case "jump-tables": return "Part of a jump table";
|
||||
case "deoptimization-exits": return "Jump to deoptimization exit";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
instructionRangeToKeyPcOffsets([start, end]: [number, number]): Array<TurbolizerInstructionStartInfo> {
|
||||
if (start == end) return [this.instructionToPCOffset[start]];
|
||||
return this.instructionToPCOffset.slice(start, end);
|
||||
}
|
||||
|
||||
instructionToPcOffsets(instr: number): TurbolizerInstructionStartInfo {
|
||||
return this.instructionToPCOffset[instr];
|
||||
}
|
||||
|
||||
instructionsToKeyPcOffsets(instructionIds: Iterable<number>): Array<number> {
|
||||
const keyPcOffsets = [];
|
||||
for (const instructionId of instructionIds) {
|
||||
const pcOffset = this.instructionToPCOffset[instructionId];
|
||||
if (pcOffset !== undefined) keyPcOffsets.push(pcOffset.gap);
|
||||
}
|
||||
return keyPcOffsets;
|
||||
}
|
||||
|
||||
nodesToKeyPcOffsets(nodes) {
|
||||
let offsets = [];
|
||||
for (const node of nodes) {
|
||||
const range = this.nodeIdToInstructionRange[node];
|
||||
if (!range) continue;
|
||||
offsets = offsets.concat(this.instructionRangeToKeyPcOffsets(range));
|
||||
}
|
||||
return offsets;
|
||||
}
|
||||
|
||||
nodesForPCOffset(offset: number): [Array<string>, Array<string>] {
|
||||
if (this.pcOffsets.length === 0) return [[], []];
|
||||
for (const key of this.pcOffsets) {
|
||||
if (key <= offset) {
|
||||
const instrs = this.pcOffsetToInstructions.get(key);
|
||||
const nodes = [];
|
||||
const blocks = [];
|
||||
for (const instr of instrs) {
|
||||
for (const [nodeId, range] of this.nodeIdToInstructionRange.entries()) {
|
||||
if (!range) continue;
|
||||
const [start, end] = range;
|
||||
if (start == end && instr == start) {
|
||||
nodes.push("" + nodeId);
|
||||
}
|
||||
if (start <= instr && instr < end) {
|
||||
nodes.push("" + nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [nodes, blocks];
|
||||
}
|
||||
}
|
||||
return [[], []];
|
||||
}
|
||||
|
||||
public parsePhases(phasesJson): void {
|
||||
const nodeLabelMap = new Array<NodeLabel>();
|
||||
for (const [, genericPhase] of Object.entries<GenericPhase>(phasesJson)) {
|
||||
@ -447,10 +282,6 @@ export class SourceResolver {
|
||||
castedDisassembly.data);
|
||||
disassemblyPhase.parseBlockIdToOffsetFromJSON(castedDisassembly?.blockIdToOffset);
|
||||
this.disassemblyPhase = disassemblyPhase;
|
||||
|
||||
// Will be taken from the class
|
||||
this.blockIdToPCOffset = disassemblyPhase.blockIdToOffset;
|
||||
this.blockStartPCtoBlockIds = disassemblyPhase.blockStartPCtoBlockIds;
|
||||
break;
|
||||
case PhaseType.Schedule:
|
||||
const castedSchedule = genericPhase as SchedulePhase;
|
||||
@ -484,14 +315,6 @@ export class SourceResolver {
|
||||
instructionsPhase.parseCodeOffsetsInfoFromJSON(castedInstructions
|
||||
?.codeOffsetsInfo);
|
||||
this.instructionsPhase = instructionsPhase;
|
||||
|
||||
// Will be taken from the class
|
||||
this.nodeIdToInstructionRange = instructionsPhase.nodeIdToInstructionRange;
|
||||
this.blockIdToInstructionRange = instructionsPhase.blockIdToInstructionRange;
|
||||
this.codeOffsetsInfo = instructionsPhase.codeOffsetsInfo;
|
||||
this.instructionToPCOffset = instructionsPhase.instructionToPCOffset;
|
||||
this.pcOffsetToInstructions = instructionsPhase.pcOffsetToInstructions;
|
||||
this.pcOffsets = instructionsPhase.pcOffsets;
|
||||
break;
|
||||
case PhaseType.Graph:
|
||||
const castedGraph = genericPhase as GraphPhase;
|
||||
@ -502,6 +325,9 @@ export class SourceResolver {
|
||||
this.phaseNames.set(graphPhase.name, this.phases.length);
|
||||
this.phases.push(graphPhase);
|
||||
break;
|
||||
case PhaseType.TurboshaftGraph:
|
||||
// Allow to avoid exception and view turboshaft schedule phase
|
||||
break;
|
||||
default:
|
||||
throw "Unsupported phase type";
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { TextView } from "./text-view";
|
||||
import { MySelection } from "../selection/selection";
|
||||
import { anyToString, interpolate } from "../common/util";
|
||||
import { InstructionSelectionHandler } from "../selection/selection-handler";
|
||||
import { TurbolizerInstructionStartInfo } from "../phases/instructions-phase";
|
||||
|
||||
const toolboxHTML = `<div id="disassembly-toolbox">
|
||||
<form>
|
||||
@ -48,10 +49,12 @@ export class DisassemblyView extends TextView {
|
||||
associateData: (text, fragment: HTMLElement) => {
|
||||
const matches = text.match(/(?<address>0?x?[0-9a-fA-F]{8,16})(?<addressSpace>\s+)(?<offset>[0-9a-f]+)(?<offsetSpace>\s*)/);
|
||||
const offset = Number.parseInt(matches.groups["offset"], 16);
|
||||
const instructionKind = view.sourceResolver.getInstructionKindForPCOffset(offset);
|
||||
const instructionKind = view.sourceResolver.instructionsPhase
|
||||
.getInstructionKindForPCOffset(offset);
|
||||
fragment.dataset.instructionKind = instructionKind;
|
||||
fragment.title = view.sourceResolver.instructionKindToReadableName(instructionKind);
|
||||
const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
|
||||
fragment.title = view.sourceResolver.instructionsPhase
|
||||
.instructionKindToReadableName(instructionKind);
|
||||
const blockIds = view.sourceResolver.disassemblyPhase.getBlockIdsForOffset(offset);
|
||||
const blockIdElement = document.createElement("SPAN");
|
||||
blockIdElement.className = "block-id com linkable-text";
|
||||
blockIdElement.innerText = "";
|
||||
@ -73,7 +76,7 @@ export class DisassemblyView extends TextView {
|
||||
fragment.classList.add('tag');
|
||||
|
||||
if (!Number.isNaN(offset)) {
|
||||
let pcOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
let pcOffset = view.sourceResolver.instructionsPhase.getKeyPcOffset(offset);
|
||||
if (pcOffset == -1) pcOffset = Number(offset);
|
||||
fragment.dataset.pcOffset = `${pcOffset}`;
|
||||
addressElement.classList.add('linkable-text');
|
||||
@ -96,9 +99,9 @@ export class DisassemblyView extends TextView {
|
||||
fragment.innerHTML = text;
|
||||
const replacer = (match, hexOffset) => {
|
||||
const offset = Number.parseInt(hexOffset, 16);
|
||||
let keyOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
let keyOffset = view.sourceResolver.instructionsPhase.getKeyPcOffset(offset);
|
||||
if (keyOffset == -1) keyOffset = Number(offset);
|
||||
const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
|
||||
const blockIds = view.sourceResolver.disassemblyPhase.getBlockIdsForOffset(offset);
|
||||
let block = "";
|
||||
let blockIdData = "";
|
||||
if (blockIds && blockIds.length > 0) {
|
||||
@ -117,7 +120,7 @@ export class DisassemblyView extends TextView {
|
||||
};
|
||||
const BLOCK_HEADER_STYLE = {
|
||||
associateData: function (text, fragment) {
|
||||
if (view.sourceResolver.hasBlockStartInfo()) return false;
|
||||
if (view.sourceResolver.disassemblyPhase.hasBlockStartInfo()) return false;
|
||||
const matches = /\d+/.exec(text);
|
||||
if (!matches) return true;
|
||||
const blockId = matches[0];
|
||||
@ -167,7 +170,7 @@ export class DisassemblyView extends TextView {
|
||||
const offset = Number.parseInt(offsetAsString, 10);
|
||||
if ((typeof offsetAsString) != "undefined" && !Number.isNaN(offset)) {
|
||||
view.offsetSelection.select([offset], true);
|
||||
const nodes = view.sourceResolver.nodesForPCOffset(offset)[0];
|
||||
const nodes = view.sourceResolver.instructionsPhase.nodesForPCOffset(offset);
|
||||
if (nodes.length > 0) {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
@ -208,7 +211,8 @@ export class DisassemblyView extends TextView {
|
||||
},
|
||||
brokeredInstructionSelect: function (instructionIds, selected) {
|
||||
const firstSelect = view.offsetSelection.isEmpty();
|
||||
const keyPcOffsets = view.sourceResolver.instructionsToKeyPcOffsets(instructionIds);
|
||||
const keyPcOffsets = view.sourceResolver.instructionsPhase
|
||||
.instructionsToKeyPcOffsets(instructionIds);
|
||||
view.offsetSelection.select(keyPcOffsets, selected);
|
||||
view.updateSelection(firstSelect);
|
||||
},
|
||||
@ -262,7 +266,10 @@ export class DisassemblyView extends TextView {
|
||||
|
||||
updateSelection(scrollIntoView: boolean = false) {
|
||||
super.updateSelection(scrollIntoView);
|
||||
const keyPcOffsets = this.sourceResolver.nodesToKeyPcOffsets(this.selection.selectedKeys());
|
||||
const selectedKeys = this.selection.selectedKeys();
|
||||
const keyPcOffsets: Array<TurbolizerInstructionStartInfo | number> = [
|
||||
...this.sourceResolver.instructionsPhase.nodesToKeyPcOffsets(selectedKeys)
|
||||
];
|
||||
if (this.offsetSelection) {
|
||||
for (const key of this.offsetSelection.selectedKeys()) {
|
||||
keyPcOffsets.push(Number(key));
|
||||
|
@ -1,7 +1,10 @@
|
||||
// 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 { View } from "./view";
|
||||
|
||||
export class InfoView extends View {
|
||||
|
||||
constructor(idOrContainer: HTMLElement | string) {
|
||||
super(idOrContainer);
|
||||
fetch("info-view.html")
|
||||
@ -9,7 +12,7 @@ export class InfoView extends View {
|
||||
.then(htmlText => this.divNode.innerHTML = htmlText);
|
||||
}
|
||||
|
||||
createViewElement(): HTMLElement {
|
||||
public createViewElement(): HTMLElement {
|
||||
const infoContainer = document.createElement("div");
|
||||
infoContainer.classList.add("info-container");
|
||||
return infoContainer;
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
import { createElement } from "../common/util";
|
||||
import { SequenceView } from "./sequence-view";
|
||||
import { Interval } from "../source-resolver";
|
||||
import { ChildRange, Range, RegisterAllocation } from "../phases/sequence-phase";
|
||||
import { Interval } from "../interval";
|
||||
|
||||
class Constants {
|
||||
// Determines how many rows each div group holds for the purposes of
|
||||
|
@ -88,7 +88,7 @@ export class ScheduleView extends TextView {
|
||||
function createElementForNode(node) {
|
||||
const nodeEl = createElement("div", "node");
|
||||
|
||||
const [start, end] = view.sourceResolver.getInstruction(node.id);
|
||||
const [start, end] = view.sourceResolver.instructionsPhase.getInstruction(node.id);
|
||||
const [marker, tooltip] = getMarker(start, end);
|
||||
const instrMarker = createElement("div", "instr-marker com", marker);
|
||||
instrMarker.setAttribute("title", tooltip);
|
||||
@ -128,7 +128,8 @@ export class ScheduleView extends TextView {
|
||||
const scheduleBlock = createElement("div", "schedule-block");
|
||||
scheduleBlock.classList.toggle("deferred", block.isDeferred);
|
||||
|
||||
const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
|
||||
const [start, end] = view.sourceResolver.instructionsPhase
|
||||
.getInstructionRangeForBlock(block.id);
|
||||
const instrMarker = createElement("div", "instr-marker com", "⊙");
|
||||
instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
|
||||
instrMarker.onclick = mkBlockLinkHandler(block.id);
|
||||
|
@ -159,7 +159,7 @@ export class SequenceView extends TextView {
|
||||
const instNodeEl = createElement("div", "instruction-node");
|
||||
|
||||
const instId = createElement("div", "instruction-id", instruction.id);
|
||||
const offsets = view.sourceResolver.instructionToPcOffsets(instruction.id);
|
||||
const offsets = view.sourceResolver.instructionsPhase.instructionToPcOffsets(instruction.id);
|
||||
instId.classList.add("clickable");
|
||||
view.addHtmlElementForInstructionId(instruction.id, instId);
|
||||
instId.onclick = mkInstructionLinkHandler(instruction.id);
|
||||
|
@ -44,6 +44,7 @@
|
||||
"src/source-resolver.ts",
|
||||
"src/graph-layout.ts",
|
||||
"src/graphmultiview.ts",
|
||||
"src/interval.ts",
|
||||
"src/turbo-visualizer.ts",
|
||||
"src/resizer.ts"
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user