summaryrefslogtreecommitdiff
path: root/chromium/v8/tools/turbolizer/src/sequence-view.ts
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/tools/turbolizer/src/sequence-view.ts')
-rw-r--r--chromium/v8/tools/turbolizer/src/sequence-view.ts177
1 files changed, 145 insertions, 32 deletions
diff --git a/chromium/v8/tools/turbolizer/src/sequence-view.ts b/chromium/v8/tools/turbolizer/src/sequence-view.ts
index 49b7e9f7b2a..187b162b1cd 100644
--- a/chromium/v8/tools/turbolizer/src/sequence-view.ts
+++ b/chromium/v8/tools/turbolizer/src/sequence-view.ts
@@ -3,12 +3,21 @@
// found in the LICENSE file.
import { Sequence } from "../src/source-resolver";
-import { isIterable } from "../src/util";
+import { createElement } from "../src/util";
import { TextView } from "../src/text-view";
+import { RangeView } from "../src/range-view";
export class SequenceView extends TextView {
sequence: Sequence;
searchInfo: Array<any>;
+ phaseSelect: HTMLSelectElement;
+ numInstructions: number;
+ currentPhaseIndex: number;
+ phaseIndexes: Set<number>;
+ isShown: boolean;
+ rangeView: RangeView;
+ showRangeView: boolean;
+ toggleRangeViewEl: HTMLElement;
createViewElement() {
const pane = document.createElement('div');
@@ -20,6 +29,12 @@ export class SequenceView extends TextView {
constructor(parentId, broker) {
super(parentId, broker);
+ this.numInstructions = 0;
+ this.phaseIndexes = new Set<number>();
+ this.isShown = false;
+ this.showRangeView = false;
+ this.rangeView = null;
+ this.toggleRangeViewEl = this.elementForToggleRangeView();
}
attachSelection(s) {
@@ -37,34 +52,58 @@ export class SequenceView extends TextView {
return this.selection.detachSelection();
}
+ show() {
+ this.currentPhaseIndex = this.phaseSelect.selectedIndex;
+ if (!this.isShown) {
+ this.isShown = true;
+ this.phaseIndexes.add(this.currentPhaseIndex);
+ this.container.appendChild(this.divNode);
+ this.container.getElementsByClassName("graph-toolbox")[0].appendChild(this.toggleRangeViewEl);
+ }
+ if (this.showRangeView) this.rangeView.show();
+ }
+
+ hide() {
+ // A single SequenceView object is used for two phases (i.e before and after
+ // register allocation), tracking the indexes lets the redundant hides and
+ // shows be avoided when switching between the two.
+ this.currentPhaseIndex = this.phaseSelect.selectedIndex;
+ if (!this.phaseIndexes.has(this.currentPhaseIndex)) {
+ this.isShown = false;
+ this.container.removeChild(this.divNode);
+ this.container.getElementsByClassName("graph-toolbox")[0].removeChild(this.toggleRangeViewEl);
+ if (this.showRangeView) this.rangeView.hide();
+ }
+ }
+
+ onresize() {
+ if (this.showRangeView) this.rangeView.onresize();
+ }
+
initializeContent(data, rememberedSelection) {
this.divNode.innerHTML = '';
this.sequence = data.sequence;
this.searchInfo = [];
- this.divNode.addEventListener('click', (e: MouseEvent) => {
+ this.divNode.onclick = (e: MouseEvent) => {
if (!(e.target instanceof HTMLElement)) return;
const instructionId = Number.parseInt(e.target.dataset.instructionId, 10);
if (!instructionId) return;
if (!e.shiftKey) this.broker.broadcastClear(null);
this.broker.broadcastInstructionSelect(null, [instructionId], true);
- });
+ };
+ 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;
+ this.addRangeView();
this.attachSelection(rememberedSelection);
this.show();
}
elementForBlock(block) {
const view = this;
- function createElement(tag: string, cls: string | Array<string>, content?: string) {
- const el = document.createElement(tag);
- if (isIterable(cls)) {
- for (const c of cls) el.classList.add(c);
- } else {
- el.classList.add(cls);
- }
- if (content != undefined) el.innerHTML = content;
- return el;
- }
function mkLinkHandler(id, handler) {
return function (e) {
@@ -84,16 +123,33 @@ export class SequenceView extends TextView {
return mkLinkHandler(text, view.selectionHandler);
}
+ function elementForOperandWithSpan(span, text, searchInfo, isVirtual) {
+ const selectionText = isVirtual ? "virt_" + text : text;
+ span.onclick = mkOperandLinkHandler(selectionText);
+ searchInfo.push(text);
+ view.addHtmlElementForNodeId(selectionText, span);
+ const container = createElement("div", "");
+ container.appendChild(span);
+ return container;
+ }
+
function elementForOperand(operand, searchInfo) {
- const text = operand.text;
- const operandEl = createElement("div", ["parameter", "tag", "clickable", operand.type], text);
+ let isVirtual = false;
+ let className = "parameter tag clickable " + operand.type;
+ if (operand.text[0] == 'v' && !(operand.tooltip && operand.tooltip.includes("Float"))) {
+ isVirtual = true;
+ className += " virtual-reg";
+ }
+ const span = createElement("span", className, operand.text);
if (operand.tooltip) {
- operandEl.setAttribute("title", operand.tooltip);
+ span.setAttribute("title", operand.tooltip);
}
- operandEl.onclick = mkOperandLinkHandler(text);
- searchInfo.push(text);
- view.addHtmlElementForNodeId(text, operandEl);
- return operandEl;
+ return elementForOperandWithSpan(span, operand.text, searchInfo, isVirtual);
+ }
+
+ function elementForPhiOperand(text, searchInfo) {
+ const span = createElement("span", "parameter tag clickable virtual-reg", text);
+ return elementForOperandWithSpan(span, text, searchInfo, true);
}
function elementForInstruction(instruction, searchInfo) {
@@ -115,7 +171,7 @@ export class SequenceView extends TextView {
const gapEl = createElement("div", "gap", "gap");
let hasGaps = false;
for (const gap of instruction.gaps) {
- const moves = createElement("div", ["comma-sep-list", "gap-move"]);
+ const moves = createElement("div", "comma-sep-list gap-move");
for (const move of gap) {
hasGaps = true;
const moveEl = createElement("div", "move");
@@ -137,7 +193,7 @@ export class SequenceView extends TextView {
instContentsEl.appendChild(instEl);
if (instruction.outputs.length > 0) {
- const outputs = createElement("div", ["comma-sep-list", "input-output-list"]);
+ const outputs = createElement("div", "comma-sep-list input-output-list");
for (const output of instruction.outputs) {
const outputEl = elementForOperand(output, searchInfo);
outputs.appendChild(outputEl);
@@ -147,8 +203,8 @@ export class SequenceView extends TextView {
instEl.appendChild(assignEl);
}
- let text = instruction.opcode + instruction.flags;
- const instLabel = createElement("div", "node-label", text)
+ const text = instruction.opcode + instruction.flags;
+ const instLabel = createElement("div", "node-label", text);
if (instruction.opcode == "ArchNop" && instruction.outputs.length == 1 && instruction.outputs[0].tooltip) {
instLabel.innerText = instruction.outputs[0].tooltip;
}
@@ -158,7 +214,7 @@ export class SequenceView extends TextView {
instEl.appendChild(instLabel);
if (instruction.inputs.length > 0) {
- const inputs = createElement("div", ["comma-sep-list", "input-output-list"]);
+ const inputs = createElement("div", "comma-sep-list input-output-list");
for (const input of instruction.inputs) {
const inputEl = elementForOperand(input, searchInfo);
inputs.appendChild(inputEl);
@@ -167,7 +223,7 @@ export class SequenceView extends TextView {
}
if (instruction.temps.length > 0) {
- const temps = createElement("div", ["comma-sep-list", "input-output-list", "temps"]);
+ const temps = createElement("div", "comma-sep-list input-output-list temps");
for (const temp of instruction.temps) {
const tempEl = elementForOperand(temp, searchInfo);
temps.appendChild(tempEl);
@@ -181,12 +237,12 @@ export class SequenceView extends TextView {
const sequenceBlock = createElement("div", "schedule-block");
sequenceBlock.classList.toggle("deferred", block.deferred);
- const blockId = createElement("div", ["block-id", "com", "clickable"], block.id);
+ const blockId = createElement("div", "block-id com clickable", block.id);
blockId.onclick = mkBlockLinkHandler(block.id);
sequenceBlock.appendChild(blockId);
- const blockPred = createElement("div", ["predecessor-list", "block-list", "comma-sep-list"]);
+ const blockPred = createElement("div", "predecessor-list block-list comma-sep-list");
for (const pred of block.predecessors) {
- const predEl = createElement("div", ["block-id", "com", "clickable"], pred);
+ const predEl = createElement("div", "block-id com clickable", pred);
predEl.onclick = mkBlockLinkHandler(pred);
blockPred.appendChild(predEl);
}
@@ -211,7 +267,7 @@ export class SequenceView extends TextView {
phiEl.appendChild(assignEl);
for (const input of phi.operands) {
- const inputEl = createElement("div", ["parameter", "tag", "clickable"], input);
+ const inputEl = elementForPhiOperand(input, this.searchInfo);
phiEl.appendChild(inputEl);
}
}
@@ -221,9 +277,9 @@ export class SequenceView extends TextView {
instructions.appendChild(elementForInstruction(instruction, this.searchInfo));
}
sequenceBlock.appendChild(instructions);
- const blockSucc = createElement("div", ["successor-list", "block-list", "comma-sep-list"]);
+ const blockSucc = createElement("div", "successor-list block-list comma-sep-list");
for (const succ of block.successors) {
- const succEl = createElement("div", ["block-id", "com", "clickable"], succ);
+ const succEl = createElement("div", "block-id com clickable", succ);
succEl.onclick = mkBlockLinkHandler(succ);
blockSucc.appendChild(succEl);
}
@@ -239,6 +295,63 @@ export class SequenceView extends TextView {
}
}
+ addRangeView() {
+ const preventRangeView = reason => {
+ const toggleRangesInput = this.toggleRangeViewEl.firstChild as HTMLInputElement;
+ if (this.rangeView) {
+ toggleRangesInput.checked = false;
+ this.toggleRangeView(toggleRangesInput);
+ }
+ toggleRangesInput.disabled = true;
+ this.toggleRangeViewEl.style.textDecoration = "line-through";
+ this.toggleRangeViewEl.setAttribute("title", reason);
+ };
+
+ if (this.sequence.register_allocation) {
+ if (!this.rangeView) {
+ this.rangeView = new RangeView(this);
+ }
+ const source = this.sequence.register_allocation;
+ if (source.fixedLiveRanges.size == 0 && source.liveRanges.size == 0) {
+ preventRangeView("No live ranges to show");
+ } else if (this.numInstructions >= 249) {
+ // This is due to the css grid-column being limited to 1000 columns.
+ // Performance issues would otherwise impose some limit.
+ // TODO(george.wort@arm.com): Allow the user to specify an instruction range
+ // to display that spans less than 249 instructions.
+ preventRangeView(
+ "Live range display is only supported for sequences with less than 249 instructions");
+ }
+ if (this.showRangeView) {
+ this.rangeView.initializeContent(this.sequence.blocks);
+ }
+ } else {
+ preventRangeView("No live range data provided");
+ }
+ }
+
+ elementForToggleRangeView() {
+ const toggleRangeViewEl = createElement("label", "", "show live ranges");
+ const toggleRangesInput = createElement("input", "range-toggle-show") as HTMLInputElement;
+ toggleRangesInput.setAttribute("type", "checkbox");
+ toggleRangesInput.oninput = () => this.toggleRangeView(toggleRangesInput);
+ toggleRangeViewEl.insertBefore(toggleRangesInput, toggleRangeViewEl.firstChild);
+ return toggleRangeViewEl;
+ }
+
+ toggleRangeView(toggleRangesInput: HTMLInputElement) {
+ toggleRangesInput.disabled = true;
+ this.showRangeView = toggleRangesInput.checked;
+ if (this.showRangeView) {
+ this.rangeView.initializeContent(this.sequence.blocks);
+ this.rangeView.show();
+ } else {
+ this.rangeView.hide();
+ }
+ window.dispatchEvent(new Event('resize'));
+ toggleRangesInput.disabled = false;
+ }
+
searchInputAction(searchBar, e) {
e.stopPropagation();
this.selectionHandler.clear();