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 { Schedule, SourceResolver } from "../src/source-resolver";
61cb0ef41Sopenharmony_ciimport { TextView } from "../src/text-view";
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciexport class ScheduleView extends TextView {
91cb0ef41Sopenharmony_ci  schedule: Schedule;
101cb0ef41Sopenharmony_ci  sourceResolver: SourceResolver;
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci  createViewElement() {
131cb0ef41Sopenharmony_ci    const pane = document.createElement('div');
141cb0ef41Sopenharmony_ci    pane.setAttribute('id', "schedule");
151cb0ef41Sopenharmony_ci    pane.classList.add("scrollable");
161cb0ef41Sopenharmony_ci    pane.setAttribute("tabindex", "0");
171cb0ef41Sopenharmony_ci    return pane;
181cb0ef41Sopenharmony_ci  }
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci  constructor(parentId, broker) {
211cb0ef41Sopenharmony_ci    super(parentId, broker);
221cb0ef41Sopenharmony_ci    this.sourceResolver = broker.sourceResolver;
231cb0ef41Sopenharmony_ci  }
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  attachSelection(s) {
261cb0ef41Sopenharmony_ci    const view = this;
271cb0ef41Sopenharmony_ci    if (!(s instanceof Set)) return;
281cb0ef41Sopenharmony_ci    view.selectionHandler.clear();
291cb0ef41Sopenharmony_ci    view.blockSelectionHandler.clear();
301cb0ef41Sopenharmony_ci    const selected = new Array();
311cb0ef41Sopenharmony_ci    for (const key of s) selected.push(key);
321cb0ef41Sopenharmony_ci    view.selectionHandler.select(selected, true);
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  detachSelection() {
361cb0ef41Sopenharmony_ci    this.blockSelection.clear();
371cb0ef41Sopenharmony_ci    return this.selection.detachSelection();
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  initializeContent(data, rememberedSelection) {
411cb0ef41Sopenharmony_ci    this.divNode.innerHTML = '';
421cb0ef41Sopenharmony_ci    this.schedule = data.schedule;
431cb0ef41Sopenharmony_ci    this.addBlocks(data.schedule.blocks);
441cb0ef41Sopenharmony_ci    this.attachSelection(rememberedSelection);
451cb0ef41Sopenharmony_ci    this.show();
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  createElementFromString(htmlString) {
491cb0ef41Sopenharmony_ci    const div = document.createElement('div');
501cb0ef41Sopenharmony_ci    div.innerHTML = htmlString.trim();
511cb0ef41Sopenharmony_ci    return div.firstChild;
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  elementForBlock(block) {
551cb0ef41Sopenharmony_ci    const view = this;
561cb0ef41Sopenharmony_ci    function createElement(tag: string, cls: string, content?: string) {
571cb0ef41Sopenharmony_ci      const el = document.createElement(tag);
581cb0ef41Sopenharmony_ci      el.className = cls;
591cb0ef41Sopenharmony_ci      if (content != undefined) el.innerHTML = content;
601cb0ef41Sopenharmony_ci      return el;
611cb0ef41Sopenharmony_ci    }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci    function mkNodeLinkHandler(nodeId) {
641cb0ef41Sopenharmony_ci      return function (e) {
651cb0ef41Sopenharmony_ci        e.stopPropagation();
661cb0ef41Sopenharmony_ci        if (!e.shiftKey) {
671cb0ef41Sopenharmony_ci          view.selectionHandler.clear();
681cb0ef41Sopenharmony_ci        }
691cb0ef41Sopenharmony_ci        view.selectionHandler.select([nodeId], true);
701cb0ef41Sopenharmony_ci      };
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci    function getMarker(start, end) {
741cb0ef41Sopenharmony_ci      if (start != end) {
751cb0ef41Sopenharmony_ci        return ["⊙", `This node generated instructions in range [${start},${end}). ` +
761cb0ef41Sopenharmony_ci          `This is currently unreliable for constants.`];
771cb0ef41Sopenharmony_ci      }
781cb0ef41Sopenharmony_ci      if (start != -1) {
791cb0ef41Sopenharmony_ci        return ["·", `The instruction selector did not generate instructions ` +
801cb0ef41Sopenharmony_ci          `for this node, but processed the node at instruction ${start}. ` +
811cb0ef41Sopenharmony_ci          `This usually means that this node was folded into another node; ` +
821cb0ef41Sopenharmony_ci          `the highlighted machine code is a guess.`];
831cb0ef41Sopenharmony_ci      }
841cb0ef41Sopenharmony_ci      return ["", `This not is not in the final schedule.`];
851cb0ef41Sopenharmony_ci    }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci    function createElementForNode(node) {
881cb0ef41Sopenharmony_ci      const nodeEl = createElement("div", "node");
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci      const [start, end] = view.sourceResolver.getInstruction(node.id);
911cb0ef41Sopenharmony_ci      const [marker, tooltip] = getMarker(start, end);
921cb0ef41Sopenharmony_ci      const instrMarker = createElement("div", "instr-marker com", marker);
931cb0ef41Sopenharmony_ci      instrMarker.setAttribute("title", tooltip);
941cb0ef41Sopenharmony_ci      instrMarker.onclick = mkNodeLinkHandler(node.id);
951cb0ef41Sopenharmony_ci      nodeEl.appendChild(instrMarker);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci      const nodeId = createElement("div", "node-id tag clickable", node.id);
981cb0ef41Sopenharmony_ci      nodeId.onclick = mkNodeLinkHandler(node.id);
991cb0ef41Sopenharmony_ci      view.addHtmlElementForNodeId(node.id, nodeId);
1001cb0ef41Sopenharmony_ci      nodeEl.appendChild(nodeId);
1011cb0ef41Sopenharmony_ci      const nodeLabel = createElement("div", "node-label", node.label);
1021cb0ef41Sopenharmony_ci      nodeEl.appendChild(nodeLabel);
1031cb0ef41Sopenharmony_ci      if (node.inputs.length > 0) {
1041cb0ef41Sopenharmony_ci        const nodeParameters = createElement("div", "parameter-list comma-sep-list");
1051cb0ef41Sopenharmony_ci        for (const param of node.inputs) {
1061cb0ef41Sopenharmony_ci          const paramEl = createElement("div", "parameter tag clickable", param);
1071cb0ef41Sopenharmony_ci          nodeParameters.appendChild(paramEl);
1081cb0ef41Sopenharmony_ci          paramEl.onclick = mkNodeLinkHandler(param);
1091cb0ef41Sopenharmony_ci          view.addHtmlElementForNodeId(param, paramEl);
1101cb0ef41Sopenharmony_ci        }
1111cb0ef41Sopenharmony_ci        nodeEl.appendChild(nodeParameters);
1121cb0ef41Sopenharmony_ci      }
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci      return nodeEl;
1151cb0ef41Sopenharmony_ci    }
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci    function mkBlockLinkHandler(blockId) {
1181cb0ef41Sopenharmony_ci      return function (e) {
1191cb0ef41Sopenharmony_ci        e.stopPropagation();
1201cb0ef41Sopenharmony_ci        if (!e.shiftKey) {
1211cb0ef41Sopenharmony_ci          view.blockSelectionHandler.clear();
1221cb0ef41Sopenharmony_ci        }
1231cb0ef41Sopenharmony_ci        view.blockSelectionHandler.select(["" + blockId], true);
1241cb0ef41Sopenharmony_ci      };
1251cb0ef41Sopenharmony_ci    }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci    const scheduleBlock = createElement("div", "schedule-block");
1281cb0ef41Sopenharmony_ci    scheduleBlock.classList.toggle("deferred", block.isDeferred);
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci    const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
1311cb0ef41Sopenharmony_ci    const instrMarker = createElement("div", "instr-marker com", "⊙");
1321cb0ef41Sopenharmony_ci    instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
1331cb0ef41Sopenharmony_ci    instrMarker.onclick = mkBlockLinkHandler(block.id);
1341cb0ef41Sopenharmony_ci    scheduleBlock.appendChild(instrMarker);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci    const blockId = createElement("div", "block-id com clickable", block.id);
1371cb0ef41Sopenharmony_ci    blockId.onclick = mkBlockLinkHandler(block.id);
1381cb0ef41Sopenharmony_ci    scheduleBlock.appendChild(blockId);
1391cb0ef41Sopenharmony_ci    const blockPred = createElement("div", "predecessor-list block-list comma-sep-list");
1401cb0ef41Sopenharmony_ci    for (const pred of block.pred) {
1411cb0ef41Sopenharmony_ci      const predEl = createElement("div", "block-id com clickable", pred);
1421cb0ef41Sopenharmony_ci      predEl.onclick = mkBlockLinkHandler(pred);
1431cb0ef41Sopenharmony_ci      blockPred.appendChild(predEl);
1441cb0ef41Sopenharmony_ci    }
1451cb0ef41Sopenharmony_ci    if (block.pred.length) scheduleBlock.appendChild(blockPred);
1461cb0ef41Sopenharmony_ci    const nodes = createElement("div", "nodes");
1471cb0ef41Sopenharmony_ci    for (const node of block.nodes) {
1481cb0ef41Sopenharmony_ci      nodes.appendChild(createElementForNode(node));
1491cb0ef41Sopenharmony_ci    }
1501cb0ef41Sopenharmony_ci    scheduleBlock.appendChild(nodes);
1511cb0ef41Sopenharmony_ci    const blockSucc = createElement("div", "successor-list block-list comma-sep-list");
1521cb0ef41Sopenharmony_ci    for (const succ of block.succ) {
1531cb0ef41Sopenharmony_ci      const succEl = createElement("div", "block-id com clickable", succ);
1541cb0ef41Sopenharmony_ci      succEl.onclick = mkBlockLinkHandler(succ);
1551cb0ef41Sopenharmony_ci      blockSucc.appendChild(succEl);
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci    if (block.succ.length) scheduleBlock.appendChild(blockSucc);
1581cb0ef41Sopenharmony_ci    this.addHtmlElementForBlockId(block.id, scheduleBlock);
1591cb0ef41Sopenharmony_ci    return scheduleBlock;
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  addBlocks(blocks) {
1631cb0ef41Sopenharmony_ci    for (const block of blocks) {
1641cb0ef41Sopenharmony_ci      const blockEl = this.elementForBlock(block);
1651cb0ef41Sopenharmony_ci      this.divNode.appendChild(blockEl);
1661cb0ef41Sopenharmony_ci    }
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  lineString(node) {
1701cb0ef41Sopenharmony_ci    return `${node.id}: ${node.label}(${node.inputs.join(", ")})`;
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  searchInputAction(searchBar, e, onlyVisible) {
1741cb0ef41Sopenharmony_ci    e.stopPropagation();
1751cb0ef41Sopenharmony_ci    this.selectionHandler.clear();
1761cb0ef41Sopenharmony_ci    const query = searchBar.value;
1771cb0ef41Sopenharmony_ci    if (query.length == 0) return;
1781cb0ef41Sopenharmony_ci    const select = [];
1791cb0ef41Sopenharmony_ci    window.sessionStorage.setItem("lastSearch", query);
1801cb0ef41Sopenharmony_ci    const reg = new RegExp(query);
1811cb0ef41Sopenharmony_ci    for (const node of this.schedule.nodes) {
1821cb0ef41Sopenharmony_ci      if (node === undefined) continue;
1831cb0ef41Sopenharmony_ci      if (reg.exec(this.lineString(node)) != null) {
1841cb0ef41Sopenharmony_ci        select.push(node.id);
1851cb0ef41Sopenharmony_ci      }
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci    this.selectionHandler.select(select, true);
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci}
190