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 HasValueInput(const Operator * op)17inline bool OperatorProperties::HasValueInput(const Operator* op) { 18 return OperatorProperties::GetValueInputCount(op) > 0; 19 } 20 HasContextInput(const Operator * op)21inline bool OperatorProperties::HasContextInput(const Operator* op) { 22 IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode()); 23 return IrOpcode::IsJsOpcode(opcode); 24 } 25 HasEffectInput(const Operator * op)26inline bool OperatorProperties::HasEffectInput(const Operator* op) { 27 return OperatorProperties::GetEffectInputCount(op) > 0; 28 } 29 HasControlInput(const Operator * op)30inline bool OperatorProperties::HasControlInput(const Operator* op) { 31 return OperatorProperties::GetControlInputCount(op) > 0; 32 } 33 HasFrameStateInput(const Operator * op)34inline 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 GetValueInputCount(const Operator * op)87inline int OperatorProperties::GetValueInputCount(const Operator* op) { 88 return op->InputCount(); 89 } 90 GetContextInputCount(const Operator * op)91inline int OperatorProperties::GetContextInputCount(const Operator* op) { 92 return OperatorProperties::HasContextInput(op) ? 1 : 0; 93 } 94 GetFrameStateInputCount(const Operator * op)95inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) { 96 return OperatorProperties::HasFrameStateInput(op) ? 1 : 0; 97 } 98 GetEffectInputCount(const Operator * op)99inline 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 GetControlInputCount(const Operator * op)109inline 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 GetTotalInputCount(const Operator * op)131inline 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 HasValueOutput(const Operator * op)140inline bool OperatorProperties::HasValueOutput(const Operator* op) { 141 return GetValueOutputCount(op) > 0; 142 } 143 HasEffectOutput(const Operator * op)144inline 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 HasControlOutput(const Operator * op)151inline 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 GetValueOutputCount(const Operator * op)157inline int OperatorProperties::GetValueOutputCount(const Operator* op) { 158 return op->OutputCount(); 159 } 160 GetEffectOutputCount(const Operator * op)161inline int OperatorProperties::GetEffectOutputCount(const Operator* op) { 162 return HasEffectOutput(op) ? 1 : 0; 163 } 164 GetControlOutputCount(const Operator * node)165inline int OperatorProperties::GetControlOutputCount(const Operator* node) { 166 return node->opcode() == IrOpcode::kBranch ? 2 : HasControlOutput(node) ? 1 167 : 0; 168 } 169 170 IsBasicBlockBegin(const Operator * op)171inline 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