11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciimport { PROF_COLS, UNICODE_BLOCK } from "../src/constants";
61cb0ef41Sopenharmony_ciimport { SelectionBroker } from "../src/selection-broker";
71cb0ef41Sopenharmony_ciimport { TextView } from "../src/text-view";
81cb0ef41Sopenharmony_ciimport { MySelection } from "./selection";
91cb0ef41Sopenharmony_ciimport { anyToString, interpolate } from "./util";
101cb0ef41Sopenharmony_ciimport { InstructionSelectionHandler } from "./selection-handler";
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst toolboxHTML = `<div id="disassembly-toolbox">
131cb0ef41Sopenharmony_ci<form>
141cb0ef41Sopenharmony_ci  <label><input id="show-instruction-address" type="checkbox" name="instruction-address">Show addresses</label>
151cb0ef41Sopenharmony_ci  <label><input id="show-instruction-binary" type="checkbox" name="instruction-binary">Show binary literal</label>
161cb0ef41Sopenharmony_ci  <label><input id="highlight-gap-instructions" type="checkbox" name="instruction-binary">Highlight gap instructions</label>
171cb0ef41Sopenharmony_ci</form>
181cb0ef41Sopenharmony_ci</div>`;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciexport class DisassemblyView extends TextView {
211cb0ef41Sopenharmony_ci  SOURCE_POSITION_HEADER_REGEX: any;
221cb0ef41Sopenharmony_ci  addrEventCounts: any;
231cb0ef41Sopenharmony_ci  totalEventCounts: any;
241cb0ef41Sopenharmony_ci  maxEventCounts: any;
251cb0ef41Sopenharmony_ci  posLines: Array<any>;
261cb0ef41Sopenharmony_ci  instructionSelectionHandler: InstructionSelectionHandler;
271cb0ef41Sopenharmony_ci  offsetSelection: MySelection;
281cb0ef41Sopenharmony_ci  showInstructionAddressHandler: () => void;
291cb0ef41Sopenharmony_ci  showInstructionBinaryHandler: () => void;
301cb0ef41Sopenharmony_ci  highlightGapInstructionsHandler: () => void;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  createViewElement() {
331cb0ef41Sopenharmony_ci    const pane = document.createElement('div');
341cb0ef41Sopenharmony_ci    pane.setAttribute('id', "disassembly");
351cb0ef41Sopenharmony_ci    pane.innerHTML =
361cb0ef41Sopenharmony_ci      `<pre id='disassembly-text-pre' class='prettyprint prettyprinted'>
371cb0ef41Sopenharmony_ci       <ul class='disassembly-list nolinenums noindent'>
381cb0ef41Sopenharmony_ci       </ul>
391cb0ef41Sopenharmony_ci     </pre>`;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    return pane;
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  constructor(parentId, broker: SelectionBroker) {
451cb0ef41Sopenharmony_ci    super(parentId, broker);
461cb0ef41Sopenharmony_ci    const view = this;
471cb0ef41Sopenharmony_ci    const ADDRESS_STYLE = {
481cb0ef41Sopenharmony_ci      associateData: (text, fragment: HTMLElement) => {
491cb0ef41Sopenharmony_ci        const matches = text.match(/(?<address>0?x?[0-9a-fA-F]{8,16})(?<addressSpace>\s+)(?<offset>[0-9a-f]+)(?<offsetSpace>\s*)/);
501cb0ef41Sopenharmony_ci        const offset = Number.parseInt(matches.groups["offset"], 16);
511cb0ef41Sopenharmony_ci        const instructionKind = view.sourceResolver.getInstructionKindForPCOffset(offset);
521cb0ef41Sopenharmony_ci        fragment.dataset.instructionKind = instructionKind;
531cb0ef41Sopenharmony_ci        fragment.title = view.sourceResolver.instructionKindToReadableName(instructionKind);
541cb0ef41Sopenharmony_ci        const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
551cb0ef41Sopenharmony_ci        const blockIdElement = document.createElement("SPAN");
561cb0ef41Sopenharmony_ci        blockIdElement.className = "block-id com linkable-text";
571cb0ef41Sopenharmony_ci        blockIdElement.innerText = "";
581cb0ef41Sopenharmony_ci        if (blockIds && blockIds.length > 0) {
591cb0ef41Sopenharmony_ci          blockIds.forEach(blockId => view.addHtmlElementForBlockId(blockId, fragment));
601cb0ef41Sopenharmony_ci          blockIdElement.innerText = `B${blockIds.join(",")}:`;
611cb0ef41Sopenharmony_ci          blockIdElement.dataset.blockId = `${blockIds.join(",")}`;
621cb0ef41Sopenharmony_ci        }
631cb0ef41Sopenharmony_ci        fragment.appendChild(blockIdElement);
641cb0ef41Sopenharmony_ci        const addressElement = document.createElement("SPAN");
651cb0ef41Sopenharmony_ci        addressElement.className = "instruction-address";
661cb0ef41Sopenharmony_ci        addressElement.innerText = matches.groups["address"];
671cb0ef41Sopenharmony_ci        const offsetElement = document.createElement("SPAN");
681cb0ef41Sopenharmony_ci        offsetElement.innerText = matches.groups["offset"];
691cb0ef41Sopenharmony_ci        fragment.appendChild(addressElement);
701cb0ef41Sopenharmony_ci        fragment.appendChild(document.createTextNode(matches.groups["addressSpace"]));
711cb0ef41Sopenharmony_ci        fragment.appendChild(offsetElement);
721cb0ef41Sopenharmony_ci        fragment.appendChild(document.createTextNode(matches.groups["offsetSpace"]));
731cb0ef41Sopenharmony_ci        fragment.classList.add('tag');
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci        if (!Number.isNaN(offset)) {
761cb0ef41Sopenharmony_ci          let pcOffset = view.sourceResolver.getKeyPcOffset(offset);
771cb0ef41Sopenharmony_ci          if (pcOffset == -1) pcOffset = Number(offset);
781cb0ef41Sopenharmony_ci          fragment.dataset.pcOffset = `${pcOffset}`;
791cb0ef41Sopenharmony_ci          addressElement.classList.add('linkable-text');
801cb0ef41Sopenharmony_ci          offsetElement.classList.add('linkable-text');
811cb0ef41Sopenharmony_ci        }
821cb0ef41Sopenharmony_ci        return true;
831cb0ef41Sopenharmony_ci      }
841cb0ef41Sopenharmony_ci    };
851cb0ef41Sopenharmony_ci    const UNCLASSIFIED_STYLE = {
861cb0ef41Sopenharmony_ci      css: 'com'
871cb0ef41Sopenharmony_ci    };
881cb0ef41Sopenharmony_ci    const NUMBER_STYLE = {
891cb0ef41Sopenharmony_ci      css: ['instruction-binary', 'lit']
901cb0ef41Sopenharmony_ci    };
911cb0ef41Sopenharmony_ci    const COMMENT_STYLE = {
921cb0ef41Sopenharmony_ci      css: 'com'
931cb0ef41Sopenharmony_ci    };
941cb0ef41Sopenharmony_ci    const OPCODE_ARGS = {
951cb0ef41Sopenharmony_ci      associateData: function (text, fragment) {
961cb0ef41Sopenharmony_ci        fragment.innerHTML = text;
971cb0ef41Sopenharmony_ci        const replacer = (match, hexOffset) => {
981cb0ef41Sopenharmony_ci          const offset = Number.parseInt(hexOffset, 16);
991cb0ef41Sopenharmony_ci          let keyOffset = view.sourceResolver.getKeyPcOffset(offset);
1001cb0ef41Sopenharmony_ci          if (keyOffset == -1) keyOffset = Number(offset);
1011cb0ef41Sopenharmony_ci          const blockIds = view.sourceResolver.getBlockIdsForOffset(offset);
1021cb0ef41Sopenharmony_ci          let block = "";
1031cb0ef41Sopenharmony_ci          let blockIdData = "";
1041cb0ef41Sopenharmony_ci          if (blockIds && blockIds.length > 0) {
1051cb0ef41Sopenharmony_ci            block = `B${blockIds.join(",")} `;
1061cb0ef41Sopenharmony_ci            blockIdData = `data-block-id="${blockIds.join(",")}"`;
1071cb0ef41Sopenharmony_ci          }
1081cb0ef41Sopenharmony_ci          return `<span class="tag linkable-text" data-pc-offset="${keyOffset}" ${blockIdData}>${block}${match}</span>`;
1091cb0ef41Sopenharmony_ci        };
1101cb0ef41Sopenharmony_ci        const html = text.replace(/<.0?x?([0-9a-fA-F]+)>/g, replacer);
1111cb0ef41Sopenharmony_ci        fragment.innerHTML = html;
1121cb0ef41Sopenharmony_ci        return true;
1131cb0ef41Sopenharmony_ci      }
1141cb0ef41Sopenharmony_ci    };
1151cb0ef41Sopenharmony_ci    const OPCODE_STYLE = {
1161cb0ef41Sopenharmony_ci      css: 'kwd'
1171cb0ef41Sopenharmony_ci    };
1181cb0ef41Sopenharmony_ci    const BLOCK_HEADER_STYLE = {
1191cb0ef41Sopenharmony_ci      associateData: function (text, fragment) {
1201cb0ef41Sopenharmony_ci        if (view.sourceResolver.hasBlockStartInfo()) return false;
1211cb0ef41Sopenharmony_ci        const matches = /\d+/.exec(text);
1221cb0ef41Sopenharmony_ci        if (!matches) return true;
1231cb0ef41Sopenharmony_ci        const blockId = matches[0];
1241cb0ef41Sopenharmony_ci        fragment.dataset.blockId = blockId;
1251cb0ef41Sopenharmony_ci        fragment.innerHTML = text;
1261cb0ef41Sopenharmony_ci        fragment.className = "com block";
1271cb0ef41Sopenharmony_ci        return true;
1281cb0ef41Sopenharmony_ci      }
1291cb0ef41Sopenharmony_ci    };
1301cb0ef41Sopenharmony_ci    const SOURCE_POSITION_HEADER_STYLE = {
1311cb0ef41Sopenharmony_ci      css: 'com'
1321cb0ef41Sopenharmony_ci    };
1331cb0ef41Sopenharmony_ci    view.SOURCE_POSITION_HEADER_REGEX = /^\s*--[^<]*<.*(not inlined|inlined\((\d+)\)):(\d+)>\s*--/;
1341cb0ef41Sopenharmony_ci    const patterns = [
1351cb0ef41Sopenharmony_ci      [
1361cb0ef41Sopenharmony_ci        [/^0?x?[0-9a-fA-F]{8,16}\s+[0-9a-f]+\s+/, ADDRESS_STYLE, 1],
1371cb0ef41Sopenharmony_ci        [view.SOURCE_POSITION_HEADER_REGEX, SOURCE_POSITION_HEADER_STYLE, -1],
1381cb0ef41Sopenharmony_ci        [/^\s+-- B\d+ start.*/, BLOCK_HEADER_STYLE, -1],
1391cb0ef41Sopenharmony_ci        [/^.*/, UNCLASSIFIED_STYLE, -1]
1401cb0ef41Sopenharmony_ci      ],
1411cb0ef41Sopenharmony_ci      [
1421cb0ef41Sopenharmony_ci        [/^\s*[0-9a-f]+\s+/, NUMBER_STYLE, 2],
1431cb0ef41Sopenharmony_ci        [/^\s*[0-9a-f]+\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
1441cb0ef41Sopenharmony_ci        [/^.*/, null, -1]
1451cb0ef41Sopenharmony_ci      ],
1461cb0ef41Sopenharmony_ci      [
1471cb0ef41Sopenharmony_ci        [/^REX.W \S+\s+/, OPCODE_STYLE, 3],
1481cb0ef41Sopenharmony_ci        [/^\S+\s+/, OPCODE_STYLE, 3],
1491cb0ef41Sopenharmony_ci        [/^\S+$/, OPCODE_STYLE, -1],
1501cb0ef41Sopenharmony_ci        [/^.*/, null, -1]
1511cb0ef41Sopenharmony_ci      ],
1521cb0ef41Sopenharmony_ci      [
1531cb0ef41Sopenharmony_ci        [/^\s+/, null],
1541cb0ef41Sopenharmony_ci        [/^[^;]+$/, OPCODE_ARGS, -1],
1551cb0ef41Sopenharmony_ci        [/^[^;]+/, OPCODE_ARGS, 4],
1561cb0ef41Sopenharmony_ci        [/^;/, COMMENT_STYLE, 5]
1571cb0ef41Sopenharmony_ci      ],
1581cb0ef41Sopenharmony_ci      [
1591cb0ef41Sopenharmony_ci        [/^.+$/, COMMENT_STYLE, -1]
1601cb0ef41Sopenharmony_ci      ]
1611cb0ef41Sopenharmony_ci    ];
1621cb0ef41Sopenharmony_ci    view.setPatterns(patterns);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci    const linkHandler = (e: MouseEvent) => {
1651cb0ef41Sopenharmony_ci      if (!(e.target instanceof HTMLElement)) return;
1661cb0ef41Sopenharmony_ci      const offsetAsString = typeof e.target.dataset.pcOffset != "undefined" ? e.target.dataset.pcOffset : e.target.parentElement.dataset.pcOffset;
1671cb0ef41Sopenharmony_ci      const offset = Number.parseInt(offsetAsString, 10);
1681cb0ef41Sopenharmony_ci      if ((typeof offsetAsString) != "undefined" && !Number.isNaN(offset)) {
1691cb0ef41Sopenharmony_ci        view.offsetSelection.select([offset], true);
1701cb0ef41Sopenharmony_ci        const nodes = view.sourceResolver.nodesForPCOffset(offset)[0];
1711cb0ef41Sopenharmony_ci        if (nodes.length > 0) {
1721cb0ef41Sopenharmony_ci          e.stopPropagation();
1731cb0ef41Sopenharmony_ci          if (!e.shiftKey) {
1741cb0ef41Sopenharmony_ci            view.selectionHandler.clear();
1751cb0ef41Sopenharmony_ci          }
1761cb0ef41Sopenharmony_ci          view.selectionHandler.select(nodes, true);
1771cb0ef41Sopenharmony_ci        } else {
1781cb0ef41Sopenharmony_ci          view.updateSelection();
1791cb0ef41Sopenharmony_ci        }
1801cb0ef41Sopenharmony_ci      }
1811cb0ef41Sopenharmony_ci      return undefined;
1821cb0ef41Sopenharmony_ci    };
1831cb0ef41Sopenharmony_ci    view.divNode.addEventListener('click', linkHandler);
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci    const linkHandlerBlock = e => {
1861cb0ef41Sopenharmony_ci      const blockId = e.target.dataset.blockId;
1871cb0ef41Sopenharmony_ci      if (typeof blockId != "undefined") {
1881cb0ef41Sopenharmony_ci        const blockIds = blockId.split(",");
1891cb0ef41Sopenharmony_ci        if (!e.shiftKey) {
1901cb0ef41Sopenharmony_ci          view.selectionHandler.clear();
1911cb0ef41Sopenharmony_ci        }
1921cb0ef41Sopenharmony_ci        view.blockSelectionHandler.select(blockIds, true);
1931cb0ef41Sopenharmony_ci      }
1941cb0ef41Sopenharmony_ci    };
1951cb0ef41Sopenharmony_ci    view.divNode.addEventListener('click', linkHandlerBlock);
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci    this.offsetSelection = new MySelection(anyToString);
1981cb0ef41Sopenharmony_ci    const instructionSelectionHandler = {
1991cb0ef41Sopenharmony_ci      clear: function () {
2001cb0ef41Sopenharmony_ci        view.offsetSelection.clear();
2011cb0ef41Sopenharmony_ci        view.updateSelection();
2021cb0ef41Sopenharmony_ci        broker.broadcastClear(instructionSelectionHandler);
2031cb0ef41Sopenharmony_ci      },
2041cb0ef41Sopenharmony_ci      select: function (instructionIds, selected) {
2051cb0ef41Sopenharmony_ci        view.offsetSelection.select(instructionIds, selected);
2061cb0ef41Sopenharmony_ci        view.updateSelection();
2071cb0ef41Sopenharmony_ci        broker.broadcastBlockSelect(instructionSelectionHandler, instructionIds, selected);
2081cb0ef41Sopenharmony_ci      },
2091cb0ef41Sopenharmony_ci      brokeredInstructionSelect: function (instructionIds, selected) {
2101cb0ef41Sopenharmony_ci        const firstSelect = view.offsetSelection.isEmpty();
2111cb0ef41Sopenharmony_ci        const keyPcOffsets = view.sourceResolver.instructionsToKeyPcOffsets(instructionIds);
2121cb0ef41Sopenharmony_ci        view.offsetSelection.select(keyPcOffsets, selected);
2131cb0ef41Sopenharmony_ci        view.updateSelection(firstSelect);
2141cb0ef41Sopenharmony_ci      },
2151cb0ef41Sopenharmony_ci      brokeredClear: function () {
2161cb0ef41Sopenharmony_ci        view.offsetSelection.clear();
2171cb0ef41Sopenharmony_ci        view.updateSelection();
2181cb0ef41Sopenharmony_ci      }
2191cb0ef41Sopenharmony_ci    };
2201cb0ef41Sopenharmony_ci    this.instructionSelectionHandler = instructionSelectionHandler;
2211cb0ef41Sopenharmony_ci    broker.addInstructionHandler(instructionSelectionHandler);
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci    const toolbox = document.createElement("div");
2241cb0ef41Sopenharmony_ci    toolbox.id = "toolbox-anchor";
2251cb0ef41Sopenharmony_ci    toolbox.innerHTML = toolboxHTML;
2261cb0ef41Sopenharmony_ci    view.divNode.insertBefore(toolbox, view.divNode.firstChild);
2271cb0ef41Sopenharmony_ci    const instructionAddressInput: HTMLInputElement = view.divNode.querySelector("#show-instruction-address");
2281cb0ef41Sopenharmony_ci    const lastShowInstructionAddress = window.sessionStorage.getItem("show-instruction-address");
2291cb0ef41Sopenharmony_ci    instructionAddressInput.checked = lastShowInstructionAddress == 'true';
2301cb0ef41Sopenharmony_ci    const showInstructionAddressHandler = () => {
2311cb0ef41Sopenharmony_ci      window.sessionStorage.setItem("show-instruction-address", `${instructionAddressInput.checked}`);
2321cb0ef41Sopenharmony_ci      for (const el of view.divNode.querySelectorAll(".instruction-address")) {
2331cb0ef41Sopenharmony_ci        el.classList.toggle("invisible", !instructionAddressInput.checked);
2341cb0ef41Sopenharmony_ci      }
2351cb0ef41Sopenharmony_ci    };
2361cb0ef41Sopenharmony_ci    instructionAddressInput.addEventListener("change", showInstructionAddressHandler);
2371cb0ef41Sopenharmony_ci    this.showInstructionAddressHandler = showInstructionAddressHandler;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci    const instructionBinaryInput: HTMLInputElement = view.divNode.querySelector("#show-instruction-binary");
2401cb0ef41Sopenharmony_ci    const lastShowInstructionBinary = window.sessionStorage.getItem("show-instruction-binary");
2411cb0ef41Sopenharmony_ci    instructionBinaryInput.checked = lastShowInstructionBinary == 'true';
2421cb0ef41Sopenharmony_ci    const showInstructionBinaryHandler = () => {
2431cb0ef41Sopenharmony_ci      window.sessionStorage.setItem("show-instruction-binary", `${instructionBinaryInput.checked}`);
2441cb0ef41Sopenharmony_ci      for (const el of view.divNode.querySelectorAll(".instruction-binary")) {
2451cb0ef41Sopenharmony_ci        el.classList.toggle("invisible", !instructionBinaryInput.checked);
2461cb0ef41Sopenharmony_ci      }
2471cb0ef41Sopenharmony_ci    };
2481cb0ef41Sopenharmony_ci    instructionBinaryInput.addEventListener("change", showInstructionBinaryHandler);
2491cb0ef41Sopenharmony_ci    this.showInstructionBinaryHandler = showInstructionBinaryHandler;
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci    const highlightGapInstructionsInput: HTMLInputElement = view.divNode.querySelector("#highlight-gap-instructions");
2521cb0ef41Sopenharmony_ci    const lastHighlightGapInstructions = window.sessionStorage.getItem("highlight-gap-instructions");
2531cb0ef41Sopenharmony_ci    highlightGapInstructionsInput.checked = lastHighlightGapInstructions == 'true';
2541cb0ef41Sopenharmony_ci    const highlightGapInstructionsHandler = () => {
2551cb0ef41Sopenharmony_ci      window.sessionStorage.setItem("highlight-gap-instructions", `${highlightGapInstructionsInput.checked}`);
2561cb0ef41Sopenharmony_ci      view.divNode.classList.toggle("highlight-gap-instructions", highlightGapInstructionsInput.checked);
2571cb0ef41Sopenharmony_ci    };
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci    highlightGapInstructionsInput.addEventListener("change", highlightGapInstructionsHandler);
2601cb0ef41Sopenharmony_ci    this.highlightGapInstructionsHandler = highlightGapInstructionsHandler;
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  updateSelection(scrollIntoView: boolean = false) {
2641cb0ef41Sopenharmony_ci    super.updateSelection(scrollIntoView);
2651cb0ef41Sopenharmony_ci    const keyPcOffsets = this.sourceResolver.nodesToKeyPcOffsets(this.selection.selectedKeys());
2661cb0ef41Sopenharmony_ci    if (this.offsetSelection) {
2671cb0ef41Sopenharmony_ci      for (const key of this.offsetSelection.selectedKeys()) {
2681cb0ef41Sopenharmony_ci        keyPcOffsets.push(Number(key));
2691cb0ef41Sopenharmony_ci      }
2701cb0ef41Sopenharmony_ci    }
2711cb0ef41Sopenharmony_ci    for (const keyPcOffset of keyPcOffsets) {
2721cb0ef41Sopenharmony_ci      const elementsToSelect = this.divNode.querySelectorAll(`[data-pc-offset='${keyPcOffset}']`);
2731cb0ef41Sopenharmony_ci      for (const el of elementsToSelect) {
2741cb0ef41Sopenharmony_ci        el.classList.toggle("selected", true);
2751cb0ef41Sopenharmony_ci      }
2761cb0ef41Sopenharmony_ci    }
2771cb0ef41Sopenharmony_ci  }
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  initializeCode(sourceText, sourcePosition: number = 0) {
2801cb0ef41Sopenharmony_ci    const view = this;
2811cb0ef41Sopenharmony_ci    view.addrEventCounts = null;
2821cb0ef41Sopenharmony_ci    view.totalEventCounts = null;
2831cb0ef41Sopenharmony_ci    view.maxEventCounts = null;
2841cb0ef41Sopenharmony_ci    view.posLines = new Array();
2851cb0ef41Sopenharmony_ci    // Comment lines for line 0 include sourcePosition already, only need to
2861cb0ef41Sopenharmony_ci    // add sourcePosition for lines > 0.
2871cb0ef41Sopenharmony_ci    view.posLines[0] = sourcePosition;
2881cb0ef41Sopenharmony_ci    if (sourceText && sourceText != "") {
2891cb0ef41Sopenharmony_ci      const base = sourcePosition;
2901cb0ef41Sopenharmony_ci      let current = 0;
2911cb0ef41Sopenharmony_ci      const sourceLines = sourceText.split("\n");
2921cb0ef41Sopenharmony_ci      for (let i = 1; i < sourceLines.length; i++) {
2931cb0ef41Sopenharmony_ci        // Add 1 for newline character that is split off.
2941cb0ef41Sopenharmony_ci        current += sourceLines[i - 1].length + 1;
2951cb0ef41Sopenharmony_ci        view.posLines[i] = base + current;
2961cb0ef41Sopenharmony_ci      }
2971cb0ef41Sopenharmony_ci    }
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  initializePerfProfile(eventCounts) {
3011cb0ef41Sopenharmony_ci    const view = this;
3021cb0ef41Sopenharmony_ci    if (eventCounts !== undefined) {
3031cb0ef41Sopenharmony_ci      view.addrEventCounts = eventCounts;
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci      view.totalEventCounts = {};
3061cb0ef41Sopenharmony_ci      view.maxEventCounts = {};
3071cb0ef41Sopenharmony_ci      for (const evName in view.addrEventCounts) {
3081cb0ef41Sopenharmony_ci        if (view.addrEventCounts.hasOwnProperty(evName)) {
3091cb0ef41Sopenharmony_ci          const keys = Object.keys(view.addrEventCounts[evName]);
3101cb0ef41Sopenharmony_ci          const values = keys.map(key => view.addrEventCounts[evName][key]);
3111cb0ef41Sopenharmony_ci          view.totalEventCounts[evName] = values.reduce((a, b) => a + b);
3121cb0ef41Sopenharmony_ci          view.maxEventCounts[evName] = values.reduce((a, b) => Math.max(a, b));
3131cb0ef41Sopenharmony_ci        }
3141cb0ef41Sopenharmony_ci      }
3151cb0ef41Sopenharmony_ci    } else {
3161cb0ef41Sopenharmony_ci      view.addrEventCounts = null;
3171cb0ef41Sopenharmony_ci      view.totalEventCounts = null;
3181cb0ef41Sopenharmony_ci      view.maxEventCounts = null;
3191cb0ef41Sopenharmony_ci    }
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  showContent(data): void {
3231cb0ef41Sopenharmony_ci    console.time("disassembly-view");
3241cb0ef41Sopenharmony_ci    super.initializeContent(data, null);
3251cb0ef41Sopenharmony_ci    this.showInstructionAddressHandler();
3261cb0ef41Sopenharmony_ci    this.showInstructionBinaryHandler();
3271cb0ef41Sopenharmony_ci    this.highlightGapInstructionsHandler();
3281cb0ef41Sopenharmony_ci    console.timeEnd("disassembly-view");
3291cb0ef41Sopenharmony_ci  }
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  // Shorten decimals and remove trailing zeroes for readability.
3321cb0ef41Sopenharmony_ci  humanize(num) {
3331cb0ef41Sopenharmony_ci    return num.toFixed(3).replace(/\.?0+$/, "") + "%";
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci  processLine(line) {
3371cb0ef41Sopenharmony_ci    const view = this;
3381cb0ef41Sopenharmony_ci    let fragments = super.processLine(line);
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci    // Add profiling data per instruction if available.
3411cb0ef41Sopenharmony_ci    if (view.totalEventCounts) {
3421cb0ef41Sopenharmony_ci      const matches = /^(0x[0-9a-fA-F]+)\s+\d+\s+[0-9a-fA-F]+/.exec(line);
3431cb0ef41Sopenharmony_ci      if (matches) {
3441cb0ef41Sopenharmony_ci        const newFragments = [];
3451cb0ef41Sopenharmony_ci        for (const event in view.addrEventCounts) {
3461cb0ef41Sopenharmony_ci          if (!view.addrEventCounts.hasOwnProperty(event)) continue;
3471cb0ef41Sopenharmony_ci          const count = view.addrEventCounts[event][matches[1]];
3481cb0ef41Sopenharmony_ci          let str = " ";
3491cb0ef41Sopenharmony_ci          const cssCls = "prof";
3501cb0ef41Sopenharmony_ci          if (count !== undefined) {
3511cb0ef41Sopenharmony_ci            const perc = count / view.totalEventCounts[event] * 100;
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci            let col = { r: 255, g: 255, b: 255 };
3541cb0ef41Sopenharmony_ci            for (let i = 0; i < PROF_COLS.length; i++) {
3551cb0ef41Sopenharmony_ci              if (perc === PROF_COLS[i].perc) {
3561cb0ef41Sopenharmony_ci                col = PROF_COLS[i].col;
3571cb0ef41Sopenharmony_ci                break;
3581cb0ef41Sopenharmony_ci              } else if (perc > PROF_COLS[i].perc && perc < PROF_COLS[i + 1].perc) {
3591cb0ef41Sopenharmony_ci                const col1 = PROF_COLS[i].col;
3601cb0ef41Sopenharmony_ci                const col2 = PROF_COLS[i + 1].col;
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci                const val = perc - PROF_COLS[i].perc;
3631cb0ef41Sopenharmony_ci                const max = PROF_COLS[i + 1].perc - PROF_COLS[i].perc;
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci                col.r = Math.round(interpolate(val, max, col1.r, col2.r));
3661cb0ef41Sopenharmony_ci                col.g = Math.round(interpolate(val, max, col1.g, col2.g));
3671cb0ef41Sopenharmony_ci                col.b = Math.round(interpolate(val, max, col1.b, col2.b));
3681cb0ef41Sopenharmony_ci                break;
3691cb0ef41Sopenharmony_ci              }
3701cb0ef41Sopenharmony_ci            }
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci            str = UNICODE_BLOCK;
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci            const fragment = view.createFragment(str, cssCls);
3751cb0ef41Sopenharmony_ci            fragment.title = event + ": " + view.humanize(perc) + " (" + count + ")";
3761cb0ef41Sopenharmony_ci            fragment.style.color = "rgb(" + col.r + ", " + col.g + ", " + col.b + ")";
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci            newFragments.push(fragment);
3791cb0ef41Sopenharmony_ci          } else {
3801cb0ef41Sopenharmony_ci            newFragments.push(view.createFragment(str, cssCls));
3811cb0ef41Sopenharmony_ci          }
3821cb0ef41Sopenharmony_ci        }
3831cb0ef41Sopenharmony_ci        fragments = newFragments.concat(fragments);
3841cb0ef41Sopenharmony_ci      }
3851cb0ef41Sopenharmony_ci    }
3861cb0ef41Sopenharmony_ci    return fragments;
3871cb0ef41Sopenharmony_ci  }
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  detachSelection() { return null; }
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  public searchInputAction(searchInput: HTMLInputElement, e: Event, onlyVisible: boolean): void {
3921cb0ef41Sopenharmony_ci    throw new Error("Method not implemented.");
3931cb0ef41Sopenharmony_ci  }
3941cb0ef41Sopenharmony_ci}
395