operator-properties.cc 9.49 KB
Newer Older
1
// Copyright 2014 the V8 project authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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 12 13 14 15

namespace v8 {
namespace internal {
namespace compiler {

16 17
// static
bool OperatorProperties::HasContextInput(const Operator* op) {
18 19 20 21
  IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
  return IrOpcode::IsJsOpcode(opcode);
}

22 23 24 25 26
// static
bool OperatorProperties::NeedsExactContext(const Operator* op) {
  DCHECK(HasContextInput(op));
  IrOpcode::Value const opcode = static_cast<IrOpcode::Value>(op->opcode());
  switch (opcode) {
27
#define CASE(Name, ...) case IrOpcode::k##Name:
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
    // 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:
44
    case IrOpcode::kJSGetTemplateObject:
45 46 47 48 49 50 51 52 53 54 55 56
    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:
57
    case IrOpcode::kJSGetIterator:
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
      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:
75
    case IrOpcode::kJSDefineKeyedOwnProperty:
76 77
    case IrOpcode::kJSDeleteProperty:
    case IrOpcode::kJSGeneratorStore:
78
    case IrOpcode::kJSGetImportMeta:
79
    case IrOpcode::kJSHasProperty:
80
    case IrOpcode::kJSHasContextExtension:
81 82 83
    case IrOpcode::kJSLoadContext:
    case IrOpcode::kJSLoadModule:
    case IrOpcode::kJSLoadNamed:
84
    case IrOpcode::kJSLoadNamedFromSuper:
85 86
    case IrOpcode::kJSLoadProperty:
    case IrOpcode::kJSStoreContext:
87
    case IrOpcode::kJSDefineKeyedOwnPropertyInLiteral:
88
    case IrOpcode::kJSStoreGlobal:
89 90
    case IrOpcode::kJSStoreInArrayLiteral:
    case IrOpcode::kJSStoreModule:
91 92 93
    case IrOpcode::kJSSetNamedProperty:
    case IrOpcode::kJSDefineNamedOwnProperty:
    case IrOpcode::kJSSetKeyedProperty:
94 95
      return true;

96 97 98
    case IrOpcode::kJSAsyncFunctionEnter:
    case IrOpcode::kJSAsyncFunctionReject:
    case IrOpcode::kJSAsyncFunctionResolve:
99
    case IrOpcode::kJSCreateArrayIterator:
100
    case IrOpcode::kJSCreateAsyncFunctionObject:
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    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();
}
135 136

// static
137
bool 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 148
    // Strict equality cannot lazily deoptimize.
    case IrOpcode::kJSStrictEqual:
149
      return false;
150

151 152 153 154
    // Generator creation cannot call back into arbitrary JavaScript.
    case IrOpcode::kJSCreateGeneratorObject:
      return false;

155
    // Binary operations
156 157
    case IrOpcode::kJSAdd:
    case IrOpcode::kJSSubtract:
158
    case IrOpcode::kJSMultiply:
159 160
    case IrOpcode::kJSDivide:
    case IrOpcode::kJSModulus:
161
    case IrOpcode::kJSExponentiate:
162

163 164 165 166 167
    // Bitwise operations
    case IrOpcode::kJSBitwiseOr:
    case IrOpcode::kJSBitwiseXor:
    case IrOpcode::kJSBitwiseAnd:

168 169 170 171 172
    // Shift operations
    case IrOpcode::kJSShiftLeft:
    case IrOpcode::kJSShiftRight:
    case IrOpcode::kJSShiftRightLogical:

173 174
    // Compare operations
    case IrOpcode::kJSEqual:
175 176 177 178
    case IrOpcode::kJSGreaterThan:
    case IrOpcode::kJSGreaterThanOrEqual:
    case IrOpcode::kJSLessThan:
    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 198
    case IrOpcode::kJSDeleteProperty:
    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 206 207 208
    case IrOpcode::kJSSetNamedProperty:
    case IrOpcode::kJSDefineNamedOwnProperty:
    case IrOpcode::kJSSetKeyedProperty:
    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 217
    case IrOpcode::kJSToObject:
    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 235 236
    case IrOpcode::kJSAsyncFunctionEnter:
    case IrOpcode::kJSAsyncFunctionReject:
    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 244
    case IrOpcode::kJSDecrement:
    case IrOpcode::kJSIncrement:
245
    case IrOpcode::kJSNegate:
246
    case IrOpcode::kJSPromiseResolve:
247 248
    case IrOpcode::kJSRejectPromise:
    case IrOpcode::kJSResolvePromise:
249
    case IrOpcode::kJSPerformPromiseThen:
250
    case IrOpcode::kJSObjectIsArray:
251
    case IrOpcode::kJSRegExpTest:
252
    case IrOpcode::kJSGetImportMeta:
253 254 255

    // Iterator protocol operations
    case IrOpcode::kJSGetIterator:
256
      return true;
257

258
    default:
259
      return false;
260 261
  }
}
262

263

264 265
// static
int OperatorProperties::GetTotalInputCount(const Operator* op) {
266 267 268
  return op->ValueInputCount() + GetContextInputCount(op) +
         GetFrameStateInputCount(op) + op->EffectInputCount() +
         op->ControlInputCount();
269 270
}

271

272 273 274
// static
bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
  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 279
         opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess ||
         opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue ||
280
         opcode == IrOpcode::kIfDefault;
281 282
}

283 284 285
}  // namespace compiler
}  // namespace internal
}  // namespace v8