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 STATIC_CONST_MEMBER_DEFINITION const OperandType* Bytecodes::kOperandTypes[] = { |
| 17 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes, |
| 18 BYTECODE_LIST(ENTRY) |
| 19 #undef ENTRY |
| 20 }; |
| 21 |
| 22 STATIC_CONST_MEMBER_DEFINITION |
| 23 const OperandTypeInfo* Bytecodes::kOperandTypeInfos[] = { |
| 24 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos, |
| 25 BYTECODE_LIST(ENTRY) |
| 26 #undef ENTRY |
| 27 }; |
| 28 |
| 29 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kOperandCount[] = { |
| 30 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount, |
| 31 BYTECODE_LIST(ENTRY) |
| 32 #undef ENTRY |
| 33 }; |
| 34 |
| 35 STATIC_CONST_MEMBER_DEFINITION |
| 36 const AccumulatorUse Bytecodes::kAccumulatorUse[] = { |
| 37 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse, |
| 38 BYTECODE_LIST(ENTRY) |
| 39 #undef ENTRY |
| 40 }; |
| 41 |
| 42 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kBytecodeSizes[][3] = { |
| 43 #define ENTRY(Name, ...) \ |
| 44 { BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, \ |
| 45 BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, \ |
| 46 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize }, |
| 47 BYTECODE_LIST(ENTRY) |
| 48 #undef ENTRY |
| 49 }; |
| 50 |
| 51 STATIC_CONST_MEMBER_DEFINITION |
| 52 const OperandSize* const Bytecodes::kOperandSizes[][3] = { |
| 53 #define ENTRY(Name, ...) \ |
| 54 { BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, \ |
| 55 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, \ |
| 56 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes }, |
| 57 BYTECODE_LIST(ENTRY) |
| 58 #undef ENTRY |
| 59 }; |
18 | 60 |
19 // static | 61 // static |
20 const char* Bytecodes::ToString(Bytecode bytecode) { | 62 const char* Bytecodes::ToString(Bytecode bytecode) { |
21 switch (bytecode) { | 63 switch (bytecode) { |
22 #define CASE(Name, ...) \ | 64 #define CASE(Name, ...) \ |
23 case Bytecode::k##Name: \ | 65 case Bytecode::k##Name: \ |
24 return #Name; | 66 return #Name; |
25 BYTECODE_LIST(CASE) | 67 BYTECODE_LIST(CASE) |
26 #undef CASE | 68 #undef CASE |
27 } | 69 } |
28 UNREACHABLE(); | 70 UNREACHABLE(); |
29 return ""; | 71 return ""; |
30 } | 72 } |
31 | 73 |
32 // static | 74 // static |
33 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { | 75 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { |
34 static const char kSeparator = '.'; | 76 static const char kSeparator = '.'; |
35 | 77 |
36 std::string value(ToString(bytecode)); | 78 std::string value(ToString(bytecode)); |
37 if (operand_scale > OperandScale::kSingle) { | 79 if (operand_scale > OperandScale::kSingle) { |
38 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); | 80 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); |
39 std::string suffix = ToString(prefix_bytecode); | 81 std::string suffix = ToString(prefix_bytecode); |
40 return value.append(1, kSeparator).append(suffix); | 82 return value.append(1, kSeparator).append(suffix); |
41 } else { | 83 } else { |
42 return value; | 84 return value; |
43 } | 85 } |
44 } | 86 } |
45 | 87 |
46 // static | 88 // 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) { | 89 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
119 DCHECK(!IsDebugBreak(bytecode)); | 90 DCHECK(!IsDebugBreak(bytecode)); |
120 if (bytecode == Bytecode::kWide) { | 91 if (bytecode == Bytecode::kWide) { |
121 return Bytecode::kDebugBreakWide; | 92 return Bytecode::kDebugBreakWide; |
122 } | 93 } |
123 if (bytecode == Bytecode::kExtraWide) { | 94 if (bytecode == Bytecode::kExtraWide) { |
124 return Bytecode::kDebugBreakExtraWide; | 95 return Bytecode::kDebugBreakExtraWide; |
125 } | 96 } |
126 int bytecode_size = Size(bytecode, OperandScale::kSingle); | 97 int bytecode_size = Size(bytecode, OperandScale::kSingle); |
127 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ | 98 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ |
128 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ | 99 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ |
129 return Bytecode::k##Name; \ | 100 return Bytecode::k##Name; \ |
130 } | 101 } |
131 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) | 102 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) |
132 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES | 103 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES |
133 UNREACHABLE(); | 104 UNREACHABLE(); |
134 return Bytecode::kIllegal; | 105 return Bytecode::kIllegal; |
135 } | 106 } |
136 | 107 |
137 // static | 108 // 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 CHECK(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 CHECK_LE(bytecode, Bytecode::kLast); | |
314 CHECK_LT(i, NumberOfOperands(bytecode)); | |
315 CHECK_GE(i, 0); | |
316 return GetOperandTypes(bytecode)[i]; | |
317 } | |
318 | |
319 // static | |
320 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { | |
321 CHECK_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 CHECK_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, | 109 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
357 OperandScale operand_scale) { | 110 OperandScale operand_scale) { |
358 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); | 111 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); |
359 // TODO(oth): restore this to a statically determined constant. | 112 // TODO(oth): restore this to a statically determined constant. |
360 int offset = 1; | 113 int offset = 1; |
361 for (int operand_index = 0; operand_index < i; ++operand_index) { | 114 for (int operand_index = 0; operand_index < i; ++operand_index) { |
362 OperandSize operand_size = | 115 OperandSize operand_size = |
363 GetOperandSize(bytecode, operand_index, operand_scale); | 116 GetOperandSize(bytecode, operand_index, operand_scale); |
364 offset += static_cast<int>(operand_size); | 117 offset += static_cast<int>(operand_size); |
365 } | 118 } |
366 return offset; | 119 return offset; |
367 } | 120 } |
368 | 121 |
369 // static | 122 // static |
370 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, | |
371 OperandScale operand_scale) { | |
372 CHECK_LE(operand_type, OperandType::kLast); | |
373 CHECK_GE(operand_scale, OperandScale::kSingle); | |
374 CHECK_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) { | 123 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
436 switch (bytecode) { | 124 switch (bytecode) { |
437 case Bytecode::kJumpIfToBooleanTrue: | 125 case Bytecode::kJumpIfToBooleanTrue: |
438 return Bytecode::kJumpIfTrue; | 126 return Bytecode::kJumpIfTrue; |
439 case Bytecode::kJumpIfToBooleanFalse: | 127 case Bytecode::kJumpIfToBooleanFalse: |
440 return Bytecode::kJumpIfFalse; | 128 return Bytecode::kJumpIfFalse; |
441 case Bytecode::kJumpIfToBooleanTrueConstant: | 129 case Bytecode::kJumpIfToBooleanTrueConstant: |
442 return Bytecode::kJumpIfTrueConstant; | 130 return Bytecode::kJumpIfTrueConstant; |
443 case Bytecode::kJumpIfToBooleanFalseConstant: | 131 case Bytecode::kJumpIfToBooleanFalseConstant: |
444 return Bytecode::kJumpIfFalseConstant; | 132 return Bytecode::kJumpIfFalseConstant; |
445 default: | 133 default: |
446 break; | 134 break; |
447 } | 135 } |
448 UNREACHABLE(); | 136 UNREACHABLE(); |
449 return Bytecode::kIllegal; | 137 return Bytecode::kIllegal; |
450 } | 138 } |
451 | 139 |
452 // static | 140 // 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) { | 141 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
467 switch (bytecode) { | 142 switch (bytecode) { |
468 #define CASE(Name, ...) case Bytecode::k##Name: | 143 #define CASE(Name, ...) case Bytecode::k##Name: |
469 DEBUG_BREAK_BYTECODE_LIST(CASE); | 144 DEBUG_BREAK_BYTECODE_LIST(CASE); |
470 #undef CASE | 145 #undef CASE |
471 return true; | 146 return true; |
472 default: | 147 default: |
473 break; | 148 break; |
474 } | 149 } |
475 return false; | 150 return false; |
476 } | 151 } |
477 | 152 |
478 // static | 153 // 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) { | 154 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
527 switch (operand_type) { | 155 switch (operand_type) { |
528 #define CASE(Name, _) \ | 156 #define CASE(Name, _) \ |
529 case OperandType::k##Name: \ | 157 case OperandType::k##Name: \ |
530 return true; | 158 return true; |
531 REGISTER_OPERAND_TYPE_LIST(CASE) | 159 REGISTER_OPERAND_TYPE_LIST(CASE) |
532 #undef CASE | 160 #undef CASE |
533 #define CASE(Name, _) \ | 161 #define CASE(Name, _) \ |
534 case OperandType::k##Name: \ | 162 case OperandType::k##Name: \ |
535 break; | 163 break; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 case Bytecode::kNew: | 224 case Bytecode::kNew: |
597 return true; | 225 return true; |
598 default: | 226 default: |
599 return false; | 227 return false; |
600 } | 228 } |
601 } | 229 } |
602 return false; | 230 return false; |
603 } | 231 } |
604 | 232 |
605 // static | 233 // static |
606 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { | 234 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
607 switch (operand_type) { | 235 for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
608 case OperandType::kMaybeReg: | 236 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 } | 237 } |
620 return 0; | 238 return false; |
621 } | 239 } |
622 | 240 |
623 // static | 241 // static |
624 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { | 242 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
625 switch (operand_type) { | 243 switch (operand_type) { |
626 #define CASE(Name, _) \ | 244 #define CASE(Name, _) \ |
627 case OperandType::k##Name: \ | 245 case OperandType::k##Name: \ |
628 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; | 246 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; |
629 OPERAND_TYPE_LIST(CASE) | 247 OPERAND_TYPE_LIST(CASE) |
630 #undef CASE | 248 #undef CASE |
631 } | 249 } |
632 UNREACHABLE(); | 250 UNREACHABLE(); |
633 return false; | 251 return false; |
634 } | 252 } |
635 | 253 |
636 // static | 254 // static |
637 OperandSize Bytecodes::SizeForSignedOperand(int value) { | 255 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, |
638 if (value >= kMinInt8 && value <= kMaxInt8) { | 256 OperandScale operand_scale) { |
639 return OperandSize::kByte; | 257 // TODO(642111): Restore to DCHECKS once bug tracked down. |
640 } else if (value >= kMinInt16 && value <= kMaxInt16) { | 258 CHECK_LE(operand_type, OperandType::kLast); |
641 return OperandSize::kShort; | 259 CHECK_GE(operand_scale, OperandScale::kSingle); |
642 } else { | 260 CHECK_LE(operand_scale, OperandScale::kLast); |
643 return OperandSize::kQuad; | 261 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && |
644 } | 262 OperandScale::kLast == OperandScale::kQuadruple); |
| 263 int scale_index = static_cast<int>(operand_scale) >> 1; |
| 264 static constexpr OperandSize kOperandSizes[][3] = { |
| 265 #define ENTRY(Name, ...) \ |
| 266 { OperandScaler<OperandType::k##Name, \ |
| 267 OperandScale::kSingle>::kOperandSize, \ |
| 268 OperandScaler<OperandType::k##Name, \ |
| 269 OperandScale::kDouble>::kOperandSize, \ |
| 270 OperandScaler<OperandType::k##Name, \ |
| 271 OperandScale::kQuadruple>::kOperandSize }, |
| 272 OPERAND_TYPE_LIST(ENTRY) |
| 273 #undef ENTRY |
| 274 }; |
| 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 |