Home | History | Annotate | Download | only in compiler
      1 // Copyright 2013 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 #ifndef V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
      6 #define V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
      7 
      8 #include "src/compiler/common-operator.h"
      9 #include "src/compiler/js-operator.h"
     10 #include "src/compiler/opcodes.h"
     11 #include "src/compiler/operator-properties.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace compiler {
     16 
     17 inline bool OperatorProperties::HasValueInput(const Operator* op) {
     18   return OperatorProperties::GetValueInputCount(op) > 0;
     19 }
     20 
     21 inline bool OperatorProperties::HasContextInput(const Operator* op) {
     22   IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
     23   return IrOpcode::IsJsOpcode(opcode);
     24 }
     25 
     26 inline bool OperatorProperties::HasEffectInput(const Operator* op) {
     27   return OperatorProperties::GetEffectInputCount(op) > 0;
     28 }
     29 
     30 inline bool OperatorProperties::HasControlInput(const Operator* op) {
     31   return OperatorProperties::GetControlInputCount(op) > 0;
     32 }
     33 
     34 inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
     35   if (!FLAG_turbo_deoptimization) {
     36     return false;
     37   }
     38 
     39   switch (op->opcode()) {
     40     case IrOpcode::kFrameState:
     41       return true;
     42     case IrOpcode::kJSCallRuntime: {
     43       Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(op);
     44       return Linkage::NeedsFrameState(function);
     45     }
     46 
     47     // Strict equality cannot lazily deoptimize.
     48     case IrOpcode::kJSStrictEqual:
     49     case IrOpcode::kJSStrictNotEqual:
     50       return false;
     51 
     52     // Calls
     53     case IrOpcode::kJSCallFunction:
     54     case IrOpcode::kJSCallConstruct:
     55 
     56     // Compare operations
     57     case IrOpcode::kJSEqual:
     58     case IrOpcode::kJSNotEqual:
     59     case IrOpcode::kJSLessThan:
     60     case IrOpcode::kJSGreaterThan:
     61     case IrOpcode::kJSLessThanOrEqual:
     62     case IrOpcode::kJSGreaterThanOrEqual:
     63 
     64     // Binary operations
     65     case IrOpcode::kJSBitwiseOr:
     66     case IrOpcode::kJSBitwiseXor:
     67     case IrOpcode::kJSBitwiseAnd:
     68     case IrOpcode::kJSShiftLeft:
     69     case IrOpcode::kJSShiftRight:
     70     case IrOpcode::kJSShiftRightLogical:
     71     case IrOpcode::kJSAdd:
     72     case IrOpcode::kJSSubtract:
     73     case IrOpcode::kJSMultiply:
     74     case IrOpcode::kJSDivide:
     75     case IrOpcode::kJSModulus:
     76     case IrOpcode::kJSLoadProperty:
     77     case IrOpcode::kJSStoreProperty:
     78     case IrOpcode::kJSLoadNamed:
     79     case IrOpcode::kJSStoreNamed:
     80       return true;
     81 
     82     default:
     83       return false;
     84   }
     85 }
     86 
     87 inline int OperatorProperties::GetValueInputCount(const Operator* op) {
     88   return op->InputCount();
     89 }
     90 
     91 inline int OperatorProperties::GetContextInputCount(const Operator* op) {
     92   return OperatorProperties::HasContextInput(op) ? 1 : 0;
     93 }
     94 
     95 inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
     96   return OperatorProperties::HasFrameStateInput(op) ? 1 : 0;
     97 }
     98 
     99 inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
    100   if (op->opcode() == IrOpcode::kEffectPhi ||
    101       op->opcode() == IrOpcode::kFinish) {
    102     return OpParameter<int>(op);
    103   }
    104   if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
    105     return 0;  // no effects.
    106   return 1;
    107 }
    108 
    109 inline int OperatorProperties::GetControlInputCount(const Operator* op) {
    110   switch (op->opcode()) {
    111     case IrOpcode::kPhi:
    112     case IrOpcode::kEffectPhi:
    113     case IrOpcode::kControlEffect:
    114       return 1;
    115 #define OPCODE_CASE(x) case IrOpcode::k##x:
    116       CONTROL_OP_LIST(OPCODE_CASE)
    117 #undef OPCODE_CASE
    118       // Control operators are Operator1<int>.
    119       return OpParameter<int>(op);
    120     default:
    121       // Operators that have write effects must have a control
    122       // dependency. Effect dependencies only ensure the correct order of
    123       // write/read operations without consideration of control flow. Without an
    124       // explicit control dependency writes can be float in the schedule too
    125       // early along a path that shouldn't generate a side-effect.
    126       return op->HasProperty(Operator::kNoWrite) ? 0 : 1;
    127   }
    128   return 0;
    129 }
    130 
    131 inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
    132   return GetValueInputCount(op) + GetContextInputCount(op) +
    133          GetFrameStateInputCount(op) + GetEffectInputCount(op) +
    134          GetControlInputCount(op);
    135 }
    136 
    137 // -----------------------------------------------------------------------------
    138 // Output properties.
    139 
    140 inline bool OperatorProperties::HasValueOutput(const Operator* op) {
    141   return GetValueOutputCount(op) > 0;
    142 }
    143 
    144 inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
    145   return op->opcode() == IrOpcode::kStart ||
    146          op->opcode() == IrOpcode::kControlEffect ||
    147          op->opcode() == IrOpcode::kValueEffect ||
    148          (op->opcode() != IrOpcode::kFinish && GetEffectInputCount(op) > 0);
    149 }
    150 
    151 inline bool OperatorProperties::HasControlOutput(const Operator* op) {
    152   IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
    153   return (opcode != IrOpcode::kEnd && IrOpcode::IsControlOpcode(opcode));
    154 }
    155 
    156 
    157 inline int OperatorProperties::GetValueOutputCount(const Operator* op) {
    158   return op->OutputCount();
    159 }
    160 
    161 inline int OperatorProperties::GetEffectOutputCount(const Operator* op) {
    162   return HasEffectOutput(op) ? 1 : 0;
    163 }
    164 
    165 inline int OperatorProperties::GetControlOutputCount(const Operator* node) {
    166   return node->opcode() == IrOpcode::kBranch ? 2 : HasControlOutput(node) ? 1
    167                                                                           : 0;
    168 }
    169 
    170 
    171 inline bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
    172   uint8_t opcode = op->opcode();
    173   return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd ||
    174          opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop ||
    175          opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue ||
    176          opcode == IrOpcode::kIfFalse;
    177 }
    178 
    179 }  // namespace compiler
    180 }  // namespace internal
    181 }  // namespace v8
    182 
    183 #endif  // V8_COMPILER_OPERATOR_PROPERTIES_INL_H_
    184