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