• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 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
5var TYPE_HEIGHT = 25;
6var DEFAULT_NODE_BUBBLE_RADIUS = 12;
7var NODE_INPUT_WIDTH = 50;
8var MINIMUM_NODE_INPUT_APPROACH = 15 + 2 * DEFAULT_NODE_BUBBLE_RADIUS;
9var MINIMUM_NODE_OUTPUT_APPROACH = 15;
10
11function isNodeInitiallyVisible(node) {
12  return node.cfg;
13}
14
15var Node = {
16  isControl: function() {
17    return this.control;
18  },
19  isInput: function() {
20    return this.opcode == 'Parameter' || this.opcode.endsWith('Constant');
21  },
22  isLive: function() {
23    return this.live !== false;
24  },
25  isJavaScript: function() {
26    return this.opcode.startsWith('JS');
27  },
28  isSimplified: function() {
29    if (this.isJavaScript()) return false;
30    return this.opcode.endsWith('Phi') ||
31      this.opcode.startsWith('Boolean') ||
32      this.opcode.startsWith('Number') ||
33      this.opcode.startsWith('String') ||
34      this.opcode.startsWith('Change') ||
35      this.opcode.startsWith('Object') ||
36      this.opcode.startsWith('Reference') ||
37      this.opcode.startsWith('Any') ||
38      this.opcode.endsWith('ToNumber') ||
39      (this.opcode == 'AnyToBoolean') ||
40      (this.opcode.startsWith('Load') && this.opcode.length > 4) ||
41      (this.opcode.startsWith('Store') && this.opcode.length > 5);
42  },
43  isMachine: function() {
44    return !(this.isControl() || this.isInput() ||
45             this.isJavaScript() || this.isSimplified());
46  },
47  getTotalNodeWidth: function() {
48    var inputWidth = this.inputs.length * NODE_INPUT_WIDTH;
49    return Math.max(inputWidth, this.width);
50  },
51  getTitle: function() {
52    var propsString;
53    if (this.properties === undefined) {
54      propsString = "";
55    } else if (this.properties === "") {
56      propsString = "no properties";
57    } else {
58      propsString = "[" + this.properties + "]";
59    }
60    return this.title + "\n" + propsString + "\n" + this.opinfo;
61  },
62  getDisplayLabel: function() {
63    var result = this.id + ":" + this.label;
64    if (result.length > 40) {
65      return this.id + ":" + this.opcode;
66    } else  {
67      return result;
68    }
69  },
70  getType: function() {
71    return this.type;
72  },
73  getDisplayType: function() {
74    var type_string = this.type;
75    if (type_string == undefined) return "";
76    if (type_string.length > 24) {
77      type_string = type_string.substr(0, 25) + "...";
78    }
79    return type_string;
80  },
81  deepestInputRank: function() {
82    var deepestRank = 0;
83    this.inputs.forEach(function(e) {
84      if (e.isVisible() && !e.isBackEdge()) {
85        if (e.source.rank > deepestRank) {
86          deepestRank = e.source.rank;
87        }
88      }
89    });
90    return deepestRank;
91  },
92  areAnyOutputsVisible: function() {
93    var visibleCount = 0;
94    this.outputs.forEach(function(e) { if (e.isVisible()) ++visibleCount; });
95    if (this.outputs.length == visibleCount) return 2;
96    if (visibleCount != 0) return 1;
97    return 0;
98  },
99  setOutputVisibility: function(v) {
100    var result = false;
101    this.outputs.forEach(function(e) {
102      e.visible = v;
103      if (v) {
104        if (!e.target.visible) {
105          e.target.visible = true;
106          result = true;
107        }
108      }
109    });
110    return result;
111  },
112  setInputVisibility: function(i, v) {
113    var edge = this.inputs[i];
114    edge.visible = v;
115    if (v) {
116      if (!edge.source.visible) {
117        edge.source.visible = true;
118        return true;
119      }
120    }
121    return false;
122  },
123  getInputApproach: function(index) {
124    return this.y - MINIMUM_NODE_INPUT_APPROACH -
125      (index % 4) * MINIMUM_EDGE_SEPARATION - DEFAULT_NODE_BUBBLE_RADIUS
126  },
127  getOutputApproach: function(graph, index) {
128    return this.y + this.outputApproach + graph.getNodeHeight(this) +
129      + DEFAULT_NODE_BUBBLE_RADIUS;
130  },
131  getInputX: function(index) {
132    var result = this.getTotalNodeWidth() - (NODE_INPUT_WIDTH / 2) +
133        (index - this.inputs.length + 1) * NODE_INPUT_WIDTH;
134    return result;
135  },
136  getOutputX: function() {
137    return this.getTotalNodeWidth() - (NODE_INPUT_WIDTH / 2);
138  },
139  getFunctionRelativeSourcePosition: function(graph) {
140    return this.pos - graph.sourcePosition;
141  },
142  hasBackEdges: function() {
143    return (this.opcode == "Loop") ||
144      ((this.opcode == "Phi" || this.opcode == "EffectPhi") &&
145       this.inputs[this.inputs.length - 1].source.opcode == "Loop");
146  }
147};
148