Line data Source code
1 : // Copyright 2015 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/interpreter/bytecodes.h"
6 :
7 : #include <iomanip>
8 :
9 : #include "src/base/bits.h"
10 : #include "src/interpreter/bytecode-traits.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace interpreter {
15 :
16 : // clang-format off
17 : const OperandType* const Bytecodes::kOperandTypes[] = {
18 : #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes,
19 : BYTECODE_LIST(ENTRY)
20 : #undef ENTRY
21 : };
22 :
23 : const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = {
24 : #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos,
25 : BYTECODE_LIST(ENTRY)
26 : #undef ENTRY
27 : };
28 :
29 : const int Bytecodes::kOperandCount[] = {
30 : #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount,
31 : BYTECODE_LIST(ENTRY)
32 : #undef ENTRY
33 : };
34 :
35 : const AccumulatorUse Bytecodes::kAccumulatorUse[] = {
36 : #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse,
37 : BYTECODE_LIST(ENTRY)
38 : #undef ENTRY
39 : };
40 :
41 : const int Bytecodes::kBytecodeSizes[][3] = {
42 : #define ENTRY(Name, ...) \
43 : { BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, \
44 : BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, \
45 : BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize },
46 : BYTECODE_LIST(ENTRY)
47 : #undef ENTRY
48 : };
49 :
50 : const OperandSize* const Bytecodes::kOperandSizes[][3] = {
51 : #define ENTRY(Name, ...) \
52 : { BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, \
53 : BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, \
54 : BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes },
55 : BYTECODE_LIST(ENTRY)
56 : #undef ENTRY
57 : };
58 : // clang-format on
59 :
60 : // static
61 210022 : const char* Bytecodes::ToString(Bytecode bytecode) {
62 210022 : switch (bytecode) {
63 : #define CASE(Name, ...) \
64 : case Bytecode::k##Name: \
65 : return #Name;
66 9205 : BYTECODE_LIST(CASE)
67 : #undef CASE
68 : }
69 0 : UNREACHABLE();
70 : return "";
71 : }
72 :
73 : // static
74 29086 : std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
75 : static const char kSeparator = '.';
76 :
77 29086 : std::string value(ToString(bytecode));
78 29086 : if (operand_scale > OperandScale::kSingle) {
79 18060 : Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
80 18060 : std::string suffix = ToString(prefix_bytecode);
81 18060 : return value.append(1, kSeparator).append(suffix);
82 : } else {
83 : return value;
84 : }
85 : }
86 :
87 : // static
88 3651854 : Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
89 : DCHECK(!IsDebugBreak(bytecode));
90 3651854 : if (bytecode == Bytecode::kWide) {
91 : return Bytecode::kDebugBreakWide;
92 : }
93 2899995 : if (bytecode == Bytecode::kExtraWide) {
94 : return Bytecode::kDebugBreakExtraWide;
95 : }
96 : int bytecode_size = Size(bytecode, OperandScale::kSingle);
97 : #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \
98 : if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
99 : return Bytecode::k##Name; \
100 : }
101 2890714 : DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
102 : #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
103 0 : UNREACHABLE();
104 : return Bytecode::kIllegal;
105 : }
106 :
107 : // static
108 32282682 : int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
109 : OperandScale operand_scale) {
110 : DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
111 : // TODO(oth): restore this to a statically determined constant.
112 : int offset = 1;
113 45981726 : for (int operand_index = 0; operand_index < i; ++operand_index) {
114 : OperandSize operand_size =
115 13699046 : GetOperandSize(bytecode, operand_index, operand_scale);
116 13699044 : offset += static_cast<int>(operand_size);
117 : }
118 32282680 : return offset;
119 : }
120 :
121 : // static
122 0 : Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
123 0 : switch (bytecode) {
124 : case Bytecode::kJumpIfToBooleanTrue:
125 : return Bytecode::kJumpIfTrue;
126 : case Bytecode::kJumpIfToBooleanFalse:
127 0 : return Bytecode::kJumpIfFalse;
128 : case Bytecode::kJumpIfToBooleanTrueConstant:
129 0 : return Bytecode::kJumpIfTrueConstant;
130 : case Bytecode::kJumpIfToBooleanFalseConstant:
131 0 : return Bytecode::kJumpIfFalseConstant;
132 : default:
133 : break;
134 : }
135 0 : UNREACHABLE();
136 : return Bytecode::kIllegal;
137 : }
138 :
139 : // static
140 3675325 : bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
141 3675325 : switch (bytecode) {
142 : #define CASE(Name, ...) case Bytecode::k##Name:
143 : DEBUG_BREAK_BYTECODE_LIST(CASE);
144 : #undef CASE
145 : return true;
146 : default:
147 : break;
148 : }
149 3652075 : return false;
150 : }
151 :
152 : // static
153 155948 : bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
154 155948 : switch (operand_type) {
155 : #define CASE(Name, _) \
156 : case OperandType::k##Name: \
157 : return true;
158 : REGISTER_OPERAND_TYPE_LIST(CASE)
159 : #undef CASE
160 : #define CASE(Name, _) \
161 : case OperandType::k##Name: \
162 : break;
163 : NON_REGISTER_OPERAND_TYPE_LIST(CASE)
164 : #undef CASE
165 : }
166 80619 : return false;
167 : }
168 :
169 268572 : bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) {
170 502802 : if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true;
171 : switch (bytecode) {
172 : case Bytecode::kCreateWithContext:
173 : case Bytecode::kCreateBlockContext:
174 : case Bytecode::kCreateCatchContext:
175 : case Bytecode::kCreateRegExpLiteral:
176 : return true;
177 : default:
178 : return false;
179 : }
180 : }
181 :
182 : // static
183 4 : bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
184 4 : switch (operand_type) {
185 : #define CASE(Name, _) \
186 : case OperandType::k##Name: \
187 : return true;
188 : REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
189 : #undef CASE
190 : #define CASE(Name, _) \
191 : case OperandType::k##Name: \
192 : break;
193 : NON_REGISTER_OPERAND_TYPE_LIST(CASE)
194 : REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
195 : #undef CASE
196 : }
197 1 : return false;
198 : }
199 :
200 : // static
201 3 : bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
202 3 : switch (operand_type) {
203 : #define CASE(Name, _) \
204 : case OperandType::k##Name: \
205 : return true;
206 : REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
207 : #undef CASE
208 : #define CASE(Name, _) \
209 : case OperandType::k##Name: \
210 : break;
211 : NON_REGISTER_OPERAND_TYPE_LIST(CASE)
212 : REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
213 : #undef CASE
214 : }
215 1 : return false;
216 : }
217 :
218 : // static
219 19651 : bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
220 19651 : if (operand_scale == OperandScale::kSingle) {
221 7181 : switch (bytecode) {
222 : case Bytecode::kLdaZero:
223 : case Bytecode::kLdaSmi:
224 : case Bytecode::kLdaNull:
225 : case Bytecode::kLdaTheHole:
226 : case Bytecode::kLdaConstant:
227 : case Bytecode::kLdaUndefined:
228 : case Bytecode::kLdaGlobal:
229 : case Bytecode::kLdaNamedProperty:
230 : case Bytecode::kLdaKeyedProperty:
231 : case Bytecode::kLdaContextSlot:
232 : case Bytecode::kLdaCurrentContextSlot:
233 : case Bytecode::kAdd:
234 : case Bytecode::kSub:
235 : case Bytecode::kMul:
236 : case Bytecode::kAddSmi:
237 : case Bytecode::kSubSmi:
238 : case Bytecode::kInc:
239 : case Bytecode::kDec:
240 : case Bytecode::kTypeOf:
241 : case Bytecode::kCallAnyReceiver:
242 : case Bytecode::kCallProperty:
243 : case Bytecode::kCallProperty0:
244 : case Bytecode::kCallProperty1:
245 : case Bytecode::kCallProperty2:
246 : case Bytecode::kCallUndefinedReceiver:
247 : case Bytecode::kCallUndefinedReceiver0:
248 : case Bytecode::kCallUndefinedReceiver1:
249 : case Bytecode::kCallUndefinedReceiver2:
250 : case Bytecode::kConstruct:
251 : case Bytecode::kConstructWithSpread:
252 : return true;
253 : default:
254 5848 : return false;
255 : }
256 : }
257 : return false;
258 : }
259 :
260 : // static
261 0 : bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
262 23718 : for (int i = 0; i < NumberOfOperands(bytecode); i++) {
263 19028 : if (OperandIsScalable(bytecode, i)) return true;
264 : }
265 : return false;
266 : }
267 :
268 : // static
269 0 : bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
270 0 : switch (operand_type) {
271 : #define CASE(Name, _) \
272 : case OperandType::k##Name: \
273 : return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
274 0 : OPERAND_TYPE_LIST(CASE)
275 : #undef CASE
276 : }
277 0 : UNREACHABLE();
278 : return false;
279 : }
280 :
281 : // static
282 32246634 : OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
283 : OperandScale operand_scale) {
284 : DCHECK_LE(operand_type, OperandType::kLast);
285 : DCHECK_GE(operand_scale, OperandScale::kSingle);
286 : DCHECK_LE(operand_scale, OperandScale::kLast);
287 : STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
288 : OperandScale::kLast == OperandScale::kQuadruple);
289 32246634 : int scale_index = static_cast<int>(operand_scale) >> 1;
290 : // clang-format off
291 : static const OperandSize kOperandSizes[][3] = {
292 : #define ENTRY(Name, ...) \
293 : { OperandScaler<OperandType::k##Name, \
294 : OperandScale::kSingle>::kOperandSize, \
295 : OperandScaler<OperandType::k##Name, \
296 : OperandScale::kDouble>::kOperandSize, \
297 : OperandScaler<OperandType::k##Name, \
298 : OperandScale::kQuadruple>::kOperandSize },
299 : OPERAND_TYPE_LIST(ENTRY)
300 : #undef ENTRY
301 : };
302 : // clang-format on
303 32246634 : return kOperandSizes[static_cast<size_t>(operand_type)][scale_index];
304 : }
305 :
306 : // static
307 33165 : bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
308 : OperandScale operand_scale) {
309 55275 : return operand_scale == OperandScale::kSingle ||
310 33165 : Bytecodes::IsBytecodeWithScalableOperands(bytecode);
311 : }
312 :
313 2478 : std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
314 2478 : return os << Bytecodes::ToString(bytecode);
315 : }
316 :
317 : } // namespace interpreter
318 : } // namespace internal
319 : } // namespace v8
|