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
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16// static
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
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
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
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
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