schedule-view.ts 6.3 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
import { Schedule, SourceResolver } from "../src/source-resolver";
import { TextView } from "../src/text-view";
7

8
export class ScheduleView extends TextView {
9
  schedule: Schedule;
10
  sourceResolver: SourceResolver;
11 12 13 14 15 16 17 18

  createViewElement() {
    const pane = document.createElement('div');
    pane.setAttribute('id', "schedule");
    return pane;
  }

  constructor(parentId, broker) {
19
    super(parentId, broker);
20
    this.sourceResolver = broker.sourceResolver;
21 22 23 24 25 26 27 28 29 30 31 32
  }

  attachSelection(s) {
    const view = this;
    if (!(s instanceof Set)) return;
    view.selectionHandler.clear();
    view.blockSelectionHandler.clear();
    const selected = new Array();
    for (const key of s) selected.push(key);
    view.selectionHandler.select(selected, true);
  }

33 34 35 36 37 38 39
  detachSelection() {
    this.blockSelection.clear();
    return this.selection.detachSelection();
  }

  initializeContent(data, rememberedSelection) {
    this.divNode.innerHTML = '';
40
    this.schedule = data.schedule;
41 42
    this.addBlocks(data.schedule.blocks);
    this.attachSelection(rememberedSelection);
43
    this.show();
44 45
  }

46
  createElementFromString(htmlString) {
47
    const div = document.createElement('div');
48 49 50 51 52 53
    div.innerHTML = htmlString.trim();
    return div.firstChild;
  }

  elementForBlock(block) {
    const view = this;
54
    function createElement(tag: string, cls: string, content?: string) {
55
      const el = document.createElement(tag);
56
      el.className = cls;
57 58 59 60 61 62 63 64 65 66 67 68 69 70
      if (content != undefined) el.innerHTML = content;
      return el;
    }

    function mkNodeLinkHandler(nodeId) {
      return function (e) {
        e.stopPropagation();
        if (!e.shiftKey) {
          view.selectionHandler.clear();
        }
        view.selectionHandler.select([nodeId], true);
      };
    }

71 72 73
    function getMarker(start, end) {
      if (start != end) {
        return ["⊙", `This node generated instructions in range [${start},${end}). ` +
74
          `This is currently unreliable for constants.`];
75 76 77
      }
      if (start != -1) {
        return ["·", `The instruction selector did not generate instructions ` +
78 79 80
          `for this node, but processed the node at instruction ${start}. ` +
          `This usually means that this node was folded into another node; ` +
          `the highlighted machine code is a guess.`];
81
      }
82
      return ["", `This not is not in the final schedule.`];
83 84
    }

85 86
    function createElementForNode(node) {
      const nodeEl = createElement("div", "node");
87 88 89

      const [start, end] = view.sourceResolver.getInstruction(node.id);
      const [marker, tooltip] = getMarker(start, end);
90
      const instrMarker = createElement("div", "instr-marker com", marker);
91 92 93 94
      instrMarker.setAttribute("title", tooltip);
      instrMarker.onclick = mkNodeLinkHandler(node.id);
      nodeEl.appendChild(instrMarker);

95 96 97 98 99 100
      const nodeId = createElement("div", "node-id tag clickable", node.id);
      nodeId.onclick = mkNodeLinkHandler(node.id);
      view.addHtmlElementForNodeId(node.id, nodeId);
      nodeEl.appendChild(nodeId);
      const nodeLabel = createElement("div", "node-label", node.label);
      nodeEl.appendChild(nodeLabel);
101
      if (node.inputs.length > 0) {
102
        const nodeParameters = createElement("div", "parameter-list comma-sep-list");
103
        for (const param of node.inputs) {
104
          const paramEl = createElement("div", "parameter tag clickable", param);
105
          nodeParameters.appendChild(paramEl);
106 107 108
          paramEl.onclick = mkNodeLinkHandler(param);
          view.addHtmlElementForNodeId(param, paramEl);
        }
109
        nodeEl.appendChild(nodeParameters);
110
      }
111

112
      return nodeEl;
113
    }
114 115 116 117 118 119 120 121 122 123 124

    function mkBlockLinkHandler(blockId) {
      return function (e) {
        e.stopPropagation();
        if (!e.shiftKey) {
          view.blockSelectionHandler.clear();
        }
        view.blockSelectionHandler.select(["" + blockId], true);
      };
    }

125
    const scheduleBlock = createElement("div", "schedule-block");
126 127

    const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
128
    const instrMarker = createElement("div", "instr-marker com", "⊙");
129
    instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
130
    instrMarker.onclick = mkBlockLinkHandler(block.id);
131
    scheduleBlock.appendChild(instrMarker);
132

133 134 135 136
    const blockId = createElement("div", "block-id com clickable", block.id);
    blockId.onclick = mkBlockLinkHandler(block.id);
    scheduleBlock.appendChild(blockId);
    const blockPred = createElement("div", "predecessor-list block-list comma-sep-list");
137
    for (const pred of block.pred) {
138
      const predEl = createElement("div", "block-id com clickable", pred);
139
      predEl.onclick = mkBlockLinkHandler(pred);
140
      blockPred.appendChild(predEl);
141
    }
142
    if (block.pred.length) scheduleBlock.appendChild(blockPred);
143 144
    const nodes = createElement("div", "nodes");
    for (const node of block.nodes) {
145
      nodes.appendChild(createElementForNode(node));
146
    }
147 148
    scheduleBlock.appendChild(nodes);
    const blockSucc = createElement("div", "successor-list block-list comma-sep-list");
149
    for (const succ of block.succ) {
150
      const succEl = createElement("div", "block-id com clickable", succ);
151
      succEl.onclick = mkBlockLinkHandler(succ);
152
      blockSucc.appendChild(succEl);
153
    }
154 155 156
    if (block.succ.length) scheduleBlock.appendChild(blockSucc);
    this.addHtmlElementForBlockId(block.id, scheduleBlock);
    return scheduleBlock;
157
  }
158

159 160 161 162
  addBlocks(blocks) {
    for (const block of blocks) {
      const blockEl = this.elementForBlock(block);
      this.divNode.appendChild(blockEl);
163
    }
164 165 166
  }

  lineString(node) {
167
    return `${node.id}: ${node.label}(${node.inputs.join(", ")})`;
168 169
  }

170
  searchInputAction(searchBar, e, onlyVisible) {
171
    e.stopPropagation();
172 173 174 175 176 177 178 179 180
    this.selectionHandler.clear();
    const query = searchBar.value;
    if (query.length == 0) return;
    const select = [];
    window.sessionStorage.setItem("lastSearch", query);
    const reg = new RegExp(query);
    for (const node of this.schedule.nodes) {
      if (node === undefined) continue;
      if (reg.exec(this.lineString(node)) != null) {
181
        select.push(node.id);
182
      }
183 184
    }
    this.selectionHandler.select(select, true);
185
  }
186
}