// 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::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::kJSStoreGlobal: case IrOpcode::kJSStoreMessage: 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::kJSHasProperty: case IrOpcode::kJSLoadContext: case IrOpcode::kJSLoadModule: case IrOpcode::kJSLoadNamed: case IrOpcode::kJSLoadProperty: case IrOpcode::kJSStoreContext: case IrOpcode::kJSStoreDataPropertyInLiteral: 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::kJSLoadNamed: case IrOpcode::kJSStoreNamed: case IrOpcode::kJSLoadProperty: case IrOpcode::kJSStoreProperty: case IrOpcode::kJSLoadGlobal: case IrOpcode::kJSStoreGlobal: case IrOpcode::kJSStoreNamedOwn: case IrOpcode::kJSStoreDataPropertyInLiteral: case IrOpcode::kJSDeleteProperty: // 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: 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