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
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15// static
16bool OperatorProperties::HasContextInput(const Operator* op) {
17  IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
18  return IrOpcode::IsJsOpcode(opcode);
19}
20
21
22// static
23int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
24  switch (op->opcode()) {
25    case IrOpcode::kCheckpoint:
26    case IrOpcode::kFrameState:
27      return 1;
28    case IrOpcode::kJSCallRuntime: {
29      const CallRuntimeParameters& p = CallRuntimeParametersOf(op);
30      return Linkage::NeedsFrameStateInput(p.id()) ? 1 : 0;
31    }
32
33    // Strict equality cannot lazily deoptimize.
34    case IrOpcode::kJSStrictEqual:
35    case IrOpcode::kJSStrictNotEqual:
36      return 0;
37
38    // Compare operations
39    case IrOpcode::kJSEqual:
40    case IrOpcode::kJSNotEqual:
41    case IrOpcode::kJSHasProperty:
42    case IrOpcode::kJSInstanceOf:
43
44    // Object operations
45    case IrOpcode::kJSCreate:
46    case IrOpcode::kJSCreateArguments:
47    case IrOpcode::kJSCreateArray:
48    case IrOpcode::kJSCreateLiteralArray:
49    case IrOpcode::kJSCreateLiteralObject:
50    case IrOpcode::kJSCreateLiteralRegExp:
51
52    // Property access operations
53    case IrOpcode::kJSLoadNamed:
54    case IrOpcode::kJSStoreNamed:
55    case IrOpcode::kJSLoadProperty:
56    case IrOpcode::kJSStoreProperty:
57    case IrOpcode::kJSLoadGlobal:
58    case IrOpcode::kJSStoreGlobal:
59    case IrOpcode::kJSDeleteProperty:
60
61    // Context operations
62    case IrOpcode::kJSCreateScriptContext:
63
64    // Conversions
65    case IrOpcode::kJSToInteger:
66    case IrOpcode::kJSToLength:
67    case IrOpcode::kJSToName:
68    case IrOpcode::kJSToNumber:
69    case IrOpcode::kJSToObject:
70    case IrOpcode::kJSToString:
71
72    // Call operations
73    case IrOpcode::kJSCallConstruct:
74    case IrOpcode::kJSCallFunction:
75
76    // Misc operations
77    case IrOpcode::kJSConvertReceiver:
78    case IrOpcode::kJSForInNext:
79    case IrOpcode::kJSForInPrepare:
80    case IrOpcode::kJSStackCheck:
81      return 1;
82
83    // Binary operators that can deopt in the middle the operation (e.g.,
84    // as a result of lazy deopt in ToNumber conversion) need a second frame
85    // state so that we can resume before the operation.
86    case IrOpcode::kJSMultiply:
87    case IrOpcode::kJSAdd:
88    case IrOpcode::kJSBitwiseAnd:
89    case IrOpcode::kJSBitwiseOr:
90    case IrOpcode::kJSBitwiseXor:
91    case IrOpcode::kJSDivide:
92    case IrOpcode::kJSModulus:
93    case IrOpcode::kJSShiftLeft:
94    case IrOpcode::kJSShiftRight:
95    case IrOpcode::kJSShiftRightLogical:
96    case IrOpcode::kJSSubtract:
97      return 2;
98
99    // Compare operators that can deopt in the middle the operation (e.g.,
100    // as a result of lazy deopt in ToNumber conversion) need a second frame
101    // state so that we can resume before the operation.
102    case IrOpcode::kJSGreaterThan:
103    case IrOpcode::kJSGreaterThanOrEqual:
104    case IrOpcode::kJSLessThan:
105    case IrOpcode::kJSLessThanOrEqual:
106      return 2;
107
108    default:
109      return 0;
110  }
111}
112
113
114// static
115int OperatorProperties::GetTotalInputCount(const Operator* op) {
116  return op->ValueInputCount() + GetContextInputCount(op) +
117         GetFrameStateInputCount(op) + op->EffectInputCount() +
118         op->ControlInputCount();
119}
120
121
122// static
123bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
124  Operator::Opcode const opcode = op->opcode();
125  return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd ||
126         opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop ||
127         opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue ||
128         opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess ||
129         opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue ||
130         opcode == IrOpcode::kIfDefault;
131}
132
133}  // namespace compiler
134}  // namespace internal
135}  // namespace v8
136