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 #include "src/compiler/operator-properties.h" 6 7 #include "src/compiler/js-operator.h" 8 #include "src/compiler/linkage.h" 9 #include "src/compiler/opcodes.h" 10 #include "src/runtime/runtime.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace compiler { 15 16 // static HasContextInput(const Operator * op)17bool OperatorProperties::HasContextInput(const Operator* op) { 18 IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode()); 19 return IrOpcode::IsJsOpcode(opcode); 20 } 21 22 // static NeedsExactContext(const Operator * op)23bool OperatorProperties::NeedsExactContext(const Operator* op) { 24 DCHECK(HasContextInput(op)); 25 IrOpcode::Value const opcode = static_cast<IrOpcode::Value>(op->opcode()); 26 switch (opcode) { 27 #define CASE(Name, ...) case IrOpcode::k##Name: 28 // Binary/unary operators, calls and constructor calls only 29 // need the context to generate exceptions or lookup fields 30 // on the native context, so passing any context is fine. 31 JS_SIMPLE_BINOP_LIST(CASE) 32 JS_CALL_OP_LIST(CASE) 33 JS_CONSTRUCT_OP_LIST(CASE) 34 JS_SIMPLE_UNOP_LIST(CASE) 35 #undef CASE 36 case IrOpcode::kJSCloneObject: 37 case IrOpcode::kJSCreate: 38 case IrOpcode::kJSCreateLiteralArray: 39 case IrOpcode::kJSCreateEmptyLiteralArray: 40 case IrOpcode::kJSCreateLiteralObject: 41 case IrOpcode::kJSCreateEmptyLiteralObject: 42 case IrOpcode::kJSCreateArrayFromIterable: 43 case IrOpcode::kJSCreateLiteralRegExp: 44 case IrOpcode::kJSGetTemplateObject: 45 case IrOpcode::kJSForInEnumerate: 46 case IrOpcode::kJSForInNext: 47 case IrOpcode::kJSForInPrepare: 48 case IrOpcode::kJSGeneratorRestoreContext: 49 case IrOpcode::kJSGeneratorRestoreContinuation: 50 case IrOpcode::kJSGeneratorRestoreInputOrDebugPos: 51 case IrOpcode::kJSGeneratorRestoreRegister: 52 case IrOpcode::kJSGetSuperConstructor: 53 case IrOpcode::kJSLoadGlobal: 54 case IrOpcode::kJSLoadMessage: 55 case IrOpcode::kJSStackCheck: 56 case IrOpcode::kJSStoreMessage: 57 case IrOpcode::kJSGetIterator: 58 return false; 59 60 case IrOpcode::kJSCallRuntime: 61 return Runtime::NeedsExactContext(CallRuntimeParametersOf(op).id()); 62 63 case IrOpcode::kJSCreateArguments: 64 // For mapped arguments we need to access slots of context-allocated 65 // variables if there's aliasing with formal parameters. 66 return CreateArgumentsTypeOf(op) == CreateArgumentsType::kMappedArguments; 67 68 case IrOpcode::kJSCreateBlockContext: 69 case IrOpcode::kJSCreateClosure: 70 case IrOpcode::kJSCreateFunctionContext: 71 case IrOpcode::kJSCreateGeneratorObject: 72 case IrOpcode::kJSCreateCatchContext: 73 case IrOpcode::kJSCreateWithContext: 74 case IrOpcode::kJSDebugger: 75 case IrOpcode::kJSDefineKeyedOwnProperty: 76 case IrOpcode::kJSDeleteProperty: 77 case IrOpcode::kJSGeneratorStore: 78 case IrOpcode::kJSGetImportMeta: 79 case IrOpcode::kJSHasProperty: 80 case IrOpcode::kJSHasContextExtension: 81 case IrOpcode::kJSLoadContext: 82 case IrOpcode::kJSLoadModule: 83 case IrOpcode::kJSLoadNamed: 84 case IrOpcode::kJSLoadNamedFromSuper: 85 case IrOpcode::kJSLoadProperty: 86 case IrOpcode::kJSStoreContext: 87 case IrOpcode::kJSDefineKeyedOwnPropertyInLiteral: 88 case IrOpcode::kJSStoreGlobal: 89 case IrOpcode::kJSStoreInArrayLiteral: 90 case IrOpcode::kJSStoreModule: 91 case IrOpcode::kJSSetNamedProperty: 92 case IrOpcode::kJSDefineNamedOwnProperty: 93 case IrOpcode::kJSSetKeyedProperty: 94 return true; 95 96 case IrOpcode::kJSAsyncFunctionEnter: 97 case IrOpcode::kJSAsyncFunctionReject: 98 case IrOpcode::kJSAsyncFunctionResolve: 99 case IrOpcode::kJSCreateArrayIterator: 100 case IrOpcode::kJSCreateAsyncFunctionObject: 101 case IrOpcode::kJSCreateBoundFunction: 102 case IrOpcode::kJSCreateCollectionIterator: 103 case IrOpcode::kJSCreateIterResultObject: 104 case IrOpcode::kJSCreateStringIterator: 105 case IrOpcode::kJSCreateKeyValueArray: 106 case IrOpcode::kJSCreateObject: 107 case IrOpcode::kJSCreatePromise: 108 case IrOpcode::kJSCreateTypedArray: 109 case IrOpcode::kJSCreateArray: 110 case IrOpcode::kJSFulfillPromise: 111 case IrOpcode::kJSObjectIsArray: 112 case IrOpcode::kJSPerformPromiseThen: 113 case IrOpcode::kJSPromiseResolve: 114 case IrOpcode::kJSRegExpTest: 115 case IrOpcode::kJSRejectPromise: 116 case IrOpcode::kJSResolvePromise: 117 // These operators aren't introduced by BytecodeGraphBuilder and 118 // thus we don't bother checking them. If you ever introduce one 119 // of these early in the BytecodeGraphBuilder make sure to check 120 // whether they are context-sensitive. 121 break; 122 123 #define CASE(Name) case IrOpcode::k##Name: 124 // Non-JavaScript operators don't have a notion of "context" 125 COMMON_OP_LIST(CASE) 126 CONTROL_OP_LIST(CASE) 127 MACHINE_OP_LIST(CASE) 128 MACHINE_SIMD_OP_LIST(CASE) 129 SIMPLIFIED_OP_LIST(CASE) 130 break; 131 #undef CASE 132 } 133 UNREACHABLE(); 134 } 135 136 // static HasFrameStateInput(const Operator * op)137bool OperatorProperties::HasFrameStateInput(const Operator* op) { 138 switch (op->opcode()) { 139 case IrOpcode::kCheckpoint: 140 case IrOpcode::kFrameState: 141 return true; 142 case IrOpcode::kJSCallRuntime: { 143 const CallRuntimeParameters& p = CallRuntimeParametersOf(op); 144 return Linkage::NeedsFrameStateInput(p.id()); 145 } 146 147 // Strict equality cannot lazily deoptimize. 148 case IrOpcode::kJSStrictEqual: 149 return false; 150 151 // Generator creation cannot call back into arbitrary JavaScript. 152 case IrOpcode::kJSCreateGeneratorObject: 153 return false; 154 155 // Binary operations 156 case IrOpcode::kJSAdd: 157 case IrOpcode::kJSSubtract: 158 case IrOpcode::kJSMultiply: 159 case IrOpcode::kJSDivide: 160 case IrOpcode::kJSModulus: 161 case IrOpcode::kJSExponentiate: 162 163 // Bitwise operations 164 case IrOpcode::kJSBitwiseOr: 165 case IrOpcode::kJSBitwiseXor: 166 case IrOpcode::kJSBitwiseAnd: 167 168 // Shift operations 169 case IrOpcode::kJSShiftLeft: 170 case IrOpcode::kJSShiftRight: 171 case IrOpcode::kJSShiftRightLogical: 172 173 // Compare operations 174 case IrOpcode::kJSEqual: 175 case IrOpcode::kJSGreaterThan: 176 case IrOpcode::kJSGreaterThanOrEqual: 177 case IrOpcode::kJSLessThan: 178 case IrOpcode::kJSLessThanOrEqual: 179 case IrOpcode::kJSHasProperty: 180 case IrOpcode::kJSHasInPrototypeChain: 181 case IrOpcode::kJSInstanceOf: 182 case IrOpcode::kJSOrdinaryHasInstance: 183 184 // Object operations 185 case IrOpcode::kJSCreate: 186 case IrOpcode::kJSCreateArguments: 187 case IrOpcode::kJSCreateArray: 188 case IrOpcode::kJSCreateTypedArray: 189 case IrOpcode::kJSCreateLiteralArray: 190 case IrOpcode::kJSCreateArrayFromIterable: 191 case IrOpcode::kJSCreateLiteralObject: 192 case IrOpcode::kJSCreateLiteralRegExp: 193 case IrOpcode::kJSCreateObject: 194 case IrOpcode::kJSCloneObject: 195 196 // Property access operations 197 case IrOpcode::kJSDeleteProperty: 198 case IrOpcode::kJSLoadGlobal: 199 case IrOpcode::kJSLoadNamed: 200 case IrOpcode::kJSLoadNamedFromSuper: 201 case IrOpcode::kJSLoadProperty: 202 case IrOpcode::kJSDefineKeyedOwnPropertyInLiteral: 203 case IrOpcode::kJSStoreInArrayLiteral: 204 case IrOpcode::kJSStoreGlobal: 205 case IrOpcode::kJSSetNamedProperty: 206 case IrOpcode::kJSDefineNamedOwnProperty: 207 case IrOpcode::kJSSetKeyedProperty: 208 case IrOpcode::kJSDefineKeyedOwnProperty: 209 210 // Conversions 211 case IrOpcode::kJSToLength: 212 case IrOpcode::kJSToName: 213 case IrOpcode::kJSToNumber: 214 case IrOpcode::kJSToNumberConvertBigInt: 215 case IrOpcode::kJSToNumeric: 216 case IrOpcode::kJSToObject: 217 case IrOpcode::kJSToString: 218 case IrOpcode::kJSParseInt: 219 220 // Call operations 221 case IrOpcode::kJSConstructForwardVarargs: 222 case IrOpcode::kJSConstruct: 223 case IrOpcode::kJSConstructWithArrayLike: 224 case IrOpcode::kJSConstructWithSpread: 225 case IrOpcode::kJSCallForwardVarargs: 226 case IrOpcode::kJSCall: 227 case IrOpcode::kJSCallWithArrayLike: 228 case IrOpcode::kJSCallWithSpread: 229 #if V8_ENABLE_WEBASSEMBLY 230 case IrOpcode::kJSWasmCall: 231 #endif // V8_ENABLE_WEBASSEMBLY 232 233 // Misc operations 234 case IrOpcode::kJSAsyncFunctionEnter: 235 case IrOpcode::kJSAsyncFunctionReject: 236 case IrOpcode::kJSAsyncFunctionResolve: 237 case IrOpcode::kJSForInEnumerate: 238 case IrOpcode::kJSForInNext: 239 case IrOpcode::kJSStackCheck: 240 case IrOpcode::kJSDebugger: 241 case IrOpcode::kJSGetSuperConstructor: 242 case IrOpcode::kJSBitwiseNot: 243 case IrOpcode::kJSDecrement: 244 case IrOpcode::kJSIncrement: 245 case IrOpcode::kJSNegate: 246 case IrOpcode::kJSPromiseResolve: 247 case IrOpcode::kJSRejectPromise: 248 case IrOpcode::kJSResolvePromise: 249 case IrOpcode::kJSPerformPromiseThen: 250 case IrOpcode::kJSObjectIsArray: 251 case IrOpcode::kJSRegExpTest: 252 case IrOpcode::kJSGetImportMeta: 253 254 // Iterator protocol operations 255 case IrOpcode::kJSGetIterator: 256 return true; 257 258 default: 259 return false; 260 } 261 } 262 263 264 // static GetTotalInputCount(const Operator * op)265int OperatorProperties::GetTotalInputCount(const Operator* op) { 266 return op->ValueInputCount() + GetContextInputCount(op) + 267 GetFrameStateInputCount(op) + op->EffectInputCount() + 268 op->ControlInputCount(); 269 } 270 271 272 // static IsBasicBlockBegin(const Operator * op)273bool OperatorProperties::IsBasicBlockBegin(const Operator* op) { 274 Operator::Opcode const opcode = op->opcode(); 275 return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd || 276 opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop || 277 opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue || 278 opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess || 279 opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue || 280 opcode == IrOpcode::kIfDefault; 281 } 282 283 } // namespace compiler 284 } // namespace internal 285 } // namespace v8 286