• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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