| // Copyright 2014 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "src/compiler/operator-properties.h" | 
 |  | 
 | #include "src/compiler/js-operator.h" | 
 | #include "src/compiler/linkage.h" | 
 | #include "src/compiler/opcodes.h" | 
 | #include "src/runtime/runtime.h" | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 | namespace compiler { | 
 |  | 
 | // static | 
 | bool OperatorProperties::HasContextInput(const Operator* op) { | 
 |   IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode()); | 
 |   return IrOpcode::IsJsOpcode(opcode); | 
 | } | 
 |  | 
 | // static | 
 | bool OperatorProperties::NeedsExactContext(const Operator* op) { | 
 |   DCHECK(HasContextInput(op)); | 
 |   IrOpcode::Value const opcode = static_cast<IrOpcode::Value>(op->opcode()); | 
 |   switch (opcode) { | 
 | #define CASE(Name, ...) case IrOpcode::k##Name: | 
 |     // Binary/unary operators, calls and constructor calls only | 
 |     // need the context to generate exceptions or lookup fields | 
 |     // on the native context, so passing any context is fine. | 
 |     JS_SIMPLE_BINOP_LIST(CASE) | 
 |     JS_CALL_OP_LIST(CASE) | 
 |     JS_CONSTRUCT_OP_LIST(CASE) | 
 |     JS_SIMPLE_UNOP_LIST(CASE) | 
 | #undef CASE | 
 |     case IrOpcode::kJSCloneObject: | 
 |     case IrOpcode::kJSCreate: | 
 |     case IrOpcode::kJSCreateLiteralArray: | 
 |     case IrOpcode::kJSCreateEmptyLiteralArray: | 
 |     case IrOpcode::kJSCreateLiteralObject: | 
 |     case IrOpcode::kJSCreateEmptyLiteralObject: | 
 |     case IrOpcode::kJSCreateArrayFromIterable: | 
 |     case IrOpcode::kJSCreateLiteralRegExp: | 
 |     case IrOpcode::kJSGetTemplateObject: | 
 |     case IrOpcode::kJSForInEnumerate: | 
 |     case IrOpcode::kJSForInNext: | 
 |     case IrOpcode::kJSForInPrepare: | 
 |     case IrOpcode::kJSGeneratorRestoreContext: | 
 |     case IrOpcode::kJSGeneratorRestoreContinuation: | 
 |     case IrOpcode::kJSGeneratorRestoreInputOrDebugPos: | 
 |     case IrOpcode::kJSGeneratorRestoreRegister: | 
 |     case IrOpcode::kJSGetSuperConstructor: | 
 |     case IrOpcode::kJSLoadGlobal: | 
 |     case IrOpcode::kJSLoadMessage: | 
 |     case IrOpcode::kJSStackCheck: | 
 |     case IrOpcode::kJSStoreMessage: | 
 |     case IrOpcode::kJSGetIterator: | 
 |       return false; | 
 |  | 
 |     case IrOpcode::kJSCallRuntime: | 
 |       return Runtime::NeedsExactContext(CallRuntimeParametersOf(op).id()); | 
 |  | 
 |     case IrOpcode::kJSCreateArguments: | 
 |       // For mapped arguments we need to access slots of context-allocated | 
 |       // variables if there's aliasing with formal parameters. | 
 |       return CreateArgumentsTypeOf(op) == CreateArgumentsType::kMappedArguments; | 
 |  | 
 |     case IrOpcode::kJSCreateBlockContext: | 
 |     case IrOpcode::kJSCreateClosure: | 
 |     case IrOpcode::kJSCreateFunctionContext: | 
 |     case IrOpcode::kJSCreateGeneratorObject: | 
 |     case IrOpcode::kJSCreateCatchContext: | 
 |     case IrOpcode::kJSCreateWithContext: | 
 |     case IrOpcode::kJSDebugger: | 
 |     case IrOpcode::kJSDeleteProperty: | 
 |     case IrOpcode::kJSGeneratorStore: | 
 |     case IrOpcode::kJSGetImportMeta: | 
 |     case IrOpcode::kJSHasProperty: | 
 |     case IrOpcode::kJSHasContextExtension: | 
 |     case IrOpcode::kJSLoadContext: | 
 |     case IrOpcode::kJSLoadModule: | 
 |     case IrOpcode::kJSLoadNamed: | 
 |     case IrOpcode::kJSLoadNamedFromSuper: | 
 |     case IrOpcode::kJSLoadProperty: | 
 |     case IrOpcode::kJSStoreContext: | 
 |     case IrOpcode::kJSStoreDataPropertyInLiteral: | 
 |     case IrOpcode::kJSStoreGlobal: | 
 |     case IrOpcode::kJSStoreInArrayLiteral: | 
 |     case IrOpcode::kJSStoreModule: | 
 |     case IrOpcode::kJSStoreNamed: | 
 |     case IrOpcode::kJSStoreNamedOwn: | 
 |     case IrOpcode::kJSStoreProperty: | 
 |       return true; | 
 |  | 
 |     case IrOpcode::kJSAsyncFunctionEnter: | 
 |     case IrOpcode::kJSAsyncFunctionReject: | 
 |     case IrOpcode::kJSAsyncFunctionResolve: | 
 |     case IrOpcode::kJSCreateArrayIterator: | 
 |     case IrOpcode::kJSCreateAsyncFunctionObject: | 
 |     case IrOpcode::kJSCreateBoundFunction: | 
 |     case IrOpcode::kJSCreateCollectionIterator: | 
 |     case IrOpcode::kJSCreateIterResultObject: | 
 |     case IrOpcode::kJSCreateStringIterator: | 
 |     case IrOpcode::kJSCreateKeyValueArray: | 
 |     case IrOpcode::kJSCreateObject: | 
 |     case IrOpcode::kJSCreatePromise: | 
 |     case IrOpcode::kJSCreateTypedArray: | 
 |     case IrOpcode::kJSCreateArray: | 
 |     case IrOpcode::kJSFulfillPromise: | 
 |     case IrOpcode::kJSObjectIsArray: | 
 |     case IrOpcode::kJSPerformPromiseThen: | 
 |     case IrOpcode::kJSPromiseResolve: | 
 |     case IrOpcode::kJSRegExpTest: | 
 |     case IrOpcode::kJSRejectPromise: | 
 |     case IrOpcode::kJSResolvePromise: | 
 |       // These operators aren't introduced by BytecodeGraphBuilder and | 
 |       // thus we don't bother checking them. If you ever introduce one | 
 |       // of these early in the BytecodeGraphBuilder make sure to check | 
 |       // whether they are context-sensitive. | 
 |       break; | 
 |  | 
 | #define CASE(Name) case IrOpcode::k##Name: | 
 |       // Non-JavaScript operators don't have a notion of "context" | 
 |       COMMON_OP_LIST(CASE) | 
 |       CONTROL_OP_LIST(CASE) | 
 |       MACHINE_OP_LIST(CASE) | 
 |       MACHINE_SIMD_OP_LIST(CASE) | 
 |       SIMPLIFIED_OP_LIST(CASE) | 
 |       break; | 
 | #undef CASE | 
 |   } | 
 |   UNREACHABLE(); | 
 | } | 
 |  | 
 | // static | 
 | bool OperatorProperties::HasFrameStateInput(const Operator* op) { | 
 |   switch (op->opcode()) { | 
 |     case IrOpcode::kCheckpoint: | 
 |     case IrOpcode::kFrameState: | 
 |       return true; | 
 |     case IrOpcode::kJSCallRuntime: { | 
 |       const CallRuntimeParameters& p = CallRuntimeParametersOf(op); | 
 |       return Linkage::NeedsFrameStateInput(p.id()); | 
 |     } | 
 |  | 
 |     // Strict equality cannot lazily deoptimize. | 
 |     case IrOpcode::kJSStrictEqual: | 
 |       return false; | 
 |  | 
 |     // Generator creation cannot call back into arbitrary JavaScript. | 
 |     case IrOpcode::kJSCreateGeneratorObject: | 
 |       return false; | 
 |  | 
 |     // Binary operations | 
 |     case IrOpcode::kJSAdd: | 
 |     case IrOpcode::kJSSubtract: | 
 |     case IrOpcode::kJSMultiply: | 
 |     case IrOpcode::kJSDivide: | 
 |     case IrOpcode::kJSModulus: | 
 |     case IrOpcode::kJSExponentiate: | 
 |  | 
 |     // Bitwise operations | 
 |     case IrOpcode::kJSBitwiseOr: | 
 |     case IrOpcode::kJSBitwiseXor: | 
 |     case IrOpcode::kJSBitwiseAnd: | 
 |  | 
 |     // Shift operations | 
 |     case IrOpcode::kJSShiftLeft: | 
 |     case IrOpcode::kJSShiftRight: | 
 |     case IrOpcode::kJSShiftRightLogical: | 
 |  | 
 |     // Compare operations | 
 |     case IrOpcode::kJSEqual: | 
 |     case IrOpcode::kJSGreaterThan: | 
 |     case IrOpcode::kJSGreaterThanOrEqual: | 
 |     case IrOpcode::kJSLessThan: | 
 |     case IrOpcode::kJSLessThanOrEqual: | 
 |     case IrOpcode::kJSHasProperty: | 
 |     case IrOpcode::kJSHasInPrototypeChain: | 
 |     case IrOpcode::kJSInstanceOf: | 
 |     case IrOpcode::kJSOrdinaryHasInstance: | 
 |  | 
 |     // Object operations | 
 |     case IrOpcode::kJSCreate: | 
 |     case IrOpcode::kJSCreateArguments: | 
 |     case IrOpcode::kJSCreateArray: | 
 |     case IrOpcode::kJSCreateTypedArray: | 
 |     case IrOpcode::kJSCreateLiteralArray: | 
 |     case IrOpcode::kJSCreateArrayFromIterable: | 
 |     case IrOpcode::kJSCreateLiteralObject: | 
 |     case IrOpcode::kJSCreateLiteralRegExp: | 
 |     case IrOpcode::kJSCreateObject: | 
 |     case IrOpcode::kJSCloneObject: | 
 |  | 
 |     // Property access operations | 
 |     case IrOpcode::kJSDeleteProperty: | 
 |     case IrOpcode::kJSLoadGlobal: | 
 |     case IrOpcode::kJSLoadNamed: | 
 |     case IrOpcode::kJSLoadNamedFromSuper: | 
 |     case IrOpcode::kJSLoadProperty: | 
 |     case IrOpcode::kJSStoreDataPropertyInLiteral: | 
 |     case IrOpcode::kJSStoreInArrayLiteral: | 
 |     case IrOpcode::kJSStoreGlobal: | 
 |     case IrOpcode::kJSStoreNamed: | 
 |     case IrOpcode::kJSStoreNamedOwn: | 
 |     case IrOpcode::kJSStoreProperty: | 
 |  | 
 |     // Conversions | 
 |     case IrOpcode::kJSToLength: | 
 |     case IrOpcode::kJSToName: | 
 |     case IrOpcode::kJSToNumber: | 
 |     case IrOpcode::kJSToNumberConvertBigInt: | 
 |     case IrOpcode::kJSToNumeric: | 
 |     case IrOpcode::kJSToObject: | 
 |     case IrOpcode::kJSToString: | 
 |     case IrOpcode::kJSParseInt: | 
 |  | 
 |     // Call operations | 
 |     case IrOpcode::kJSConstructForwardVarargs: | 
 |     case IrOpcode::kJSConstruct: | 
 |     case IrOpcode::kJSConstructWithArrayLike: | 
 |     case IrOpcode::kJSConstructWithSpread: | 
 |     case IrOpcode::kJSCallForwardVarargs: | 
 |     case IrOpcode::kJSCall: | 
 |     case IrOpcode::kJSCallWithArrayLike: | 
 |     case IrOpcode::kJSCallWithSpread: | 
 |  | 
 |     // Misc operations | 
 |     case IrOpcode::kJSAsyncFunctionEnter: | 
 |     case IrOpcode::kJSAsyncFunctionReject: | 
 |     case IrOpcode::kJSAsyncFunctionResolve: | 
 |     case IrOpcode::kJSForInEnumerate: | 
 |     case IrOpcode::kJSForInNext: | 
 |     case IrOpcode::kJSStackCheck: | 
 |     case IrOpcode::kJSDebugger: | 
 |     case IrOpcode::kJSGetSuperConstructor: | 
 |     case IrOpcode::kJSBitwiseNot: | 
 |     case IrOpcode::kJSDecrement: | 
 |     case IrOpcode::kJSIncrement: | 
 |     case IrOpcode::kJSNegate: | 
 |     case IrOpcode::kJSPromiseResolve: | 
 |     case IrOpcode::kJSRejectPromise: | 
 |     case IrOpcode::kJSResolvePromise: | 
 |     case IrOpcode::kJSPerformPromiseThen: | 
 |     case IrOpcode::kJSObjectIsArray: | 
 |     case IrOpcode::kJSRegExpTest: | 
 |     case IrOpcode::kJSGetImportMeta: | 
 |  | 
 |     // Iterator protocol operations | 
 |     case IrOpcode::kJSGetIterator: | 
 |       return true; | 
 |  | 
 |     default: | 
 |       return false; | 
 |   } | 
 | } | 
 |  | 
 |  | 
 | // static | 
 | int OperatorProperties::GetTotalInputCount(const Operator* op) { | 
 |   return op->ValueInputCount() + GetContextInputCount(op) + | 
 |          GetFrameStateInputCount(op) + op->EffectInputCount() + | 
 |          op->ControlInputCount(); | 
 | } | 
 |  | 
 |  | 
 | // static | 
 | bool OperatorProperties::IsBasicBlockBegin(const Operator* op) { | 
 |   Operator::Opcode const opcode = op->opcode(); | 
 |   return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd || | 
 |          opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop || | 
 |          opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue || | 
 |          opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess || | 
 |          opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue || | 
 |          opcode == IrOpcode::kIfDefault; | 
 | } | 
 |  | 
 | }  // namespace compiler | 
 | }  // namespace internal | 
 | }  // namespace v8 |