blob: fd27f391aa93636829fd1d689e98ca79aa15b7c0 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdochda12d292016-06-02 14:46:10 +01007#include <iomanip>
8
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/frames.h"
10#include "src/interpreter/bytecode-traits.h"
Ben Murdochda12d292016-06-02 14:46:10 +010011#include "src/interpreter/interpreter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012
13namespace v8 {
14namespace internal {
15namespace interpreter {
16
17
18// static
19const char* Bytecodes::ToString(Bytecode bytecode) {
20 switch (bytecode) {
21#define CASE(Name, ...) \
22 case Bytecode::k##Name: \
23 return #Name;
24 BYTECODE_LIST(CASE)
25#undef CASE
26 }
27 UNREACHABLE();
28 return "";
29}
30
Ben Murdochda12d292016-06-02 14:46:10 +010031// static
32std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
33 static const char kSeparator = '.';
34
35 std::string value(ToString(bytecode));
36 if (operand_scale > OperandScale::kSingle) {
37 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
38 std::string suffix = ToString(prefix_bytecode);
39 return value.append(1, kSeparator).append(suffix);
40 } else {
41 return value;
42 }
43}
44
45// static
46const char* Bytecodes::AccumulatorUseToString(AccumulatorUse accumulator_use) {
47 switch (accumulator_use) {
48 case AccumulatorUse::kNone:
49 return "None";
50 case AccumulatorUse::kRead:
51 return "Read";
52 case AccumulatorUse::kWrite:
53 return "Write";
54 case AccumulatorUse::kReadWrite:
55 return "ReadWrite";
56 }
57 UNREACHABLE();
58 return "";
59}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060
61// static
62const char* Bytecodes::OperandTypeToString(OperandType operand_type) {
63 switch (operand_type) {
64#define CASE(Name, _) \
65 case OperandType::k##Name: \
66 return #Name;
67 OPERAND_TYPE_LIST(CASE)
68#undef CASE
69 }
70 UNREACHABLE();
71 return "";
72}
73
Ben Murdochda12d292016-06-02 14:46:10 +010074// static
75const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) {
76 switch (operand_scale) {
77 case OperandScale::kSingle:
78 return "Single";
79 case OperandScale::kDouble:
80 return "Double";
81 case OperandScale::kQuadruple:
82 return "Quadruple";
83 case OperandScale::kInvalid:
84 UNREACHABLE();
85 }
86 return "";
87}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088
89// static
90const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
91 switch (operand_size) {
92 case OperandSize::kNone:
93 return "None";
94 case OperandSize::kByte:
95 return "Byte";
96 case OperandSize::kShort:
97 return "Short";
Ben Murdochda12d292016-06-02 14:46:10 +010098 case OperandSize::kQuad:
99 return "Quad";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 }
101 UNREACHABLE();
102 return "";
103}
104
105
106// static
107uint8_t Bytecodes::ToByte(Bytecode bytecode) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100108 DCHECK(bytecode <= Bytecode::kLast);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 return static_cast<uint8_t>(bytecode);
110}
111
112
113// static
114Bytecode Bytecodes::FromByte(uint8_t value) {
115 Bytecode bytecode = static_cast<Bytecode>(value);
116 DCHECK(bytecode <= Bytecode::kLast);
117 return bytecode;
118}
119
120
121// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100123 DCHECK(!IsDebugBreak(bytecode));
124 if (bytecode == Bytecode::kWide) {
125 return Bytecode::kDebugBreakWide;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100126 }
Ben Murdochda12d292016-06-02 14:46:10 +0100127 if (bytecode == Bytecode::kExtraWide) {
128 return Bytecode::kDebugBreakExtraWide;
129 }
130 int bytecode_size = Size(bytecode, OperandScale::kSingle);
131#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \
132 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
133 return Bytecode::k##Name; \
134 }
135 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
136#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
Ben Murdoch097c5b22016-05-18 11:27:45 +0100137 UNREACHABLE();
Ben Murdochda12d292016-06-02 14:46:10 +0100138 return Bytecode::kIllegal;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100139}
140
141// static
Ben Murdochda12d292016-06-02 14:46:10 +0100142int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) {
143 int size = 1;
144 for (int i = 0; i < NumberOfOperands(bytecode); i++) {
145 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale);
146 int delta = static_cast<int>(operand_size);
147 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta)));
148 size += delta;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 }
Ben Murdochda12d292016-06-02 14:46:10 +0100150 return size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151}
152
153
154// static
155int Bytecodes::NumberOfOperands(Bytecode bytecode) {
156 DCHECK(bytecode <= Bytecode::kLast);
157 switch (bytecode) {
158#define CASE(Name, ...) \
159 case Bytecode::k##Name: \
Ben Murdochda12d292016-06-02 14:46:10 +0100160 return BytecodeTraits<__VA_ARGS__>::kOperandCount;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 BYTECODE_LIST(CASE)
162#undef CASE
163 }
164 UNREACHABLE();
165 return 0;
166}
167
168
169// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100170int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
171 DCHECK(bytecode <= Bytecode::kLast);
172 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100173#define CASE(Name, ...) \
174 case Bytecode::k##Name: \
175 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100176 return Name##Trait::kRegisterOperandCount;
177 BYTECODE_LIST(CASE)
178#undef CASE
179 }
180 UNREACHABLE();
181 return false;
182}
183
184// static
Ben Murdochda12d292016-06-02 14:46:10 +0100185Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) {
186 switch (operand_scale) {
187 case OperandScale::kQuadruple:
188 return Bytecode::kExtraWide;
189 case OperandScale::kDouble:
190 return Bytecode::kWide;
191 default:
192 UNREACHABLE();
193 return Bytecode::kIllegal;
194 }
195}
196
197// static
198bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
199 return operand_scale != OperandScale::kSingle;
200}
201
202// static
203OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) {
204 switch (bytecode) {
205 case Bytecode::kExtraWide:
206 case Bytecode::kDebugBreakExtraWide:
207 return OperandScale::kQuadruple;
208 case Bytecode::kWide:
209 case Bytecode::kDebugBreakWide:
210 return OperandScale::kDouble;
211 default:
212 UNREACHABLE();
213 return OperandScale::kSingle;
214 }
215}
216
217// static
218AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) {
219 DCHECK(bytecode <= Bytecode::kLast);
220 switch (bytecode) {
221#define CASE(Name, ...) \
222 case Bytecode::k##Name: \
223 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse;
224 BYTECODE_LIST(CASE)
225#undef CASE
226 }
227 UNREACHABLE();
228 return AccumulatorUse::kNone;
229}
230
231// static
232bool Bytecodes::ReadsAccumulator(Bytecode bytecode) {
233 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) ==
234 AccumulatorUse::kRead;
235}
236
237// static
238bool Bytecodes::WritesAccumulator(Bytecode bytecode) {
239 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) ==
240 AccumulatorUse::kWrite;
241}
242
243// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
245 DCHECK(bytecode <= Bytecode::kLast);
246 switch (bytecode) {
247#define CASE(Name, ...) \
248 case Bytecode::k##Name: \
Ben Murdochda12d292016-06-02 14:46:10 +0100249 return BytecodeTraits<__VA_ARGS__>::GetOperandType(i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 BYTECODE_LIST(CASE)
251#undef CASE
252 }
253 UNREACHABLE();
254 return OperandType::kNone;
255}
256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257// static
Ben Murdochda12d292016-06-02 14:46:10 +0100258OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i,
259 OperandScale operand_scale) {
260 OperandType op_type = GetOperandType(bytecode, i);
261 return ScaledOperandSize(op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262}
263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100265int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
266 DCHECK(bytecode <= Bytecode::kLast);
267 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100268#define CASE(Name, ...) \
269 case Bytecode::k##Name: \
270 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100271 return Name##Trait::kRegisterOperandBitmap;
272 BYTECODE_LIST(CASE)
273#undef CASE
274 }
275 UNREACHABLE();
276 return false;
277}
278
279// static
Ben Murdochda12d292016-06-02 14:46:10 +0100280int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
281 OperandScale operand_scale) {
282 // TODO(oth): restore this to a statically determined constant.
283 int offset = 1;
284 for (int operand_index = 0; operand_index < i; ++operand_index) {
285 OperandSize operand_size =
286 GetOperandSize(bytecode, operand_index, operand_scale);
287 offset += static_cast<int>(operand_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 }
Ben Murdochda12d292016-06-02 14:46:10 +0100289 return offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290}
291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292// static
Ben Murdochda12d292016-06-02 14:46:10 +0100293OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
294 OperandScale operand_scale) {
295 return static_cast<OperandSize>(
296 ScaledOperandSize(operand_type, operand_scale));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297}
298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299// static
300bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
301 return bytecode == Bytecode::kJumpIfTrue ||
302 bytecode == Bytecode::kJumpIfFalse ||
303 bytecode == Bytecode::kJumpIfToBooleanTrue ||
304 bytecode == Bytecode::kJumpIfToBooleanFalse ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 bytecode == Bytecode::kJumpIfNotHole ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 bytecode == Bytecode::kJumpIfNull ||
307 bytecode == Bytecode::kJumpIfUndefined;
308}
309
310
311// static
312bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
313 return bytecode == Bytecode::kJumpIfTrueConstant ||
314 bytecode == Bytecode::kJumpIfFalseConstant ||
315 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
316 bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100317 bytecode == Bytecode::kJumpIfNotHoleConstant ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 bytecode == Bytecode::kJumpIfNullConstant ||
319 bytecode == Bytecode::kJumpIfUndefinedConstant;
320}
321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322// static
323bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
324 return IsConditionalJumpImmediate(bytecode) ||
Ben Murdochda12d292016-06-02 14:46:10 +0100325 IsConditionalJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326}
327
328
329// static
330bool Bytecodes::IsJumpImmediate(Bytecode bytecode) {
331 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode);
332}
333
334
335// static
336bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
337 return bytecode == Bytecode::kJumpConstant ||
338 IsConditionalJumpConstant(bytecode);
339}
340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341// static
342bool Bytecodes::IsJump(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100343 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344}
345
346
347// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100348bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
349 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
Ben Murdochda12d292016-06-02 14:46:10 +0100350 bytecode == Bytecode::kNew;
351}
352
353// static
354bool Bytecodes::IsCallRuntime(Bytecode bytecode) {
355 return bytecode == Bytecode::kCallRuntime ||
356 bytecode == Bytecode::kCallRuntimeForPair ||
357 bytecode == Bytecode::kInvokeIntrinsic;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100358}
359
360// static
361bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
362 switch (bytecode) {
363#define CASE(Name, ...) case Bytecode::k##Name:
364 DEBUG_BREAK_BYTECODE_LIST(CASE);
365#undef CASE
366 return true;
367 default:
368 break;
369 }
370 return false;
371}
372
373// static
Ben Murdochda12d292016-06-02 14:46:10 +0100374bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
375 switch (bytecode) {
376#define CASE(Name, ...) \
377 case Bytecode::k##Name: \
378 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
379 return Name##Trait::IsScalable();
380 BYTECODE_LIST(CASE)
381#undef CASE
382 }
383 UNREACHABLE();
384 return false;
385}
386
387// static
388bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) {
389 switch (bytecode) {
390 case Bytecode::kExtraWide:
391 case Bytecode::kDebugBreakExtraWide:
392 case Bytecode::kWide:
393 case Bytecode::kDebugBreakWide:
394 return true;
395 default:
396 return false;
397 }
398}
399
400// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
402 return bytecode == Bytecode::kReturn || IsJump(bytecode);
403}
404
Ben Murdoch097c5b22016-05-18 11:27:45 +0100405// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100406bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100407 return operand_type == OperandType::kMaybeReg;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100408}
409
410// static
411bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
412 switch (operand_type) {
413#define CASE(Name, _) \
414 case OperandType::k##Name: \
415 return true;
416 REGISTER_OPERAND_TYPE_LIST(CASE)
417#undef CASE
418#define CASE(Name, _) \
419 case OperandType::k##Name: \
420 break;
421 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
422#undef CASE
423 }
424 return false;
425}
426
427// static
428bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
429 switch (operand_type) {
430#define CASE(Name, _) \
431 case OperandType::k##Name: \
432 return true;
433 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
434#undef CASE
435#define CASE(Name, _) \
436 case OperandType::k##Name: \
437 break;
438 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
439 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
440#undef CASE
441 }
442 return false;
443}
444
445// static
446bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
447 switch (operand_type) {
448#define CASE(Name, _) \
449 case OperandType::k##Name: \
450 return true;
451 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
452#undef CASE
453#define CASE(Name, _) \
454 case OperandType::k##Name: \
455 break;
456 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
457 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
458#undef CASE
459 }
460 return false;
461}
462
Ben Murdochda12d292016-06-02 14:46:10 +0100463// static
464bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
465 switch (operand_type) {
466#define CASE(Name, _) \
467 case OperandType::k##Name: \
468 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned;
469 OPERAND_TYPE_LIST(CASE)
470#undef CASE
Ben Murdoch097c5b22016-05-18 11:27:45 +0100471 }
Ben Murdochda12d292016-06-02 14:46:10 +0100472 UNREACHABLE();
473 return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100474}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100475
Ben Murdochda12d292016-06-02 14:46:10 +0100476// static
477OperandScale Bytecodes::NextOperandScale(OperandScale operand_scale) {
478 DCHECK(operand_scale >= OperandScale::kSingle &&
479 operand_scale <= OperandScale::kMaxValid);
480 return static_cast<OperandScale>(2 * static_cast<int>(operand_scale));
481}
482
483// static
484Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start,
485 OperandType operand_type,
486 OperandScale operand_scale) {
487 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
488 int32_t operand =
489 DecodeSignedOperand(operand_start, operand_type, operand_scale);
490 return Register::FromOperand(operand);
491}
492
493// static
494int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start,
495 OperandType operand_type,
496 OperandScale operand_scale) {
497 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
498 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
499 case OperandSize::kByte:
500 return static_cast<int8_t>(*operand_start);
501 case OperandSize::kShort:
502 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
503 case OperandSize::kQuad:
504 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
505 case OperandSize::kNone:
506 UNREACHABLE();
507 }
508 return 0;
509}
510
511// static
512uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start,
513 OperandType operand_type,
514 OperandScale operand_scale) {
515 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
516 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
517 case OperandSize::kByte:
518 return *operand_start;
519 case OperandSize::kShort:
520 return ReadUnalignedUInt16(operand_start);
521 case OperandSize::kQuad:
522 return ReadUnalignedUInt32(operand_start);
523 case OperandSize::kNone:
524 UNREACHABLE();
525 }
526 return 0;
527}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528
529// static
530std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
531 int parameter_count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
Ben Murdochda12d292016-06-02 14:46:10 +0100533 int prefix_offset = 0;
534 OperandScale operand_scale = OperandScale::kSingle;
535 if (IsPrefixScalingBytecode(bytecode)) {
536 prefix_offset = 1;
537 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
538 bytecode = Bytecodes::FromByte(bytecode_start[1]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 }
Ben Murdochda12d292016-06-02 14:46:10 +0100540
541 // Prepare to print bytecode and operands as hex digits.
542 std::ios saved_format(nullptr);
543 saved_format.copyfmt(saved_format);
544 os.fill('0');
545 os.flags(std::ios::hex);
546
547 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
548 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
549 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
550 }
551 os.copyfmt(saved_format);
552
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553 const int kBytecodeColumnSize = 6;
Ben Murdochda12d292016-06-02 14:46:10 +0100554 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 os << " ";
556 }
557
Ben Murdochda12d292016-06-02 14:46:10 +0100558 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559
Ben Murdoch097c5b22016-05-18 11:27:45 +0100560 // Operands for the debug break are from the original instruction.
561 if (IsDebugBreak(bytecode)) return os;
562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 int number_of_operands = NumberOfOperands(bytecode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100564 int range = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 for (int i = 0; i < number_of_operands; i++) {
566 OperandType op_type = GetOperandType(bytecode, i);
567 const uint8_t* operand_start =
Ben Murdochda12d292016-06-02 14:46:10 +0100568 &bytecode_start[prefix_offset +
569 GetOperandOffset(bytecode, i, operand_scale)];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 switch (op_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100571 case interpreter::OperandType::kRegCount:
572 os << "#"
573 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100575 case interpreter::OperandType::kIdx:
576 case interpreter::OperandType::kRuntimeId:
577 os << "["
578 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
579 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100581 case interpreter::OperandType::kImm:
582 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
583 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100585 case interpreter::OperandType::kFlag8:
586 os << "#"
587 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100589 case interpreter::OperandType::kMaybeReg:
590 case interpreter::OperandType::kReg:
591 case interpreter::OperandType::kRegOut: {
592 Register reg =
593 DecodeRegisterOperand(operand_start, op_type, operand_scale);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100594 os << reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 break;
596 }
Ben Murdochda12d292016-06-02 14:46:10 +0100597 case interpreter::OperandType::kRegOutTriple:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100598 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100599 case interpreter::OperandType::kRegOutPair:
600 case interpreter::OperandType::kRegPair: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100601 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100602 Register first_reg =
603 DecodeRegisterOperand(operand_start, op_type, operand_scale);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100604 Register last_reg = Register(first_reg.index() + range);
605 os << first_reg.ToString(parameter_count) << "-"
606 << last_reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 break;
608 }
609 case interpreter::OperandType::kNone:
610 UNREACHABLE();
611 break;
612 }
613 if (i != number_of_operands - 1) {
614 os << ", ";
615 }
616 }
617 return os;
618}
619
Ben Murdochda12d292016-06-02 14:46:10 +0100620// static
621bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
622 OperandScale operand_scale) {
623 return operand_scale == OperandScale::kSingle ||
624 Bytecodes::IsBytecodeWithScalableOperands(bytecode);
625}
626
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
628 return os << Bytecodes::ToString(bytecode);
629}
630
Ben Murdochda12d292016-06-02 14:46:10 +0100631std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) {
632 return os << Bytecodes::AccumulatorUseToString(use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633}
634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
636 return os << Bytecodes::OperandSizeToString(operand_size);
637}
638
Ben Murdochda12d292016-06-02 14:46:10 +0100639std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) {
640 return os << Bytecodes::OperandScaleToString(operand_scale);
641}
642
643std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
644 return os << Bytecodes::OperandTypeToString(operand_type);
645}
646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647static const int kLastParamRegisterIndex =
648 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
649static const int kFunctionClosureRegisterIndex =
650 -InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100651static const int kCurrentContextRegisterIndex =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 -InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize;
653static const int kNewTargetRegisterIndex =
654 -InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize;
655
Ben Murdoch097c5b22016-05-18 11:27:45 +0100656bool Register::is_byte_operand() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100657 return index_ >= -kMaxInt8 && index_ <= -kMinInt8;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100658}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659
Ben Murdoch097c5b22016-05-18 11:27:45 +0100660bool Register::is_short_operand() const {
Ben Murdochda12d292016-06-02 14:46:10 +0100661 return index_ >= -kMaxInt16 && index_ <= -kMinInt16;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100662}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663
664Register Register::FromParameterIndex(int index, int parameter_count) {
665 DCHECK_GE(index, 0);
666 DCHECK_LT(index, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667 int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
668 DCHECK_LT(register_index, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 return Register(register_index);
670}
671
672
673int Register::ToParameterIndex(int parameter_count) const {
674 DCHECK(is_parameter());
675 return index() - kLastParamRegisterIndex + parameter_count - 1;
676}
677
678
679Register Register::function_closure() {
680 return Register(kFunctionClosureRegisterIndex);
681}
682
683
684bool Register::is_function_closure() const {
685 return index() == kFunctionClosureRegisterIndex;
686}
687
688
Ben Murdoch097c5b22016-05-18 11:27:45 +0100689Register Register::current_context() {
690 return Register(kCurrentContextRegisterIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691}
692
693
Ben Murdoch097c5b22016-05-18 11:27:45 +0100694bool Register::is_current_context() const {
695 return index() == kCurrentContextRegisterIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696}
697
698
699Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
700
701
702bool Register::is_new_target() const {
703 return index() == kNewTargetRegisterIndex;
704}
705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
707 Register reg4, Register reg5) {
708 if (reg1.index() + 1 != reg2.index()) {
709 return false;
710 }
711 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
712 return false;
713 }
714 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
715 return false;
716 }
717 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
718 return false;
719 }
720 return true;
721}
722
Ben Murdoch097c5b22016-05-18 11:27:45 +0100723std::string Register::ToString(int parameter_count) {
724 if (is_current_context()) {
725 return std::string("<context>");
726 } else if (is_function_closure()) {
727 return std::string("<closure>");
728 } else if (is_new_target()) {
729 return std::string("<new.target>");
730 } else if (is_parameter()) {
731 int parameter_index = ToParameterIndex(parameter_count);
732 if (parameter_index == 0) {
733 return std::string("<this>");
734 } else {
735 std::ostringstream s;
736 s << "a" << parameter_index - 1;
737 return s.str();
738 }
739 } else {
740 std::ostringstream s;
741 s << "r" << index();
742 return s.str();
743 }
744}
745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746} // namespace interpreter
747} // namespace internal
748} // namespace v8