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/frames.h"
11 #include "src/interpreter/bytecode-traits.h"
12 #include "src/interpreter/interpreter.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace interpreter {
17
18
19 // static
ToString(Bytecode bytecode)20 const char* Bytecodes::ToString(Bytecode bytecode) {
21 switch (bytecode) {
22 #define CASE(Name, ...) \
23 case Bytecode::k##Name: \
24 return #Name;
25 BYTECODE_LIST(CASE)
26 #undef CASE
27 }
28 UNREACHABLE();
29 return "";
30 }
31
32 // static
ToString(Bytecode bytecode,OperandScale operand_scale)33 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
34 static const char kSeparator = '.';
35
36 std::string value(ToString(bytecode));
37 if (operand_scale > OperandScale::kSingle) {
38 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
39 std::string suffix = ToString(prefix_bytecode);
40 return value.append(1, kSeparator).append(suffix);
41 } else {
42 return value;
43 }
44 }
45
46 // static
AccumulatorUseToString(AccumulatorUse accumulator_use)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
OperandTypeToString(OperandType operand_type)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
OperandScaleToString(OperandScale operand_scale)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
OperandSizeToString(OperandSize operand_size)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
FromByte(uint8_t value)105 Bytecode Bytecodes::FromByte(uint8_t value) {
106 Bytecode bytecode = static_cast<Bytecode>(value);
107 DCHECK(bytecode <= Bytecode::kLast);
108 return bytecode;
109 }
110
111 // static
GetDebugBreak(Bytecode bytecode)112 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
113 DCHECK(!IsDebugBreak(bytecode));
114 if (bytecode == Bytecode::kWide) {
115 return Bytecode::kDebugBreakWide;
116 }
117 if (bytecode == Bytecode::kExtraWide) {
118 return Bytecode::kDebugBreakExtraWide;
119 }
120 int bytecode_size = Size(bytecode, OperandScale::kSingle);
121 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \
122 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
123 return Bytecode::k##Name; \
124 }
125 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
126 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
127 UNREACHABLE();
128 return Bytecode::kIllegal;
129 }
130
131 // static
Size(Bytecode bytecode,OperandScale operand_scale)132 int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) {
133 int size = 1;
134 for (int i = 0; i < NumberOfOperands(bytecode); i++) {
135 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale);
136 int delta = static_cast<int>(operand_size);
137 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta)));
138 size += delta;
139 }
140 return size;
141 }
142
143 // static
ReturnCount(Bytecode bytecode)144 size_t Bytecodes::ReturnCount(Bytecode bytecode) {
145 return bytecode == Bytecode::kReturn ? 1 : 0;
146 }
147
148 // static
NumberOfOperands(Bytecode bytecode)149 int Bytecodes::NumberOfOperands(Bytecode bytecode) {
150 DCHECK(bytecode <= Bytecode::kLast);
151 switch (bytecode) {
152 #define CASE(Name, ...) \
153 case Bytecode::k##Name: \
154 return BytecodeTraits<__VA_ARGS__>::kOperandCount;
155 BYTECODE_LIST(CASE)
156 #undef CASE
157 }
158 UNREACHABLE();
159 return 0;
160 }
161
162 // static
NumberOfRegisterOperands(Bytecode bytecode)163 int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
164 DCHECK(bytecode <= Bytecode::kLast);
165 switch (bytecode) {
166 #define CASE(Name, ...) \
167 case Bytecode::k##Name: \
168 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
169 return Name##Trait::kRegisterOperandCount;
170 BYTECODE_LIST(CASE)
171 #undef CASE
172 }
173 UNREACHABLE();
174 return false;
175 }
176
177 // static
OperandScaleToPrefixBytecode(OperandScale operand_scale)178 Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) {
179 switch (operand_scale) {
180 case OperandScale::kQuadruple:
181 return Bytecode::kExtraWide;
182 case OperandScale::kDouble:
183 return Bytecode::kWide;
184 default:
185 UNREACHABLE();
186 return Bytecode::kIllegal;
187 }
188 }
189
190 // static
OperandScaleRequiresPrefixBytecode(OperandScale operand_scale)191 bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
192 return operand_scale != OperandScale::kSingle;
193 }
194
195 // static
PrefixBytecodeToOperandScale(Bytecode bytecode)196 OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) {
197 switch (bytecode) {
198 case Bytecode::kExtraWide:
199 case Bytecode::kDebugBreakExtraWide:
200 return OperandScale::kQuadruple;
201 case Bytecode::kWide:
202 case Bytecode::kDebugBreakWide:
203 return OperandScale::kDouble;
204 default:
205 UNREACHABLE();
206 return OperandScale::kSingle;
207 }
208 }
209
210 // static
GetAccumulatorUse(Bytecode bytecode)211 AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) {
212 DCHECK(bytecode <= Bytecode::kLast);
213 switch (bytecode) {
214 #define CASE(Name, ...) \
215 case Bytecode::k##Name: \
216 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse;
217 BYTECODE_LIST(CASE)
218 #undef CASE
219 }
220 UNREACHABLE();
221 return AccumulatorUse::kNone;
222 }
223
224 // static
ReadsAccumulator(Bytecode bytecode)225 bool Bytecodes::ReadsAccumulator(Bytecode bytecode) {
226 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) ==
227 AccumulatorUse::kRead;
228 }
229
230 // static
WritesAccumulator(Bytecode bytecode)231 bool Bytecodes::WritesAccumulator(Bytecode bytecode) {
232 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) ==
233 AccumulatorUse::kWrite;
234 }
235
236 // static
WritesBooleanToAccumulator(Bytecode bytecode)237 bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) {
238 switch (bytecode) {
239 case Bytecode::kLdaTrue:
240 case Bytecode::kLdaFalse:
241 case Bytecode::kToBooleanLogicalNot:
242 case Bytecode::kLogicalNot:
243 case Bytecode::kTestEqual:
244 case Bytecode::kTestNotEqual:
245 case Bytecode::kTestEqualStrict:
246 case Bytecode::kTestLessThan:
247 case Bytecode::kTestLessThanOrEqual:
248 case Bytecode::kTestGreaterThan:
249 case Bytecode::kTestGreaterThanOrEqual:
250 case Bytecode::kTestInstanceOf:
251 case Bytecode::kTestIn:
252 case Bytecode::kForInDone:
253 return true;
254 default:
255 return false;
256 }
257 }
258
259 // static
IsAccumulatorLoadWithoutEffects(Bytecode bytecode)260 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
261 switch (bytecode) {
262 case Bytecode::kLdaZero:
263 case Bytecode::kLdaSmi:
264 case Bytecode::kLdaUndefined:
265 case Bytecode::kLdaNull:
266 case Bytecode::kLdaTheHole:
267 case Bytecode::kLdaTrue:
268 case Bytecode::kLdaFalse:
269 case Bytecode::kLdaConstant:
270 case Bytecode::kLdar:
271 return true;
272 default:
273 return false;
274 }
275 }
276
277 // static
IsJumpWithoutEffects(Bytecode bytecode)278 bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) {
279 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode);
280 }
281
282 // static
IsRegisterLoadWithoutEffects(Bytecode bytecode)283 bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) {
284 switch (bytecode) {
285 case Bytecode::kMov:
286 case Bytecode::kPopContext:
287 case Bytecode::kPushContext:
288 case Bytecode::kStar:
289 case Bytecode::kLdrUndefined:
290 return true;
291 default:
292 return false;
293 }
294 }
295
296 // static
IsWithoutExternalSideEffects(Bytecode bytecode)297 bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) {
298 // These bytecodes only manipulate interpreter frame state and will
299 // never throw.
300 return (IsAccumulatorLoadWithoutEffects(bytecode) ||
301 IsRegisterLoadWithoutEffects(bytecode) ||
302 bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode));
303 }
304
305 // static
GetOperandType(Bytecode bytecode,int i)306 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
307 DCHECK_LE(bytecode, Bytecode::kLast);
308 DCHECK_LT(i, NumberOfOperands(bytecode));
309 DCHECK_GE(i, 0);
310 return GetOperandTypes(bytecode)[i];
311 }
312
313 // static
GetOperandTypes(Bytecode bytecode)314 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) {
315 DCHECK(bytecode <= Bytecode::kLast);
316 switch (bytecode) {
317 #define CASE(Name, ...) \
318 case Bytecode::k##Name: \
319 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes();
320 BYTECODE_LIST(CASE)
321 #undef CASE
322 }
323 UNREACHABLE();
324 return nullptr;
325 }
326
327 // static
GetOperandTypeInfos(Bytecode bytecode)328 const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) {
329 DCHECK(bytecode <= Bytecode::kLast);
330 switch (bytecode) {
331 #define CASE(Name, ...) \
332 case Bytecode::k##Name: \
333 return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos();
334 BYTECODE_LIST(CASE)
335 #undef CASE
336 }
337 UNREACHABLE();
338 return nullptr;
339 }
340
341 // static
GetOperandSize(Bytecode bytecode,int i,OperandScale operand_scale)342 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i,
343 OperandScale operand_scale) {
344 DCHECK_LT(i, NumberOfOperands(bytecode));
345 return GetOperandSizes(bytecode, operand_scale)[i];
346 }
347
348 // static
GetOperandSizes(Bytecode bytecode,OperandScale operand_scale)349 const OperandSize* Bytecodes::GetOperandSizes(Bytecode bytecode,
350 OperandScale operand_scale) {
351 DCHECK(bytecode <= Bytecode::kLast);
352 switch (bytecode) {
353 #define CASE(Name, ...) \
354 case Bytecode::k##Name: \
355 return BytecodeTraits<__VA_ARGS__>::GetOperandSizes(operand_scale);
356 BYTECODE_LIST(CASE)
357 #undef CASE
358 }
359 UNREACHABLE();
360 return nullptr;
361 }
362
363 // static
GetRegisterOperandBitmap(Bytecode bytecode)364 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
365 DCHECK(bytecode <= Bytecode::kLast);
366 switch (bytecode) {
367 #define CASE(Name, ...) \
368 case Bytecode::k##Name: \
369 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
370 return Name##Trait::kRegisterOperandBitmap;
371 BYTECODE_LIST(CASE)
372 #undef CASE
373 }
374 UNREACHABLE();
375 return false;
376 }
377
378 // static
GetOperandOffset(Bytecode bytecode,int i,OperandScale operand_scale)379 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
380 OperandScale operand_scale) {
381 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
382 // TODO(oth): restore this to a statically determined constant.
383 int offset = 1;
384 for (int operand_index = 0; operand_index < i; ++operand_index) {
385 OperandSize operand_size =
386 GetOperandSize(bytecode, operand_index, operand_scale);
387 offset += static_cast<int>(operand_size);
388 }
389 return offset;
390 }
391
392 // static
SizeOfOperand(OperandType operand_type,OperandScale operand_scale)393 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
394 OperandScale operand_scale) {
395 return static_cast<OperandSize>(
396 ScaledOperandSize(operand_type, operand_scale));
397 }
398
399 // static
IsConditionalJumpImmediate(Bytecode bytecode)400 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
401 return bytecode == Bytecode::kJumpIfTrue ||
402 bytecode == Bytecode::kJumpIfFalse ||
403 bytecode == Bytecode::kJumpIfToBooleanTrue ||
404 bytecode == Bytecode::kJumpIfToBooleanFalse ||
405 bytecode == Bytecode::kJumpIfNotHole ||
406 bytecode == Bytecode::kJumpIfNull ||
407 bytecode == Bytecode::kJumpIfUndefined;
408 }
409
410
411 // static
IsConditionalJumpConstant(Bytecode bytecode)412 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
413 return bytecode == Bytecode::kJumpIfTrueConstant ||
414 bytecode == Bytecode::kJumpIfFalseConstant ||
415 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
416 bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
417 bytecode == Bytecode::kJumpIfNotHoleConstant ||
418 bytecode == Bytecode::kJumpIfNullConstant ||
419 bytecode == Bytecode::kJumpIfUndefinedConstant;
420 }
421
422 // static
IsConditionalJump(Bytecode bytecode)423 bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
424 return IsConditionalJumpImmediate(bytecode) ||
425 IsConditionalJumpConstant(bytecode);
426 }
427
428
429 // static
IsJumpImmediate(Bytecode bytecode)430 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) {
431 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode);
432 }
433
434
435 // static
IsJumpConstant(Bytecode bytecode)436 bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
437 return bytecode == Bytecode::kJumpConstant ||
438 IsConditionalJumpConstant(bytecode);
439 }
440
441 // static
IsJump(Bytecode bytecode)442 bool Bytecodes::IsJump(Bytecode bytecode) {
443 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
444 }
445
446 // static
IsJumpIfToBoolean(Bytecode bytecode)447 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) {
448 return bytecode == Bytecode::kJumpIfToBooleanTrue ||
449 bytecode == Bytecode::kJumpIfToBooleanFalse ||
450 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
451 bytecode == Bytecode::kJumpIfToBooleanFalseConstant;
452 }
453
454 // static
GetJumpWithoutToBoolean(Bytecode bytecode)455 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
456 switch (bytecode) {
457 case Bytecode::kJumpIfToBooleanTrue:
458 return Bytecode::kJumpIfTrue;
459 case Bytecode::kJumpIfToBooleanFalse:
460 return Bytecode::kJumpIfFalse;
461 case Bytecode::kJumpIfToBooleanTrueConstant:
462 return Bytecode::kJumpIfTrueConstant;
463 case Bytecode::kJumpIfToBooleanFalseConstant:
464 return Bytecode::kJumpIfFalseConstant;
465 default:
466 break;
467 }
468 UNREACHABLE();
469 return Bytecode::kIllegal;
470 }
471
472 // static
IsCallOrNew(Bytecode bytecode)473 bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
474 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
475 bytecode == Bytecode::kNew;
476 }
477
478 // static
IsCallRuntime(Bytecode bytecode)479 bool Bytecodes::IsCallRuntime(Bytecode bytecode) {
480 return bytecode == Bytecode::kCallRuntime ||
481 bytecode == Bytecode::kCallRuntimeForPair ||
482 bytecode == Bytecode::kInvokeIntrinsic;
483 }
484
485 // static
IsDebugBreak(Bytecode bytecode)486 bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
487 switch (bytecode) {
488 #define CASE(Name, ...) case Bytecode::k##Name:
489 DEBUG_BREAK_BYTECODE_LIST(CASE);
490 #undef CASE
491 return true;
492 default:
493 break;
494 }
495 return false;
496 }
497
498 // static
IsLdarOrStar(Bytecode bytecode)499 bool Bytecodes::IsLdarOrStar(Bytecode bytecode) {
500 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
501 }
502
503 // static
IsBytecodeWithScalableOperands(Bytecode bytecode)504 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
505 switch (bytecode) {
506 #define CASE(Name, ...) \
507 case Bytecode::k##Name: \
508 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
509 return Name##Trait::IsScalable();
510 BYTECODE_LIST(CASE)
511 #undef CASE
512 }
513 UNREACHABLE();
514 return false;
515 }
516
517 // static
IsPrefixScalingBytecode(Bytecode bytecode)518 bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) {
519 switch (bytecode) {
520 case Bytecode::kExtraWide:
521 case Bytecode::kDebugBreakExtraWide:
522 case Bytecode::kWide:
523 case Bytecode::kDebugBreakWide:
524 return true;
525 default:
526 return false;
527 }
528 }
529
530 // static
IsJumpOrReturn(Bytecode bytecode)531 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
532 return bytecode == Bytecode::kReturn || IsJump(bytecode);
533 }
534
535 // static
IsMaybeRegisterOperandType(OperandType operand_type)536 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
537 return operand_type == OperandType::kMaybeReg;
538 }
539
540 // static
IsRegisterOperandType(OperandType operand_type)541 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
542 switch (operand_type) {
543 #define CASE(Name, _) \
544 case OperandType::k##Name: \
545 return true;
546 REGISTER_OPERAND_TYPE_LIST(CASE)
547 #undef CASE
548 #define CASE(Name, _) \
549 case OperandType::k##Name: \
550 break;
551 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
552 #undef CASE
553 }
554 return false;
555 }
556
557 // static
IsRegisterInputOperandType(OperandType operand_type)558 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
559 switch (operand_type) {
560 #define CASE(Name, _) \
561 case OperandType::k##Name: \
562 return true;
563 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
564 #undef CASE
565 #define CASE(Name, _) \
566 case OperandType::k##Name: \
567 break;
568 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
569 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
570 #undef CASE
571 }
572 return false;
573 }
574
575 // static
IsRegisterOutputOperandType(OperandType operand_type)576 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
577 switch (operand_type) {
578 #define CASE(Name, _) \
579 case OperandType::k##Name: \
580 return true;
581 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
582 #undef CASE
583 #define CASE(Name, _) \
584 case OperandType::k##Name: \
585 break;
586 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
587 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
588 #undef CASE
589 }
590 return false;
591 }
592
593 // static
GetNumberOfRegistersRepresentedBy(OperandType operand_type)594 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
595 switch (operand_type) {
596 case OperandType::kMaybeReg:
597 case OperandType::kReg:
598 case OperandType::kRegOut:
599 return 1;
600 case OperandType::kRegPair:
601 case OperandType::kRegOutPair:
602 return 2;
603 case OperandType::kRegOutTriple:
604 return 3;
605 default:
606 UNREACHABLE();
607 }
608 return 0;
609 }
610
611 // static
IsUnsignedOperandType(OperandType operand_type)612 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
613 switch (operand_type) {
614 #define CASE(Name, _) \
615 case OperandType::k##Name: \
616 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
617 OPERAND_TYPE_LIST(CASE)
618 #undef CASE
619 }
620 UNREACHABLE();
621 return false;
622 }
623
624 // static
SizeForSignedOperand(int value)625 OperandSize Bytecodes::SizeForSignedOperand(int value) {
626 if (value >= kMinInt8 && value <= kMaxInt8) {
627 return OperandSize::kByte;
628 } else if (value >= kMinInt16 && value <= kMaxInt16) {
629 return OperandSize::kShort;
630 } else {
631 return OperandSize::kQuad;
632 }
633 }
634
635 // static
SizeForUnsignedOperand(uint32_t value)636 OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) {
637 if (value <= kMaxUInt8) {
638 return OperandSize::kByte;
639 } else if (value <= kMaxUInt16) {
640 return OperandSize::kShort;
641 } else {
642 return OperandSize::kQuad;
643 }
644 }
645
646 // static
DecodeRegisterOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)647 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start,
648 OperandType operand_type,
649 OperandScale operand_scale) {
650 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
651 int32_t operand =
652 DecodeSignedOperand(operand_start, operand_type, operand_scale);
653 return Register::FromOperand(operand);
654 }
655
656 // static
DecodeSignedOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)657 int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start,
658 OperandType operand_type,
659 OperandScale operand_scale) {
660 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
661 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
662 case OperandSize::kByte:
663 return static_cast<int8_t>(*operand_start);
664 case OperandSize::kShort:
665 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
666 case OperandSize::kQuad:
667 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
668 case OperandSize::kNone:
669 UNREACHABLE();
670 }
671 return 0;
672 }
673
674 // static
DecodeUnsignedOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)675 uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start,
676 OperandType operand_type,
677 OperandScale operand_scale) {
678 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
679 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
680 case OperandSize::kByte:
681 return *operand_start;
682 case OperandSize::kShort:
683 return ReadUnalignedUInt16(operand_start);
684 case OperandSize::kQuad:
685 return ReadUnalignedUInt32(operand_start);
686 case OperandSize::kNone:
687 UNREACHABLE();
688 }
689 return 0;
690 }
691
692 // static
Decode(std::ostream & os,const uint8_t * bytecode_start,int parameter_count)693 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
694 int parameter_count) {
695 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
696 int prefix_offset = 0;
697 OperandScale operand_scale = OperandScale::kSingle;
698 if (IsPrefixScalingBytecode(bytecode)) {
699 prefix_offset = 1;
700 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
701 bytecode = Bytecodes::FromByte(bytecode_start[1]);
702 }
703
704 // Prepare to print bytecode and operands as hex digits.
705 std::ios saved_format(nullptr);
706 saved_format.copyfmt(saved_format);
707 os.fill('0');
708 os.flags(std::ios::hex);
709
710 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
711 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
712 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
713 }
714 os.copyfmt(saved_format);
715
716 const int kBytecodeColumnSize = 6;
717 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
718 os << " ";
719 }
720
721 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
722
723 // Operands for the debug break are from the original instruction.
724 if (IsDebugBreak(bytecode)) return os;
725
726 int number_of_operands = NumberOfOperands(bytecode);
727 int range = 0;
728 for (int i = 0; i < number_of_operands; i++) {
729 OperandType op_type = GetOperandType(bytecode, i);
730 const uint8_t* operand_start =
731 &bytecode_start[prefix_offset +
732 GetOperandOffset(bytecode, i, operand_scale)];
733 switch (op_type) {
734 case interpreter::OperandType::kRegCount:
735 os << "#"
736 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
737 break;
738 case interpreter::OperandType::kIdx:
739 case interpreter::OperandType::kRuntimeId:
740 case interpreter::OperandType::kIntrinsicId:
741 os << "["
742 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
743 << "]";
744 break;
745 case interpreter::OperandType::kImm:
746 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
747 << "]";
748 break;
749 case interpreter::OperandType::kFlag8:
750 os << "#"
751 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
752 break;
753 case interpreter::OperandType::kMaybeReg:
754 case interpreter::OperandType::kReg:
755 case interpreter::OperandType::kRegOut: {
756 Register reg =
757 DecodeRegisterOperand(operand_start, op_type, operand_scale);
758 os << reg.ToString(parameter_count);
759 break;
760 }
761 case interpreter::OperandType::kRegOutTriple:
762 range += 1;
763 case interpreter::OperandType::kRegOutPair:
764 case interpreter::OperandType::kRegPair: {
765 range += 1;
766 Register first_reg =
767 DecodeRegisterOperand(operand_start, op_type, operand_scale);
768 Register last_reg = Register(first_reg.index() + range);
769 os << first_reg.ToString(parameter_count) << "-"
770 << last_reg.ToString(parameter_count);
771 break;
772 }
773 case interpreter::OperandType::kNone:
774 UNREACHABLE();
775 break;
776 }
777 if (i != number_of_operands - 1) {
778 os << ", ";
779 }
780 }
781 return os;
782 }
783
784 // static
BytecodeHasHandler(Bytecode bytecode,OperandScale operand_scale)785 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
786 OperandScale operand_scale) {
787 return operand_scale == OperandScale::kSingle ||
788 Bytecodes::IsBytecodeWithScalableOperands(bytecode);
789 }
790
operator <<(std::ostream & os,const Bytecode & bytecode)791 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
792 return os << Bytecodes::ToString(bytecode);
793 }
794
operator <<(std::ostream & os,const AccumulatorUse & use)795 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) {
796 return os << Bytecodes::AccumulatorUseToString(use);
797 }
798
operator <<(std::ostream & os,const OperandSize & operand_size)799 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
800 return os << Bytecodes::OperandSizeToString(operand_size);
801 }
802
operator <<(std::ostream & os,const OperandScale & operand_scale)803 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) {
804 return os << Bytecodes::OperandScaleToString(operand_scale);
805 }
806
operator <<(std::ostream & os,const OperandType & operand_type)807 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
808 return os << Bytecodes::OperandTypeToString(operand_type);
809 }
810
811 static const int kLastParamRegisterIndex =
812 (InterpreterFrameConstants::kRegisterFileFromFp -
813 InterpreterFrameConstants::kLastParamFromFp) /
814 kPointerSize;
815 static const int kFunctionClosureRegisterIndex =
816 (InterpreterFrameConstants::kRegisterFileFromFp -
817 StandardFrameConstants::kFunctionOffset) /
818 kPointerSize;
819 static const int kCurrentContextRegisterIndex =
820 (InterpreterFrameConstants::kRegisterFileFromFp -
821 StandardFrameConstants::kContextOffset) /
822 kPointerSize;
823 static const int kNewTargetRegisterIndex =
824 (InterpreterFrameConstants::kRegisterFileFromFp -
825 InterpreterFrameConstants::kNewTargetFromFp) /
826 kPointerSize;
827 static const int kBytecodeArrayRegisterIndex =
828 (InterpreterFrameConstants::kRegisterFileFromFp -
829 InterpreterFrameConstants::kBytecodeArrayFromFp) /
830 kPointerSize;
831 static const int kBytecodeOffsetRegisterIndex =
832 (InterpreterFrameConstants::kRegisterFileFromFp -
833 InterpreterFrameConstants::kBytecodeOffsetFromFp) /
834 kPointerSize;
835 static const int kCallerPCOffsetRegisterIndex =
836 (InterpreterFrameConstants::kRegisterFileFromFp -
837 InterpreterFrameConstants::kCallerPCOffsetFromFp) /
838 kPointerSize;
839
FromParameterIndex(int index,int parameter_count)840 Register Register::FromParameterIndex(int index, int parameter_count) {
841 DCHECK_GE(index, 0);
842 DCHECK_LT(index, parameter_count);
843 int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
844 DCHECK_LT(register_index, 0);
845 return Register(register_index);
846 }
847
ToParameterIndex(int parameter_count) const848 int Register::ToParameterIndex(int parameter_count) const {
849 DCHECK(is_parameter());
850 return index() - kLastParamRegisterIndex + parameter_count - 1;
851 }
852
function_closure()853 Register Register::function_closure() {
854 return Register(kFunctionClosureRegisterIndex);
855 }
856
is_function_closure() const857 bool Register::is_function_closure() const {
858 return index() == kFunctionClosureRegisterIndex;
859 }
860
current_context()861 Register Register::current_context() {
862 return Register(kCurrentContextRegisterIndex);
863 }
864
is_current_context() const865 bool Register::is_current_context() const {
866 return index() == kCurrentContextRegisterIndex;
867 }
868
new_target()869 Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
870
is_new_target() const871 bool Register::is_new_target() const {
872 return index() == kNewTargetRegisterIndex;
873 }
874
bytecode_array()875 Register Register::bytecode_array() {
876 return Register(kBytecodeArrayRegisterIndex);
877 }
878
is_bytecode_array() const879 bool Register::is_bytecode_array() const {
880 return index() == kBytecodeArrayRegisterIndex;
881 }
882
bytecode_offset()883 Register Register::bytecode_offset() {
884 return Register(kBytecodeOffsetRegisterIndex);
885 }
886
is_bytecode_offset() const887 bool Register::is_bytecode_offset() const {
888 return index() == kBytecodeOffsetRegisterIndex;
889 }
890
891 // static
virtual_accumulator()892 Register Register::virtual_accumulator() {
893 return Register(kCallerPCOffsetRegisterIndex);
894 }
895
SizeOfOperand() const896 OperandSize Register::SizeOfOperand() const {
897 int32_t operand = ToOperand();
898 if (operand >= kMinInt8 && operand <= kMaxInt8) {
899 return OperandSize::kByte;
900 } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
901 return OperandSize::kShort;
902 } else {
903 return OperandSize::kQuad;
904 }
905 }
906
AreContiguous(Register reg1,Register reg2,Register reg3,Register reg4,Register reg5)907 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
908 Register reg4, Register reg5) {
909 if (reg1.index() + 1 != reg2.index()) {
910 return false;
911 }
912 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
913 return false;
914 }
915 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
916 return false;
917 }
918 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
919 return false;
920 }
921 return true;
922 }
923
ToString(int parameter_count)924 std::string Register::ToString(int parameter_count) {
925 if (is_current_context()) {
926 return std::string("<context>");
927 } else if (is_function_closure()) {
928 return std::string("<closure>");
929 } else if (is_new_target()) {
930 return std::string("<new.target>");
931 } else if (is_parameter()) {
932 int parameter_index = ToParameterIndex(parameter_count);
933 if (parameter_index == 0) {
934 return std::string("<this>");
935 } else {
936 std::ostringstream s;
937 s << "a" << parameter_index - 1;
938 return s.str();
939 }
940 } else {
941 std::ostringstream s;
942 s << "r" << index();
943 return s.str();
944 }
945 }
946
947 } // namespace interpreter
948 } // namespace internal
949 } // namespace v8
950