Commit 9693b86f authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbolizer] Improve selection handling in disassembly view

Disassembly selections now work even if no origin node is associated
with the disassembly code range that the user selects.

TBR=neis@chromium.org

Bug: v8:7327
Change-Id: Ib5bfcaded66deb65314fde7d3cb9ed2c3c4f6fe9
Notry: true
Reviewed-on: https://chromium-review.googlesource.com/c/1387492Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58423}
parent 6e5fb004
......@@ -118,6 +118,7 @@ export class DisassemblyView extends TextView {
const linkHandler = (e) => {
const offset = e.target.dataset.pcOffset;
if (typeof offset != "undefined" && !Number.isNaN(offset)) {
view.offsetSelection.select([offset], true);
const [nodes, blockId] = view.sourceResolver.nodesForPCOffset(offset)
if (nodes.length > 0) {
e.stopPropagation();
......@@ -125,6 +126,8 @@ export class DisassemblyView extends TextView {
view.selectionHandler.clear();
}
view.selectionHandler.select(nodes, true);
} else {
view.updateSelection();
}
}
return undefined;
......@@ -170,6 +173,22 @@ export class DisassemblyView extends TextView {
broker.addInstructionHandler(instructionSelectionHandler);
}
updateSelection(scrollIntoView: boolean = false) {
super.updateSelection(scrollIntoView);
let keyPcOffsets = this.sourceResolver.nodesToKeyPcOffsets(this.selection.selectedKeys());
if (this.offsetSelection) {
for (const key of this.offsetSelection.selectedKeys()) {
keyPcOffsets.push(Number(key))
}
}
for (const keyPcOffset of keyPcOffsets) {
const elementsToSelect = this.divNode.querySelectorAll(`[data-pc-offset='${keyPcOffset}']`)
for (const el of elementsToSelect) {
el.classList.toggle("selected", true);
}
}
}
initializeCode(sourceText, sourcePosition) {
let view = this;
view.addr_event_counts = null;
......
......@@ -68,7 +68,7 @@ interface Inlining {
sourceId: number;
}
interface OtherPhase {
type: "disassembly"|"sequence"|"schedule";
type: "disassembly" | "sequence" | "schedule";
name: string;
data: any;
}
......@@ -77,9 +77,9 @@ interface InstructionsPhase {
type: "instructions";
name: string;
data: any;
instructionOffsetToPCOffset: any;
blockIdtoInstructionRange: any;
nodeIdToInstructionRange: any;
instructionOffsetToPCOffset?: any;
blockIdtoInstructionRange?: any;
nodeIdToInstructionRange?: any;
}
interface GraphPhase {
......@@ -320,7 +320,7 @@ export class SourceResolver {
return inliningStack;
}
recordOrigins(phase:GraphPhase) {
recordOrigins(phase: GraphPhase) {
if (phase.type != "graph") return;
for (const node of phase.data.nodes) {
phase.highestNodeId = Math.max(phase.highestNodeId, node.id)
......@@ -436,29 +436,37 @@ export class SourceResolver {
parsePhases(phases) {
for (const [phaseId, phase] of Object.entries<Phase>(phases)) {
if (phase.type == 'disassembly') {
this.disassemblyPhase = phase;
} else if (phase.type == 'schedule') {
this.phases.push(this.parseSchedule(phase));
this.phaseNames.set(phase.name, this.phases.length);
} else if (phase.type == 'sequence') {
this.phases.push(this.parseSequence(phase));
this.phaseNames.set(phase.name, this.phases.length);
} else if (phase.type == 'instructions') {
if (phase.nodeIdToInstructionRange) {
this.readNodeIdToInstructionRange(phase.nodeIdToInstructionRange);
}
if (phase.blockIdtoInstructionRange) {
this.readBlockIdToInstructionRange(phase.blockIdtoInstructionRange);
}
if (phase.instructionOffsetToPCOffset) {
this.readInstructionOffsetToPCOffset(phase.instructionOffsetToPCOffset);
}
} else {
const graphPhase: GraphPhase = Object.assign({highestNodeId: 0});
this.phases.push(graphPhase);
this.recordOrigins(graphPhase);
this.phaseNames.set(graphPhase.name, this.phases.length);
switch (phase.type) {
case 'disassembly':
this.disassemblyPhase = phase;
break;
case 'schedule':
this.phases.push(this.parseSchedule(phase));
this.phaseNames.set(phase.name, this.phases.length);
break;
case 'sequence':
this.phases.push(this.parseSequence(phase));
this.phaseNames.set(phase.name, this.phases.length);
break;
case 'instructions':
if (phase.nodeIdToInstructionRange) {
this.readNodeIdToInstructionRange(phase.nodeIdToInstructionRange);
}
if (phase.blockIdtoInstructionRange) {
this.readBlockIdToInstructionRange(phase.blockIdtoInstructionRange);
}
if (phase.instructionOffsetToPCOffset) {
this.readInstructionOffsetToPCOffset(phase.instructionOffsetToPCOffset);
}
break;
case 'graph':
const graphPhase: GraphPhase = Object.assign(phase, { highestNodeId: 0 });
this.phases.push(graphPhase);
this.recordOrigins(graphPhase);
this.phaseNames.set(graphPhase.name, this.phases.length);
break;
default:
throw "Unsupported phase type";
}
}
}
......@@ -475,7 +483,7 @@ export class SourceResolver {
return this.phaseNames.get(phaseName);
}
forEachPhase(f:(value: Phase, index: number, array: Phase[]) => void) {
forEachPhase(f: (value: Phase, index: number, array: Phase[]) => void) {
this.phases.forEach(f);
}
......
......@@ -59,11 +59,12 @@ export abstract class TextView extends View {
};
this.selectionHandler = selectionHandler;
broker.addNodeHandler(selectionHandler);
view.divNode.onmouseup = function (e) {
view.divNode.addEventListener('click', (e) => {
if (!e.shiftKey) {
view.selectionHandler.clear();
}
}
e.stopPropagation();
});
const blockSelectionHandler = {
clear: function () {
view.blockSelection.clear();
......@@ -139,18 +140,6 @@ export abstract class TextView extends View {
for (const el of elementsToSelect) {
el.classList.toggle("selected", false);
}
let keyPcOffsets = view.sourceResolver.nodesToKeyPcOffsets(view.selection.selectedKeys());
if (view.offsetSelection) {
for (const key of view.offsetSelection.selectedKeys()) {
keyPcOffsets.push(Number(key))
}
}
for (const keyPcOffset of keyPcOffsets) {
const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset='${keyPcOffset}']`)
for (const el of elementsToSelect) {
el.classList.toggle("selected", true);
}
}
for (const key of this.nodeIdToHtmlElementsMap.keys()) {
for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
element.classList.toggle("selected", false);
......
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