• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import { Schedule, SourceResolver } from "../src/source-resolver";
6import { TextView } from "../src/text-view";
7
8export class ScheduleView extends TextView {
9  schedule: Schedule;
10  sourceResolver: SourceResolver;
11
12  createViewElement() {
13    const pane = document.createElement('div');
14    pane.setAttribute('id', "schedule");
15    pane.classList.add("scrollable");
16    pane.setAttribute("tabindex", "0");
17    return pane;
18  }
19
20  constructor(parentId, broker) {
21    super(parentId, broker);
22    this.sourceResolver = broker.sourceResolver;
23  }
24
25  attachSelection(s) {
26    const view = this;
27    if (!(s instanceof Set)) return;
28    view.selectionHandler.clear();
29    view.blockSelectionHandler.clear();
30    const selected = new Array();
31    for (const key of s) selected.push(key);
32    view.selectionHandler.select(selected, true);
33  }
34
35  detachSelection() {
36    this.blockSelection.clear();
37    return this.selection.detachSelection();
38  }
39
40  initializeContent(data, rememberedSelection) {
41    this.divNode.innerHTML = '';
42    this.schedule = data.schedule;
43    this.addBlocks(data.schedule.blocks);
44    this.attachSelection(rememberedSelection);
45    this.show();
46  }
47
48  createElementFromString(htmlString) {
49    const div = document.createElement('div');
50    div.innerHTML = htmlString.trim();
51    return div.firstChild;
52  }
53
54  elementForBlock(block) {
55    const view = this;
56    function createElement(tag: string, cls: string, content?: string) {
57      const el = document.createElement(tag);
58      el.className = cls;
59      if (content != undefined) el.innerHTML = content;
60      return el;
61    }
62
63    function mkNodeLinkHandler(nodeId) {
64      return function (e) {
65        e.stopPropagation();
66        if (!e.shiftKey) {
67          view.selectionHandler.clear();
68        }
69        view.selectionHandler.select([nodeId], true);
70      };
71    }
72
73    function getMarker(start, end) {
74      if (start != end) {
75        return ["⊙", `This node generated instructions in range [${start},${end}). ` +
76          `This is currently unreliable for constants.`];
77      }
78      if (start != -1) {
79        return ["·", `The instruction selector did not generate instructions ` +
80          `for this node, but processed the node at instruction ${start}. ` +
81          `This usually means that this node was folded into another node; ` +
82          `the highlighted machine code is a guess.`];
83      }
84      return ["", `This not is not in the final schedule.`];
85    }
86
87    function createElementForNode(node) {
88      const nodeEl = createElement("div", "node");
89
90      const [start, end] = view.sourceResolver.getInstruction(node.id);
91      const [marker, tooltip] = getMarker(start, end);
92      const instrMarker = createElement("div", "instr-marker com", marker);
93      instrMarker.setAttribute("title", tooltip);
94      instrMarker.onclick = mkNodeLinkHandler(node.id);
95      nodeEl.appendChild(instrMarker);
96
97      const nodeId = createElement("div", "node-id tag clickable", node.id);
98      nodeId.onclick = mkNodeLinkHandler(node.id);
99      view.addHtmlElementForNodeId(node.id, nodeId);
100      nodeEl.appendChild(nodeId);
101      const nodeLabel = createElement("div", "node-label", node.label);
102      nodeEl.appendChild(nodeLabel);
103      if (node.inputs.length > 0) {
104        const nodeParameters = createElement("div", "parameter-list comma-sep-list");
105        for (const param of node.inputs) {
106          const paramEl = createElement("div", "parameter tag clickable", param);
107          nodeParameters.appendChild(paramEl);
108          paramEl.onclick = mkNodeLinkHandler(param);
109          view.addHtmlElementForNodeId(param, paramEl);
110        }
111        nodeEl.appendChild(nodeParameters);
112      }
113
114      return nodeEl;
115    }
116
117    function mkBlockLinkHandler(blockId) {
118      return function (e) {
119        e.stopPropagation();
120        if (!e.shiftKey) {
121          view.blockSelectionHandler.clear();
122        }
123        view.blockSelectionHandler.select(["" + blockId], true);
124      };
125    }
126
127    const scheduleBlock = createElement("div", "schedule-block");
128    scheduleBlock.classList.toggle("deferred", block.isDeferred);
129
130    const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
131    const instrMarker = createElement("div", "instr-marker com", "⊙");
132    instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`);
133    instrMarker.onclick = mkBlockLinkHandler(block.id);
134    scheduleBlock.appendChild(instrMarker);
135
136    const blockId = createElement("div", "block-id com clickable", block.id);
137    blockId.onclick = mkBlockLinkHandler(block.id);
138    scheduleBlock.appendChild(blockId);
139    const blockPred = createElement("div", "predecessor-list block-list comma-sep-list");
140    for (const pred of block.pred) {
141      const predEl = createElement("div", "block-id com clickable", pred);
142      predEl.onclick = mkBlockLinkHandler(pred);
143      blockPred.appendChild(predEl);
144    }
145    if (block.pred.length) scheduleBlock.appendChild(blockPred);
146    const nodes = createElement("div", "nodes");
147    for (const node of block.nodes) {
148      nodes.appendChild(createElementForNode(node));
149    }
150    scheduleBlock.appendChild(nodes);
151    const blockSucc = createElement("div", "successor-list block-list comma-sep-list");
152    for (const succ of block.succ) {
153      const succEl = createElement("div", "block-id com clickable", succ);
154      succEl.onclick = mkBlockLinkHandler(succ);
155      blockSucc.appendChild(succEl);
156    }
157    if (block.succ.length) scheduleBlock.appendChild(blockSucc);
158    this.addHtmlElementForBlockId(block.id, scheduleBlock);
159    return scheduleBlock;
160  }
161
162  addBlocks(blocks) {
163    for (const block of blocks) {
164      const blockEl = this.elementForBlock(block);
165      this.divNode.appendChild(blockEl);
166    }
167  }
168
169  lineString(node) {
170    return `${node.id}: ${node.label}(${node.inputs.join(", ")})`;
171  }
172
173  searchInputAction(searchBar, e, onlyVisible) {
174    e.stopPropagation();
175    this.selectionHandler.clear();
176    const query = searchBar.value;
177    if (query.length == 0) return;
178    const select = [];
179    window.sessionStorage.setItem("lastSearch", query);
180    const reg = new RegExp(query);
181    for (const node of this.schedule.nodes) {
182      if (node === undefined) continue;
183      if (reg.exec(this.lineString(node)) != null) {
184        select.push(node.id);
185      }
186    }
187    this.selectionHandler.select(select, true);
188  }
189}
190