[turbolizer] Display block names in disassembly pane
Bug: v8:7327 Change-Id: Ia8e5d51b12cc86734523860af88d4c3948e0f0c0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1660614 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Daniel Clifford <danno@chromium.org> Cr-Commit-Position: refs/heads/master@{#63371}
This commit is contained in:
parent
5812aabb0b
commit
98dfac7526
@ -2433,6 +2433,23 @@ MaybeHandle<Code> Pipeline::GenerateCodeForCodeStub(
|
||||
return code;
|
||||
}
|
||||
|
||||
struct BlockStartsAsJSON {
|
||||
const ZoneVector<int>* block_starts;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const BlockStartsAsJSON& s) {
|
||||
out << ", \"blockIdToOffset\": {";
|
||||
bool need_comma = false;
|
||||
for (size_t i = 0; i < s.block_starts->size(); ++i) {
|
||||
if (need_comma) out << ", ";
|
||||
int offset = (*s.block_starts)[i];
|
||||
out << "\"" << i << "\":" << offset;
|
||||
need_comma = true;
|
||||
}
|
||||
out << "},";
|
||||
return out;
|
||||
}
|
||||
|
||||
// static
|
||||
wasm::WasmCompilationResult Pipeline::GenerateCodeForWasmNativeStub(
|
||||
wasm::WasmEngine* wasm_engine, CallDescriptor* call_descriptor,
|
||||
@ -2503,7 +2520,9 @@ wasm::WasmCompilationResult Pipeline::GenerateCodeForWasmNativeStub(
|
||||
|
||||
if (info.trace_turbo_json_enabled()) {
|
||||
TurboJsonFile json_of(&info, std::ios_base::app);
|
||||
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
|
||||
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\""
|
||||
<< BlockStartsAsJSON{&code_generator->block_starts()}
|
||||
<< "\"data\":\"";
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
std::stringstream disassembler_stream;
|
||||
Disassembler::Decode(
|
||||
@ -2696,7 +2715,9 @@ void Pipeline::GenerateCodeForWasmFunction(
|
||||
|
||||
if (data.info()->trace_turbo_json_enabled()) {
|
||||
TurboJsonFile json_of(data.info(), std::ios_base::app);
|
||||
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
|
||||
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\""
|
||||
<< BlockStartsAsJSON{&code_generator->block_starts()}
|
||||
<< "\"data\":\"";
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
std::stringstream disassembler_stream;
|
||||
Disassembler::Decode(
|
||||
@ -2934,23 +2955,6 @@ void PipelineImpl::AssembleCode(Linkage* linkage,
|
||||
data->EndPhaseKind();
|
||||
}
|
||||
|
||||
struct BlockStartsAsJSON {
|
||||
const ZoneVector<int>* block_starts;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const BlockStartsAsJSON& s) {
|
||||
out << ", \"blockIdToOffset\": {";
|
||||
bool need_comma = false;
|
||||
for (size_t i = 0; i < s.block_starts->size(); ++i) {
|
||||
if (need_comma) out << ", ";
|
||||
int offset = (*s.block_starts)[i];
|
||||
out << "\"" << i << "\":" << offset;
|
||||
need_comma = true;
|
||||
}
|
||||
out << "},";
|
||||
return out;
|
||||
}
|
||||
|
||||
MaybeHandle<Code> PipelineImpl::FinalizeCode(bool retire_broker) {
|
||||
PipelineData* data = this->data_;
|
||||
if (data->broker() && retire_broker) {
|
||||
|
47
tools/turbolizer/package-lock.json
generated
47
tools/turbolizer/package-lock.json
generated
@ -1687,9 +1687,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
|
||||
"integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
@ -2344,9 +2344,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"mixin-deep": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
|
||||
"integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
||||
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
|
||||
"requires": {
|
||||
"for-in": "^1.0.2",
|
||||
"is-extendable": "^1.0.1"
|
||||
@ -2872,9 +2872,9 @@
|
||||
}
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
|
||||
"integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
@ -3407,35 +3407,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
|
||||
"integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
|
||||
"requires": {
|
||||
"arr-union": "^3.1.0",
|
||||
"get-value": "^2.0.6",
|
||||
"is-extendable": "^0.1.1",
|
||||
"set-value": "^0.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"set-value": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
|
||||
"integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
"is-plain-object": "^2.0.1",
|
||||
"to-object-path": "^0.3.0"
|
||||
}
|
||||
}
|
||||
"set-value": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
|
@ -32,7 +32,7 @@ export class DisassemblyView extends TextView {
|
||||
pane.setAttribute('id', "disassembly");
|
||||
pane.innerHTML =
|
||||
`<pre id='disassembly-text-pre' class='prettyprint prettyprinted'>
|
||||
<ul id='disassembly-list' class='nolinenums noindent'>
|
||||
<ul class='disassembly-list nolinenums noindent'>
|
||||
</ul>
|
||||
</pre>`;
|
||||
|
||||
@ -46,6 +46,16 @@ 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 blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
|
||||
const blockIdElement = document.createElement("SPAN");
|
||||
blockIdElement.className = "block-id com linkable-text";
|
||||
blockIdElement.innerText = "";
|
||||
if (blockIds && blockIds.length > 0) {
|
||||
blockIds.forEach(blockId => view.addHtmlElementForBlockId(blockId, fragment));
|
||||
blockIdElement.innerText = `B${blockIds.join(",")}:`;
|
||||
blockIdElement.dataset.blockId = `${blockIds.join(",")}`;
|
||||
}
|
||||
fragment.appendChild(blockIdElement);
|
||||
const addressElement = document.createElement("SPAN");
|
||||
addressElement.className = "instruction-address";
|
||||
addressElement.innerText = matches.groups["address"];
|
||||
@ -58,11 +68,13 @@ export class DisassemblyView extends TextView {
|
||||
fragment.classList.add('tag');
|
||||
|
||||
if (!Number.isNaN(offset)) {
|
||||
const pcOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
let pcOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
if (pcOffset == -1) pcOffset = Number(offset);
|
||||
fragment.dataset.pcOffset = `${pcOffset}`;
|
||||
addressElement.classList.add('linkable-text');
|
||||
offsetElement.classList.add('linkable-text');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const UNCLASSIFIED_STYLE = {
|
||||
@ -79,11 +91,20 @@ export class DisassemblyView extends TextView {
|
||||
fragment.innerHTML = text;
|
||||
const replacer = (match, hexOffset) => {
|
||||
const offset = Number.parseInt(hexOffset, 16);
|
||||
const keyOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
return `<span class="tag linkable-text" data-pc-offset="${keyOffset}">${match}</span>`;
|
||||
let keyOffset = view.sourceResolver.getKeyPcOffset(offset);
|
||||
if (keyOffset == -1) keyOffset = Number(offset);
|
||||
const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
|
||||
let block = "";
|
||||
let blockIdData = "";
|
||||
if (blockIds && blockIds.length > 0) {
|
||||
block = `B${blockIds.join(",")} `;
|
||||
blockIdData = `data-block-id="${blockIds.join(",")}"`;
|
||||
}
|
||||
return `<span class="tag linkable-text" data-pc-offset="${keyOffset}" ${blockIdData}>${block}${match}</span>`;
|
||||
};
|
||||
const html = text.replace(/<.0?x?([0-9a-fA-F]+)>/g, replacer);
|
||||
fragment.innerHTML = html;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const OPCODE_STYLE = {
|
||||
@ -91,12 +112,14 @@ export class DisassemblyView extends TextView {
|
||||
};
|
||||
const BLOCK_HEADER_STYLE = {
|
||||
associateData: function (text, fragment) {
|
||||
if (view.sourceResolver.hasBlockStartInfo()) return false;
|
||||
const matches = /\d+/.exec(text);
|
||||
if (!matches) return;
|
||||
if (!matches) return true;
|
||||
const blockId = matches[0];
|
||||
fragment.dataset.blockId = blockId;
|
||||
fragment.innerHTML = text;
|
||||
fragment.className = "com block";
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const SOURCE_POSITION_HEADER_STYLE = {
|
||||
@ -135,7 +158,7 @@ export class DisassemblyView extends TextView {
|
||||
|
||||
const linkHandler = (e: MouseEvent) => {
|
||||
if (!(e.target instanceof HTMLElement)) return;
|
||||
const offsetAsString = e.target.dataset.pcOffset ? e.target.dataset.pcOffset : e.target.parentElement.dataset.pcOffset;
|
||||
const offsetAsString = typeof e.target.dataset.pcOffset != "undefined" ? e.target.dataset.pcOffset : e.target.parentElement.dataset.pcOffset;
|
||||
const offset = Number.parseInt(offsetAsString, 10);
|
||||
if ((typeof offsetAsString) != "undefined" && !Number.isNaN(offset)) {
|
||||
view.offsetSelection.select([offset], true);
|
||||
@ -156,12 +179,12 @@ export class DisassemblyView extends TextView {
|
||||
|
||||
const linkHandlerBlock = e => {
|
||||
const blockId = e.target.dataset.blockId;
|
||||
if (typeof blockId != "undefined" && !Number.isNaN(blockId)) {
|
||||
e.stopPropagation();
|
||||
if (typeof blockId != "undefined") {
|
||||
const blockIds = blockId.split(",");
|
||||
if (!e.shiftKey) {
|
||||
view.selectionHandler.clear();
|
||||
}
|
||||
view.blockSelectionHandler.select([blockId], true);
|
||||
view.blockSelectionHandler.select(blockIds, true);
|
||||
}
|
||||
};
|
||||
view.divNode.addEventListener('click', linkHandlerBlock);
|
||||
|
@ -118,6 +118,8 @@ export class SourceResolver {
|
||||
instructionToPCOffset: Array<number>;
|
||||
pcOffsetToInstructions: Map<number, Array<number>>;
|
||||
pcOffsets: Array<number>;
|
||||
blockIdToPCOffset: Array<number>;
|
||||
blockStartPCtoBlockIds: Map<number, Array<number>>;
|
||||
|
||||
constructor() {
|
||||
// Maps node ids to source positions.
|
||||
@ -147,6 +149,16 @@ export class SourceResolver {
|
||||
// Maps PC offsets to instructions.
|
||||
this.pcOffsetToInstructions = new Map();
|
||||
this.pcOffsets = [];
|
||||
this.blockIdToPCOffset = [];
|
||||
this.blockStartPCtoBlockIds = new Map();
|
||||
}
|
||||
|
||||
getBlockIdsForOffset(offset): Array<number> {
|
||||
return this.blockStartPCtoBlockIds.get(offset);
|
||||
}
|
||||
|
||||
hasBlockStartInfo() {
|
||||
return this.blockIdToPCOffset.length > 0;
|
||||
}
|
||||
|
||||
setSources(sources, mainBackup) {
|
||||
@ -447,6 +459,15 @@ export class SourceResolver {
|
||||
switch (phase.type) {
|
||||
case 'disassembly':
|
||||
this.disassemblyPhase = phase;
|
||||
if (phase['blockIdToOffset']) {
|
||||
for (const [blockId, pc] of Object.entries<number>(phase['blockIdToOffset'])) {
|
||||
this.blockIdToPCOffset[blockId] = pc;
|
||||
if (!this.blockStartPCtoBlockIds.has(pc)) {
|
||||
this.blockStartPCtoBlockIds.set(pc, []);
|
||||
}
|
||||
this.blockStartPCtoBlockIds.get(pc).push(Number(blockId));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'schedule':
|
||||
this.phaseNames.set(phase.name, this.phases.length);
|
||||
|
@ -129,6 +129,10 @@ export abstract class TextView extends PhaseView {
|
||||
if (this.divNode.parentNode == null) return;
|
||||
const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement);
|
||||
const view = this;
|
||||
const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`);
|
||||
for (const el of elementsToSelect) {
|
||||
el.classList.toggle("selected", false);
|
||||
}
|
||||
for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) {
|
||||
const isSelected = view.blockSelection.isSelected(blockId);
|
||||
for (const element of elements) {
|
||||
@ -136,10 +140,6 @@ export abstract class TextView extends PhaseView {
|
||||
element.classList.toggle("selected", isSelected);
|
||||
}
|
||||
}
|
||||
const elementsToSelect = view.divNode.querySelectorAll(`[data-pc-offset]`);
|
||||
for (const el of elementsToSelect) {
|
||||
el.classList.toggle("selected", false);
|
||||
}
|
||||
for (const key of this.nodeIdToHtmlElementsMap.keys()) {
|
||||
for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
|
||||
element.classList.toggle("selected", false);
|
||||
@ -170,7 +170,9 @@ export abstract class TextView extends PhaseView {
|
||||
const fragment = document.createElement("SPAN");
|
||||
|
||||
if (typeof style.associateData == 'function') {
|
||||
style.associateData(text, fragment);
|
||||
if (style.associateData(text, fragment) === false) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (style.css != undefined) {
|
||||
const css = isIterable(style.css) ? style.css : [style.css];
|
||||
@ -198,7 +200,7 @@ export abstract class TextView extends PhaseView {
|
||||
const text = matches[0];
|
||||
if (text != '') {
|
||||
const fragment = view.createFragment(matches[0], style);
|
||||
result.push(fragment);
|
||||
if (fragment !== null) result.push(fragment);
|
||||
}
|
||||
line = line.substr(matches[0].length);
|
||||
}
|
||||
|
@ -696,3 +696,9 @@ text {
|
||||
padding-left: .5ex;
|
||||
outline: 1px dotted grey;
|
||||
}
|
||||
|
||||
ul.disassembly-list .block-id {
|
||||
width: 4ex;
|
||||
display: block;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user