Home | History | Annotate | Download | only in turbolizer
      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 
      5 var TYPE_HEIGHT = 25;
      6 var DEFAULT_NODE_BUBBLE_RADIUS = 12;
      7 var NODE_INPUT_WIDTH = 50;
      8 var MINIMUM_NODE_INPUT_APPROACH = 15 + 2 * DEFAULT_NODE_BUBBLE_RADIUS;
      9 var MINIMUM_NODE_OUTPUT_APPROACH = 15;
     10 
     11 function isNodeInitiallyVisible(node) {
     12   return node.cfg;
     13 }
     14 
     15 var 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