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