OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/globals.h" | |
11 #include "src/interpreter/bytecode-traits.h" | 10 #include "src/interpreter/bytecode-traits.h" |
12 | 11 |
13 namespace v8 { | 12 namespace v8 { |
14 namespace internal { | 13 namespace internal { |
15 namespace interpreter { | 14 namespace interpreter { |
16 | 15 |
17 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; | 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 |
18 | 59 |
19 // static | 60 // static |
20 const char* Bytecodes::ToString(Bytecode bytecode) { | 61 const char* Bytecodes::ToString(Bytecode bytecode) { |
21 switch (bytecode) { | 62 switch (bytecode) { |
22 #define CASE(Name, ...) \ | 63 #define CASE(Name, ...) \ |
23 case Bytecode::k##Name: \ | 64 case Bytecode::k##Name: \ |
24 return #Name; | 65 return #Name; |
25 BYTECODE_LIST(CASE) | 66 BYTECODE_LIST(CASE) |
26 #undef CASE | 67 #undef CASE |
27 } | 68 } |
28 UNREACHABLE(); | 69 UNREACHABLE(); |
29 return ""; | 70 return ""; |
30 } | 71 } |
31 | 72 |
32 // static | 73 // static |
33 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { | 74 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { |
34 static const char kSeparator = '.'; | 75 static const char kSeparator = '.'; |
35 | 76 |
36 std::string value(ToString(bytecode)); | 77 std::string value(ToString(bytecode)); |
37 if (operand_scale > OperandScale::kSingle) { | 78 if (operand_scale > OperandScale::kSingle) { |
38 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); | 79 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); |
39 std::string suffix = ToString(prefix_bytecode); | 80 std::string suffix = ToString(prefix_bytecode); |
40 return value.append(1, kSeparator).append(suffix); | 81 return value.append(1, kSeparator).append(suffix); |
41 } else { | 82 } else { |
42 return value; | 83 return value; |
43 } | 84 } |
44 } | 85 } |
45 | 86 |
46 // static | 87 // static |
47 const char* Bytecodes::AccumulatorUseToString(AccumulatorUse accumulator_use) { | |
48 switch (accumulator_use) { | |
49 case AccumulatorUse::kNone: | |
50 return "None"; | |
51 case AccumulatorUse::kRead: | |
52 return "Read"; | |
53 case AccumulatorUse::kWrite: | |
54 return "Write"; | |
55 case AccumulatorUse::kReadWrite: | |
56 return "ReadWrite"; | |
57 } | |
58 UNREACHABLE(); | |
59 return ""; | |
60 } | |
61 | |
62 // static | |
63 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | |
64 switch (operand_type) { | |
65 #define CASE(Name, _) \ | |
66 case OperandType::k##Name: \ | |
67 return #Name; | |
68 OPERAND_TYPE_LIST(CASE) | |
69 #undef CASE | |
70 } | |
71 UNREACHABLE(); | |
72 return ""; | |
73 } | |
74 | |
75 // static | |
76 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { | |
77 switch (operand_scale) { | |
78 #define CASE(Name, _) \ | |
79 case OperandScale::k##Name: \ | |
80 return #Name; | |
81 OPERAND_SCALE_LIST(CASE) | |
82 #undef CASE | |
83 } | |
84 UNREACHABLE(); | |
85 return ""; | |
86 } | |
87 | |
88 // static | |
89 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | |
90 switch (operand_size) { | |
91 case OperandSize::kNone: | |
92 return "None"; | |
93 case OperandSize::kByte: | |
94 return "Byte"; | |
95 case OperandSize::kShort: | |
96 return "Short"; | |
97 case OperandSize::kQuad: | |
98 return "Quad"; | |
99 } | |
100 UNREACHABLE(); | |
101 return ""; | |
102 } | |
103 | |
104 // static | |
105 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | |
106 DCHECK_LE(bytecode, Bytecode::kLast); | |
107 return static_cast<uint8_t>(bytecode); | |
108 } | |
109 | |
110 // static | |
111 Bytecode Bytecodes::FromByte(uint8_t value) { | |
112 Bytecode bytecode = static_cast<Bytecode>(value); | |
113 DCHECK(bytecode <= Bytecode::kLast); | |
114 return bytecode; | |
115 } | |
116 | |
117 // static | |
118 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 88 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
119 DCHECK(!IsDebugBreak(bytecode)); | 89 DCHECK(!IsDebugBreak(bytecode)); |
120 if (bytecode == Bytecode::kWide) { | 90 if (bytecode == Bytecode::kWide) { |
121 return Bytecode::kDebugBreakWide; | 91 return Bytecode::kDebugBreakWide; |
122 } | 92 } |
123 if (bytecode == Bytecode::kExtraWide) { | 93 if (bytecode == Bytecode::kExtraWide) { |
124 return Bytecode::kDebugBreakExtraWide; | 94 return Bytecode::kDebugBreakExtraWide; |
125 } | 95 } |
126 int bytecode_size = Size(bytecode, OperandScale::kSingle); | 96 int bytecode_size = Size(bytecode, OperandScale::kSingle); |
127 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ | 97 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ |
128 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ | 98 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ |
129 return Bytecode::k##Name; \ | 99 return Bytecode::k##Name; \ |
130 } | 100 } |
131 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) | 101 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) |
132 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES | 102 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES |
133 UNREACHABLE(); | 103 UNREACHABLE(); |
134 return Bytecode::kIllegal; | 104 return Bytecode::kIllegal; |
135 } | 105 } |
136 | 106 |
137 // static | 107 // static |
138 int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) { | |
139 int size = 1; | |
140 for (int i = 0; i < NumberOfOperands(bytecode); i++) { | |
141 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); | |
142 int delta = static_cast<int>(operand_size); | |
143 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); | |
144 size += delta; | |
145 } | |
146 return size; | |
147 } | |
148 | |
149 // static | |
150 size_t Bytecodes::ReturnCount(Bytecode bytecode) { | |
151 return bytecode == Bytecode::kReturn ? 1 : 0; | |
152 } | |
153 | |
154 // static | |
155 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | |
156 DCHECK(bytecode <= Bytecode::kLast); | |
157 switch (bytecode) { | |
158 #define CASE(Name, ...) \ | |
159 case Bytecode::k##Name: \ | |
160 return BytecodeTraits<__VA_ARGS__>::kOperandCount; | |
161 BYTECODE_LIST(CASE) | |
162 #undef CASE | |
163 } | |
164 UNREACHABLE(); | |
165 return 0; | |
166 } | |
167 | |
168 // static | |
169 int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) { | |
170 DCHECK(bytecode <= Bytecode::kLast); | |
171 switch (bytecode) { | |
172 #define CASE(Name, ...) \ | |
173 case Bytecode::k##Name: \ | |
174 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ | |
175 return Name##Trait::kRegisterOperandCount; | |
176 BYTECODE_LIST(CASE) | |
177 #undef CASE | |
178 } | |
179 UNREACHABLE(); | |
180 return false; | |
181 } | |
182 | |
183 // static | |
184 Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) { | |
185 switch (operand_scale) { | |
186 case OperandScale::kQuadruple: | |
187 return Bytecode::kExtraWide; | |
188 case OperandScale::kDouble: | |
189 return Bytecode::kWide; | |
190 default: | |
191 UNREACHABLE(); | |
192 return Bytecode::kIllegal; | |
193 } | |
194 } | |
195 | |
196 // static | |
197 bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) { | |
198 return operand_scale != OperandScale::kSingle; | |
199 } | |
200 | |
201 // static | |
202 OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) { | |
203 switch (bytecode) { | |
204 case Bytecode::kExtraWide: | |
205 case Bytecode::kDebugBreakExtraWide: | |
206 return OperandScale::kQuadruple; | |
207 case Bytecode::kWide: | |
208 case Bytecode::kDebugBreakWide: | |
209 return OperandScale::kDouble; | |
210 default: | |
211 UNREACHABLE(); | |
212 return OperandScale::kSingle; | |
213 } | |
214 } | |
215 | |
216 // static | |
217 AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) { | |
218 DCHECK(bytecode <= Bytecode::kLast); | |
219 switch (bytecode) { | |
220 #define CASE(Name, ...) \ | |
221 case Bytecode::k##Name: \ | |
222 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse; | |
223 BYTECODE_LIST(CASE) | |
224 #undef CASE | |
225 } | |
226 UNREACHABLE(); | |
227 return AccumulatorUse::kNone; | |
228 } | |
229 | |
230 // static | |
231 bool Bytecodes::ReadsAccumulator(Bytecode bytecode) { | |
232 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) == | |
233 AccumulatorUse::kRead; | |
234 } | |
235 | |
236 // static | |
237 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { | |
238 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == | |
239 AccumulatorUse::kWrite; | |
240 } | |
241 | |
242 // static | |
243 bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) { | |
244 switch (bytecode) { | |
245 case Bytecode::kLdaTrue: | |
246 case Bytecode::kLdaFalse: | |
247 case Bytecode::kToBooleanLogicalNot: | |
248 case Bytecode::kLogicalNot: | |
249 case Bytecode::kTestEqual: | |
250 case Bytecode::kTestNotEqual: | |
251 case Bytecode::kTestEqualStrict: | |
252 case Bytecode::kTestLessThan: | |
253 case Bytecode::kTestLessThanOrEqual: | |
254 case Bytecode::kTestGreaterThan: | |
255 case Bytecode::kTestGreaterThanOrEqual: | |
256 case Bytecode::kTestInstanceOf: | |
257 case Bytecode::kTestIn: | |
258 case Bytecode::kForInContinue: | |
259 return true; | |
260 default: | |
261 return false; | |
262 } | |
263 } | |
264 | |
265 // static | |
266 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { | |
267 switch (bytecode) { | |
268 case Bytecode::kLdaZero: | |
269 case Bytecode::kLdaSmi: | |
270 case Bytecode::kLdaUndefined: | |
271 case Bytecode::kLdaNull: | |
272 case Bytecode::kLdaTheHole: | |
273 case Bytecode::kLdaTrue: | |
274 case Bytecode::kLdaFalse: | |
275 case Bytecode::kLdaConstant: | |
276 case Bytecode::kLdar: | |
277 return true; | |
278 default: | |
279 return false; | |
280 } | |
281 } | |
282 | |
283 // static | |
284 bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) { | |
285 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode); | |
286 } | |
287 | |
288 // static | |
289 bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) { | |
290 switch (bytecode) { | |
291 case Bytecode::kMov: | |
292 case Bytecode::kPopContext: | |
293 case Bytecode::kPushContext: | |
294 case Bytecode::kStar: | |
295 case Bytecode::kLdrUndefined: | |
296 return true; | |
297 default: | |
298 return false; | |
299 } | |
300 } | |
301 | |
302 // static | |
303 bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) { | |
304 // These bytecodes only manipulate interpreter frame state and will | |
305 // never throw. | |
306 return (IsAccumulatorLoadWithoutEffects(bytecode) || | |
307 IsRegisterLoadWithoutEffects(bytecode) || | |
308 bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode)); | |
309 } | |
310 | |
311 // static | |
312 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | |
313 DCHECK_LE(bytecode, Bytecode::kLast); | |
314 DCHECK_LT(i, NumberOfOperands(bytecode)); | |
315 DCHECK_GE(i, 0); | |
316 return GetOperandTypes(bytecode)[i]; | |
317 } | |
318 | |
319 // static | |
320 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { | |
321 DCHECK_LE(bytecode, Bytecode::kLast); | |
322 switch (bytecode) { | |
323 #define CASE(Name, ...) \ | |
324 case Bytecode::k##Name: \ | |
325 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); | |
326 BYTECODE_LIST(CASE) | |
327 #undef CASE | |
328 } | |
329 UNREACHABLE(); | |
330 return nullptr; | |
331 } | |
332 | |
333 // static | |
334 const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) { | |
335 DCHECK(bytecode <= Bytecode::kLast); | |
336 switch (bytecode) { | |
337 #define CASE(Name, ...) \ | |
338 case Bytecode::k##Name: \ | |
339 return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos(); | |
340 BYTECODE_LIST(CASE) | |
341 #undef CASE | |
342 } | |
343 UNREACHABLE(); | |
344 return nullptr; | |
345 } | |
346 | |
347 // static | |
348 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, | |
349 OperandScale operand_scale) { | |
350 DCHECK_LT(i, NumberOfOperands(bytecode)); | |
351 OperandType operand_type = GetOperandType(bytecode, i); | |
352 return SizeOfOperand(operand_type, operand_scale); | |
353 } | |
354 | |
355 // static | |
356 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, | 108 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
357 OperandScale operand_scale) { | 109 OperandScale operand_scale) { |
358 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); | 110 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); |
359 // TODO(oth): restore this to a statically determined constant. | 111 // TODO(oth): restore this to a statically determined constant. |
360 int offset = 1; | 112 int offset = 1; |
361 for (int operand_index = 0; operand_index < i; ++operand_index) { | 113 for (int operand_index = 0; operand_index < i; ++operand_index) { |
362 OperandSize operand_size = | 114 OperandSize operand_size = |
363 GetOperandSize(bytecode, operand_index, operand_scale); | 115 GetOperandSize(bytecode, operand_index, operand_scale); |
364 offset += static_cast<int>(operand_size); | 116 offset += static_cast<int>(operand_size); |
365 } | 117 } |
366 return offset; | 118 return offset; |
367 } | 119 } |
368 | 120 |
369 // static | 121 // static |
370 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, | |
371 OperandScale operand_scale) { | |
372 DCHECK_LE(operand_type, OperandType::kLast); | |
373 DCHECK_GE(operand_scale, OperandScale::kSingle); | |
374 DCHECK_LE(operand_scale, OperandScale::kLast); | |
375 return static_cast<OperandSize>( | |
376 ScaledOperandSize(operand_type, operand_scale)); | |
377 } | |
378 | |
379 // static | |
380 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { | |
381 return bytecode == Bytecode::kJumpIfTrue || | |
382 bytecode == Bytecode::kJumpIfFalse || | |
383 bytecode == Bytecode::kJumpIfToBooleanTrue || | |
384 bytecode == Bytecode::kJumpIfToBooleanFalse || | |
385 bytecode == Bytecode::kJumpIfNotHole || | |
386 bytecode == Bytecode::kJumpIfNull || | |
387 bytecode == Bytecode::kJumpIfUndefined; | |
388 } | |
389 | |
390 // static | |
391 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { | |
392 return bytecode == Bytecode::kJumpIfTrueConstant || | |
393 bytecode == Bytecode::kJumpIfFalseConstant || | |
394 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | |
395 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || | |
396 bytecode == Bytecode::kJumpIfNotHoleConstant || | |
397 bytecode == Bytecode::kJumpIfNullConstant || | |
398 bytecode == Bytecode::kJumpIfUndefinedConstant; | |
399 } | |
400 | |
401 // static | |
402 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { | |
403 return IsConditionalJumpImmediate(bytecode) || | |
404 IsConditionalJumpConstant(bytecode); | |
405 } | |
406 | |
407 | |
408 // static | |
409 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { | |
410 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop || | |
411 IsConditionalJumpImmediate(bytecode); | |
412 } | |
413 | |
414 | |
415 // static | |
416 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | |
417 return bytecode == Bytecode::kJumpConstant || | |
418 IsConditionalJumpConstant(bytecode); | |
419 } | |
420 | |
421 // static | |
422 bool Bytecodes::IsJump(Bytecode bytecode) { | |
423 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); | |
424 } | |
425 | |
426 // static | |
427 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { | |
428 return bytecode == Bytecode::kJumpIfToBooleanTrue || | |
429 bytecode == Bytecode::kJumpIfToBooleanFalse || | |
430 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | |
431 bytecode == Bytecode::kJumpIfToBooleanFalseConstant; | |
432 } | |
433 | |
434 // static | |
435 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { | 122 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
436 switch (bytecode) { | 123 switch (bytecode) { |
437 case Bytecode::kJumpIfToBooleanTrue: | 124 case Bytecode::kJumpIfToBooleanTrue: |
438 return Bytecode::kJumpIfTrue; | 125 return Bytecode::kJumpIfTrue; |
439 case Bytecode::kJumpIfToBooleanFalse: | 126 case Bytecode::kJumpIfToBooleanFalse: |
440 return Bytecode::kJumpIfFalse; | 127 return Bytecode::kJumpIfFalse; |
441 case Bytecode::kJumpIfToBooleanTrueConstant: | 128 case Bytecode::kJumpIfToBooleanTrueConstant: |
442 return Bytecode::kJumpIfTrueConstant; | 129 return Bytecode::kJumpIfTrueConstant; |
443 case Bytecode::kJumpIfToBooleanFalseConstant: | 130 case Bytecode::kJumpIfToBooleanFalseConstant: |
444 return Bytecode::kJumpIfFalseConstant; | 131 return Bytecode::kJumpIfFalseConstant; |
445 default: | 132 default: |
446 break; | 133 break; |
447 } | 134 } |
448 UNREACHABLE(); | 135 UNREACHABLE(); |
449 return Bytecode::kIllegal; | 136 return Bytecode::kIllegal; |
450 } | 137 } |
451 | 138 |
452 // static | 139 // static |
453 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { | |
454 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || | |
455 bytecode == Bytecode::kNew; | |
456 } | |
457 | |
458 // static | |
459 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { | |
460 return bytecode == Bytecode::kCallRuntime || | |
461 bytecode == Bytecode::kCallRuntimeForPair || | |
462 bytecode == Bytecode::kInvokeIntrinsic; | |
463 } | |
464 | |
465 // static | |
466 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { | 140 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
467 switch (bytecode) { | 141 switch (bytecode) { |
468 #define CASE(Name, ...) case Bytecode::k##Name: | 142 #define CASE(Name, ...) case Bytecode::k##Name: |
469 DEBUG_BREAK_BYTECODE_LIST(CASE); | 143 DEBUG_BREAK_BYTECODE_LIST(CASE); |
470 #undef CASE | 144 #undef CASE |
471 return true; | 145 return true; |
472 default: | 146 default: |
473 break; | 147 break; |
474 } | 148 } |
475 return false; | 149 return false; |
476 } | 150 } |
477 | 151 |
478 // static | 152 // static |
479 bool Bytecodes::IsLdarOrStar(Bytecode bytecode) { | |
480 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar; | |
481 } | |
482 | |
483 // static | |
484 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { | |
485 switch (bytecode) { | |
486 #define CASE(Name, ...) \ | |
487 case Bytecode::k##Name: \ | |
488 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ | |
489 return Name##Trait::IsScalable(); | |
490 BYTECODE_LIST(CASE) | |
491 #undef CASE | |
492 } | |
493 UNREACHABLE(); | |
494 return false; | |
495 } | |
496 | |
497 // static | |
498 bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) { | |
499 switch (bytecode) { | |
500 case Bytecode::kExtraWide: | |
501 case Bytecode::kDebugBreakExtraWide: | |
502 case Bytecode::kWide: | |
503 case Bytecode::kDebugBreakWide: | |
504 return true; | |
505 default: | |
506 return false; | |
507 } | |
508 } | |
509 | |
510 // static | |
511 bool Bytecodes::PutsNameInAccumulator(Bytecode bytecode) { | |
512 return bytecode == Bytecode::kTypeOf; | |
513 } | |
514 | |
515 // static | |
516 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { | |
517 return bytecode == Bytecode::kReturn || IsJump(bytecode); | |
518 } | |
519 | |
520 // static | |
521 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { | |
522 return operand_type == OperandType::kMaybeReg; | |
523 } | |
524 | |
525 // static | |
526 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { | 153 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
527 switch (operand_type) { | 154 switch (operand_type) { |
528 #define CASE(Name, _) \ | 155 #define CASE(Name, _) \ |
529 case OperandType::k##Name: \ | 156 case OperandType::k##Name: \ |
530 return true; | 157 return true; |
531 REGISTER_OPERAND_TYPE_LIST(CASE) | 158 REGISTER_OPERAND_TYPE_LIST(CASE) |
532 #undef CASE | 159 #undef CASE |
533 #define CASE(Name, _) \ | 160 #define CASE(Name, _) \ |
534 case OperandType::k##Name: \ | 161 case OperandType::k##Name: \ |
535 break; | 162 break; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 case Bytecode::kNew: | 223 case Bytecode::kNew: |
597 return true; | 224 return true; |
598 default: | 225 default: |
599 return false; | 226 return false; |
600 } | 227 } |
601 } | 228 } |
602 return false; | 229 return false; |
603 } | 230 } |
604 | 231 |
605 // static | 232 // static |
606 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { | 233 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
607 switch (operand_type) { | 234 for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
608 case OperandType::kMaybeReg: | 235 if (OperandIsScalable(bytecode, i)) return true; |
609 case OperandType::kReg: | |
610 case OperandType::kRegOut: | |
611 return 1; | |
612 case OperandType::kRegPair: | |
613 case OperandType::kRegOutPair: | |
614 return 2; | |
615 case OperandType::kRegOutTriple: | |
616 return 3; | |
617 default: | |
618 return 0; | |
619 } | 236 } |
620 return 0; | 237 return false; |
621 } | 238 } |
622 | 239 |
623 // static | 240 // static |
624 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { | 241 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
625 switch (operand_type) { | 242 switch (operand_type) { |
626 #define CASE(Name, _) \ | 243 #define CASE(Name, _) \ |
627 case OperandType::k##Name: \ | 244 case OperandType::k##Name: \ |
628 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; | 245 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; |
629 OPERAND_TYPE_LIST(CASE) | 246 OPERAND_TYPE_LIST(CASE) |
630 #undef CASE | 247 #undef CASE |
631 } | 248 } |
632 UNREACHABLE(); | 249 UNREACHABLE(); |
633 return false; | 250 return false; |
634 } | 251 } |
635 | 252 |
636 // static | 253 // static |
637 OperandSize Bytecodes::SizeForSignedOperand(int value) { | 254 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, |
638 if (value >= kMinInt8 && value <= kMaxInt8) { | 255 OperandScale operand_scale) { |
639 return OperandSize::kByte; | 256 DCHECK_LE(operand_type, OperandType::kLast); |
640 } else if (value >= kMinInt16 && value <= kMaxInt16) { | 257 DCHECK_GE(operand_scale, OperandScale::kSingle); |
641 return OperandSize::kShort; | 258 DCHECK_LE(operand_scale, OperandScale::kLast); |
642 } else { | 259 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && |
643 return OperandSize::kQuad; | 260 OperandScale::kLast == OperandScale::kQuadruple); |
644 } | 261 int scale_index = static_cast<int>(operand_scale) >> 1; |
| 262 // clang-format off |
| 263 static const OperandSize kOperandSizes[][3] = { |
| 264 #define ENTRY(Name, ...) \ |
| 265 { OperandScaler<OperandType::k##Name, \ |
| 266 OperandScale::kSingle>::kOperandSize, \ |
| 267 OperandScaler<OperandType::k##Name, \ |
| 268 OperandScale::kDouble>::kOperandSize, \ |
| 269 OperandScaler<OperandType::k##Name, \ |
| 270 OperandScale::kQuadruple>::kOperandSize }, |
| 271 OPERAND_TYPE_LIST(ENTRY) |
| 272 #undef ENTRY |
| 273 }; |
| 274 // clang-format on |
| 275 return kOperandSizes[static_cast<size_t>(operand_type)][scale_index]; |
645 } | 276 } |
646 | 277 |
647 // static | 278 // static |
648 OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) { | |
649 if (value <= kMaxUInt8) { | |
650 return OperandSize::kByte; | |
651 } else if (value <= kMaxUInt16) { | |
652 return OperandSize::kShort; | |
653 } else { | |
654 return OperandSize::kQuad; | |
655 } | |
656 } | |
657 | |
658 // static | |
659 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, | 279 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, |
660 OperandScale operand_scale) { | 280 OperandScale operand_scale) { |
661 return operand_scale == OperandScale::kSingle || | 281 return operand_scale == OperandScale::kSingle || |
662 Bytecodes::IsBytecodeWithScalableOperands(bytecode); | 282 Bytecodes::IsBytecodeWithScalableOperands(bytecode); |
663 } | 283 } |
664 | 284 |
665 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 285 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
666 return os << Bytecodes::ToString(bytecode); | 286 return os << Bytecodes::ToString(bytecode); |
667 } | 287 } |
668 | 288 |
669 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { | |
670 return os << Bytecodes::AccumulatorUseToString(use); | |
671 } | |
672 | |
673 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { | |
674 return os << Bytecodes::OperandSizeToString(operand_size); | |
675 } | |
676 | |
677 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { | |
678 return os << Bytecodes::OperandScaleToString(operand_scale); | |
679 } | |
680 | |
681 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | |
682 return os << Bytecodes::OperandTypeToString(operand_type); | |
683 } | |
684 | |
685 } // namespace interpreter | 289 } // namespace interpreter |
686 } // namespace internal | 290 } // namespace internal |
687 } // namespace v8 | 291 } // namespace v8 |
OLD | NEW |