11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/operator-properties.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/compiler/js-operator.h" 81cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h" 101cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace v8 { 131cb0ef41Sopenharmony_cinamespace internal { 141cb0ef41Sopenharmony_cinamespace compiler { 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci// static 171cb0ef41Sopenharmony_cibool OperatorProperties::HasContextInput(const Operator* op) { 181cb0ef41Sopenharmony_ci IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode()); 191cb0ef41Sopenharmony_ci return IrOpcode::IsJsOpcode(opcode); 201cb0ef41Sopenharmony_ci} 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci// static 231cb0ef41Sopenharmony_cibool OperatorProperties::NeedsExactContext(const Operator* op) { 241cb0ef41Sopenharmony_ci DCHECK(HasContextInput(op)); 251cb0ef41Sopenharmony_ci IrOpcode::Value const opcode = static_cast<IrOpcode::Value>(op->opcode()); 261cb0ef41Sopenharmony_ci switch (opcode) { 271cb0ef41Sopenharmony_ci#define CASE(Name, ...) case IrOpcode::k##Name: 281cb0ef41Sopenharmony_ci // Binary/unary operators, calls and constructor calls only 291cb0ef41Sopenharmony_ci // need the context to generate exceptions or lookup fields 301cb0ef41Sopenharmony_ci // on the native context, so passing any context is fine. 311cb0ef41Sopenharmony_ci JS_SIMPLE_BINOP_LIST(CASE) 321cb0ef41Sopenharmony_ci JS_CALL_OP_LIST(CASE) 331cb0ef41Sopenharmony_ci JS_CONSTRUCT_OP_LIST(CASE) 341cb0ef41Sopenharmony_ci JS_SIMPLE_UNOP_LIST(CASE) 351cb0ef41Sopenharmony_ci#undef CASE 361cb0ef41Sopenharmony_ci case IrOpcode::kJSCloneObject: 371cb0ef41Sopenharmony_ci case IrOpcode::kJSCreate: 381cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralArray: 391cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateEmptyLiteralArray: 401cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralObject: 411cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateEmptyLiteralObject: 421cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArrayFromIterable: 431cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralRegExp: 441cb0ef41Sopenharmony_ci case IrOpcode::kJSGetTemplateObject: 451cb0ef41Sopenharmony_ci case IrOpcode::kJSForInEnumerate: 461cb0ef41Sopenharmony_ci case IrOpcode::kJSForInNext: 471cb0ef41Sopenharmony_ci case IrOpcode::kJSForInPrepare: 481cb0ef41Sopenharmony_ci case IrOpcode::kJSGeneratorRestoreContext: 491cb0ef41Sopenharmony_ci case IrOpcode::kJSGeneratorRestoreContinuation: 501cb0ef41Sopenharmony_ci case IrOpcode::kJSGeneratorRestoreInputOrDebugPos: 511cb0ef41Sopenharmony_ci case IrOpcode::kJSGeneratorRestoreRegister: 521cb0ef41Sopenharmony_ci case IrOpcode::kJSGetSuperConstructor: 531cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadGlobal: 541cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadMessage: 551cb0ef41Sopenharmony_ci case IrOpcode::kJSStackCheck: 561cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreMessage: 571cb0ef41Sopenharmony_ci case IrOpcode::kJSGetIterator: 581cb0ef41Sopenharmony_ci return false; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci case IrOpcode::kJSCallRuntime: 611cb0ef41Sopenharmony_ci return Runtime::NeedsExactContext(CallRuntimeParametersOf(op).id()); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArguments: 641cb0ef41Sopenharmony_ci // For mapped arguments we need to access slots of context-allocated 651cb0ef41Sopenharmony_ci // variables if there's aliasing with formal parameters. 661cb0ef41Sopenharmony_ci return CreateArgumentsTypeOf(op) == CreateArgumentsType::kMappedArguments; 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateBlockContext: 691cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateClosure: 701cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateFunctionContext: 711cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateGeneratorObject: 721cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateCatchContext: 731cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateWithContext: 741cb0ef41Sopenharmony_ci case IrOpcode::kJSDebugger: 751cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineKeyedOwnProperty: 761cb0ef41Sopenharmony_ci case IrOpcode::kJSDeleteProperty: 771cb0ef41Sopenharmony_ci case IrOpcode::kJSGeneratorStore: 781cb0ef41Sopenharmony_ci case IrOpcode::kJSGetImportMeta: 791cb0ef41Sopenharmony_ci case IrOpcode::kJSHasProperty: 801cb0ef41Sopenharmony_ci case IrOpcode::kJSHasContextExtension: 811cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadContext: 821cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadModule: 831cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadNamed: 841cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadNamedFromSuper: 851cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadProperty: 861cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreContext: 871cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineKeyedOwnPropertyInLiteral: 881cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreGlobal: 891cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreInArrayLiteral: 901cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreModule: 911cb0ef41Sopenharmony_ci case IrOpcode::kJSSetNamedProperty: 921cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineNamedOwnProperty: 931cb0ef41Sopenharmony_ci case IrOpcode::kJSSetKeyedProperty: 941cb0ef41Sopenharmony_ci return true; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionEnter: 971cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionReject: 981cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionResolve: 991cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArrayIterator: 1001cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateAsyncFunctionObject: 1011cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateBoundFunction: 1021cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateCollectionIterator: 1031cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateIterResultObject: 1041cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateStringIterator: 1051cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateKeyValueArray: 1061cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateObject: 1071cb0ef41Sopenharmony_ci case IrOpcode::kJSCreatePromise: 1081cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateTypedArray: 1091cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArray: 1101cb0ef41Sopenharmony_ci case IrOpcode::kJSFulfillPromise: 1111cb0ef41Sopenharmony_ci case IrOpcode::kJSObjectIsArray: 1121cb0ef41Sopenharmony_ci case IrOpcode::kJSPerformPromiseThen: 1131cb0ef41Sopenharmony_ci case IrOpcode::kJSPromiseResolve: 1141cb0ef41Sopenharmony_ci case IrOpcode::kJSRegExpTest: 1151cb0ef41Sopenharmony_ci case IrOpcode::kJSRejectPromise: 1161cb0ef41Sopenharmony_ci case IrOpcode::kJSResolvePromise: 1171cb0ef41Sopenharmony_ci // These operators aren't introduced by BytecodeGraphBuilder and 1181cb0ef41Sopenharmony_ci // thus we don't bother checking them. If you ever introduce one 1191cb0ef41Sopenharmony_ci // of these early in the BytecodeGraphBuilder make sure to check 1201cb0ef41Sopenharmony_ci // whether they are context-sensitive. 1211cb0ef41Sopenharmony_ci break; 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci#define CASE(Name) case IrOpcode::k##Name: 1241cb0ef41Sopenharmony_ci // Non-JavaScript operators don't have a notion of "context" 1251cb0ef41Sopenharmony_ci COMMON_OP_LIST(CASE) 1261cb0ef41Sopenharmony_ci CONTROL_OP_LIST(CASE) 1271cb0ef41Sopenharmony_ci MACHINE_OP_LIST(CASE) 1281cb0ef41Sopenharmony_ci MACHINE_SIMD_OP_LIST(CASE) 1291cb0ef41Sopenharmony_ci SIMPLIFIED_OP_LIST(CASE) 1301cb0ef41Sopenharmony_ci break; 1311cb0ef41Sopenharmony_ci#undef CASE 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci UNREACHABLE(); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci// static 1371cb0ef41Sopenharmony_cibool OperatorProperties::HasFrameStateInput(const Operator* op) { 1381cb0ef41Sopenharmony_ci switch (op->opcode()) { 1391cb0ef41Sopenharmony_ci case IrOpcode::kCheckpoint: 1401cb0ef41Sopenharmony_ci case IrOpcode::kFrameState: 1411cb0ef41Sopenharmony_ci return true; 1421cb0ef41Sopenharmony_ci case IrOpcode::kJSCallRuntime: { 1431cb0ef41Sopenharmony_ci const CallRuntimeParameters& p = CallRuntimeParametersOf(op); 1441cb0ef41Sopenharmony_ci return Linkage::NeedsFrameStateInput(p.id()); 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // Strict equality cannot lazily deoptimize. 1481cb0ef41Sopenharmony_ci case IrOpcode::kJSStrictEqual: 1491cb0ef41Sopenharmony_ci return false; 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci // Generator creation cannot call back into arbitrary JavaScript. 1521cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateGeneratorObject: 1531cb0ef41Sopenharmony_ci return false; 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci // Binary operations 1561cb0ef41Sopenharmony_ci case IrOpcode::kJSAdd: 1571cb0ef41Sopenharmony_ci case IrOpcode::kJSSubtract: 1581cb0ef41Sopenharmony_ci case IrOpcode::kJSMultiply: 1591cb0ef41Sopenharmony_ci case IrOpcode::kJSDivide: 1601cb0ef41Sopenharmony_ci case IrOpcode::kJSModulus: 1611cb0ef41Sopenharmony_ci case IrOpcode::kJSExponentiate: 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci // Bitwise operations 1641cb0ef41Sopenharmony_ci case IrOpcode::kJSBitwiseOr: 1651cb0ef41Sopenharmony_ci case IrOpcode::kJSBitwiseXor: 1661cb0ef41Sopenharmony_ci case IrOpcode::kJSBitwiseAnd: 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci // Shift operations 1691cb0ef41Sopenharmony_ci case IrOpcode::kJSShiftLeft: 1701cb0ef41Sopenharmony_ci case IrOpcode::kJSShiftRight: 1711cb0ef41Sopenharmony_ci case IrOpcode::kJSShiftRightLogical: 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci // Compare operations 1741cb0ef41Sopenharmony_ci case IrOpcode::kJSEqual: 1751cb0ef41Sopenharmony_ci case IrOpcode::kJSGreaterThan: 1761cb0ef41Sopenharmony_ci case IrOpcode::kJSGreaterThanOrEqual: 1771cb0ef41Sopenharmony_ci case IrOpcode::kJSLessThan: 1781cb0ef41Sopenharmony_ci case IrOpcode::kJSLessThanOrEqual: 1791cb0ef41Sopenharmony_ci case IrOpcode::kJSHasProperty: 1801cb0ef41Sopenharmony_ci case IrOpcode::kJSHasInPrototypeChain: 1811cb0ef41Sopenharmony_ci case IrOpcode::kJSInstanceOf: 1821cb0ef41Sopenharmony_ci case IrOpcode::kJSOrdinaryHasInstance: 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci // Object operations 1851cb0ef41Sopenharmony_ci case IrOpcode::kJSCreate: 1861cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArguments: 1871cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArray: 1881cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateTypedArray: 1891cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralArray: 1901cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateArrayFromIterable: 1911cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralObject: 1921cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateLiteralRegExp: 1931cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateObject: 1941cb0ef41Sopenharmony_ci case IrOpcode::kJSCloneObject: 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci // Property access operations 1971cb0ef41Sopenharmony_ci case IrOpcode::kJSDeleteProperty: 1981cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadGlobal: 1991cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadNamed: 2001cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadNamedFromSuper: 2011cb0ef41Sopenharmony_ci case IrOpcode::kJSLoadProperty: 2021cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineKeyedOwnPropertyInLiteral: 2031cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreInArrayLiteral: 2041cb0ef41Sopenharmony_ci case IrOpcode::kJSStoreGlobal: 2051cb0ef41Sopenharmony_ci case IrOpcode::kJSSetNamedProperty: 2061cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineNamedOwnProperty: 2071cb0ef41Sopenharmony_ci case IrOpcode::kJSSetKeyedProperty: 2081cb0ef41Sopenharmony_ci case IrOpcode::kJSDefineKeyedOwnProperty: 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci // Conversions 2111cb0ef41Sopenharmony_ci case IrOpcode::kJSToLength: 2121cb0ef41Sopenharmony_ci case IrOpcode::kJSToName: 2131cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumber: 2141cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumberConvertBigInt: 2151cb0ef41Sopenharmony_ci case IrOpcode::kJSToNumeric: 2161cb0ef41Sopenharmony_ci case IrOpcode::kJSToObject: 2171cb0ef41Sopenharmony_ci case IrOpcode::kJSToString: 2181cb0ef41Sopenharmony_ci case IrOpcode::kJSParseInt: 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci // Call operations 2211cb0ef41Sopenharmony_ci case IrOpcode::kJSConstructForwardVarargs: 2221cb0ef41Sopenharmony_ci case IrOpcode::kJSConstruct: 2231cb0ef41Sopenharmony_ci case IrOpcode::kJSConstructWithArrayLike: 2241cb0ef41Sopenharmony_ci case IrOpcode::kJSConstructWithSpread: 2251cb0ef41Sopenharmony_ci case IrOpcode::kJSCallForwardVarargs: 2261cb0ef41Sopenharmony_ci case IrOpcode::kJSCall: 2271cb0ef41Sopenharmony_ci case IrOpcode::kJSCallWithArrayLike: 2281cb0ef41Sopenharmony_ci case IrOpcode::kJSCallWithSpread: 2291cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2301cb0ef41Sopenharmony_ci case IrOpcode::kJSWasmCall: 2311cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci // Misc operations 2341cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionEnter: 2351cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionReject: 2361cb0ef41Sopenharmony_ci case IrOpcode::kJSAsyncFunctionResolve: 2371cb0ef41Sopenharmony_ci case IrOpcode::kJSForInEnumerate: 2381cb0ef41Sopenharmony_ci case IrOpcode::kJSForInNext: 2391cb0ef41Sopenharmony_ci case IrOpcode::kJSStackCheck: 2401cb0ef41Sopenharmony_ci case IrOpcode::kJSDebugger: 2411cb0ef41Sopenharmony_ci case IrOpcode::kJSGetSuperConstructor: 2421cb0ef41Sopenharmony_ci case IrOpcode::kJSBitwiseNot: 2431cb0ef41Sopenharmony_ci case IrOpcode::kJSDecrement: 2441cb0ef41Sopenharmony_ci case IrOpcode::kJSIncrement: 2451cb0ef41Sopenharmony_ci case IrOpcode::kJSNegate: 2461cb0ef41Sopenharmony_ci case IrOpcode::kJSPromiseResolve: 2471cb0ef41Sopenharmony_ci case IrOpcode::kJSRejectPromise: 2481cb0ef41Sopenharmony_ci case IrOpcode::kJSResolvePromise: 2491cb0ef41Sopenharmony_ci case IrOpcode::kJSPerformPromiseThen: 2501cb0ef41Sopenharmony_ci case IrOpcode::kJSObjectIsArray: 2511cb0ef41Sopenharmony_ci case IrOpcode::kJSRegExpTest: 2521cb0ef41Sopenharmony_ci case IrOpcode::kJSGetImportMeta: 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci // Iterator protocol operations 2551cb0ef41Sopenharmony_ci case IrOpcode::kJSGetIterator: 2561cb0ef41Sopenharmony_ci return true; 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci default: 2591cb0ef41Sopenharmony_ci return false; 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci} 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci// static 2651cb0ef41Sopenharmony_ciint OperatorProperties::GetTotalInputCount(const Operator* op) { 2661cb0ef41Sopenharmony_ci return op->ValueInputCount() + GetContextInputCount(op) + 2671cb0ef41Sopenharmony_ci GetFrameStateInputCount(op) + op->EffectInputCount() + 2681cb0ef41Sopenharmony_ci op->ControlInputCount(); 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci// static 2731cb0ef41Sopenharmony_cibool OperatorProperties::IsBasicBlockBegin(const Operator* op) { 2741cb0ef41Sopenharmony_ci Operator::Opcode const opcode = op->opcode(); 2751cb0ef41Sopenharmony_ci return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd || 2761cb0ef41Sopenharmony_ci opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop || 2771cb0ef41Sopenharmony_ci opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue || 2781cb0ef41Sopenharmony_ci opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess || 2791cb0ef41Sopenharmony_ci opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue || 2801cb0ef41Sopenharmony_ci opcode == IrOpcode::kIfDefault; 2811cb0ef41Sopenharmony_ci} 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci} // namespace compiler 2841cb0ef41Sopenharmony_ci} // namespace internal 2851cb0ef41Sopenharmony_ci} // namespace v8 286