blob: 44c513893d6660c1542641287487d3fca8f86a96 [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 Murdoch61f157c2016-09-16 13:49:30 +01009#include "src/base/bits.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/frames.h"
11#include "src/interpreter/bytecode-traits.h"
Ben Murdochda12d292016-06-02 14:46:10 +010012#include "src/interpreter/interpreter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013
14namespace v8 {
15namespace internal {
16namespace interpreter {
17
18
19// static
20const 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
Ben Murdochda12d292016-06-02 14:46:10 +010032// static
33std::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
47const 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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061
62// static
63const 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
Ben Murdochda12d292016-06-02 14:46:10 +010075// static
76const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) {
77 switch (operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +010078#define CASE(Name, _) \
79 case OperandScale::k##Name: \
80 return #Name;
81 OPERAND_SCALE_LIST(CASE)
82#undef CASE
Ben Murdochda12d292016-06-02 14:46:10 +010083 }
Ben Murdochc5610432016-08-08 18:44:38 +010084 UNREACHABLE();
Ben Murdochda12d292016-06-02 14:46:10 +010085 return "";
86}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087
88// static
89const 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";
Ben Murdochda12d292016-06-02 14:46:10 +010097 case OperandSize::kQuad:
98 return "Quad";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 }
100 UNREACHABLE();
101 return "";
102}
103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104// static
105Bytecode Bytecodes::FromByte(uint8_t value) {
106 Bytecode bytecode = static_cast<Bytecode>(value);
107 DCHECK(bytecode <= Bytecode::kLast);
108 return bytecode;
109}
110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100112Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100113 DCHECK(!IsDebugBreak(bytecode));
114 if (bytecode == Bytecode::kWide) {
115 return Bytecode::kDebugBreakWide;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100116 }
Ben Murdochda12d292016-06-02 14:46:10 +0100117 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100127 UNREACHABLE();
Ben Murdochda12d292016-06-02 14:46:10 +0100128 return Bytecode::kIllegal;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129}
130
131// static
Ben Murdochda12d292016-06-02 14:46:10 +0100132int 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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 }
Ben Murdochda12d292016-06-02 14:46:10 +0100140 return size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141}
142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143// static
Ben Murdochc5610432016-08-08 18:44:38 +0100144size_t Bytecodes::ReturnCount(Bytecode bytecode) {
145 return bytecode == Bytecode::kReturn ? 1 : 0;
146}
147
148// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149int Bytecodes::NumberOfOperands(Bytecode bytecode) {
150 DCHECK(bytecode <= Bytecode::kLast);
151 switch (bytecode) {
152#define CASE(Name, ...) \
153 case Bytecode::k##Name: \
Ben Murdochda12d292016-06-02 14:46:10 +0100154 return BytecodeTraits<__VA_ARGS__>::kOperandCount;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 BYTECODE_LIST(CASE)
156#undef CASE
157 }
158 UNREACHABLE();
159 return 0;
160}
161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100163int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
164 DCHECK(bytecode <= Bytecode::kLast);
165 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100166#define CASE(Name, ...) \
167 case Bytecode::k##Name: \
168 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100169 return Name##Trait::kRegisterOperandCount;
170 BYTECODE_LIST(CASE)
171#undef CASE
172 }
173 UNREACHABLE();
174 return false;
175}
176
177// static
Ben Murdochda12d292016-06-02 14:46:10 +0100178Bytecode 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
191bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
192 return operand_scale != OperandScale::kSingle;
193}
194
195// static
196OperandScale 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
211AccumulatorUse 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
225bool Bytecodes::ReadsAccumulator(Bytecode bytecode) {
226 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) ==
227 AccumulatorUse::kRead;
228}
229
230// static
231bool Bytecodes::WritesAccumulator(Bytecode bytecode) {
232 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) ==
233 AccumulatorUse::kWrite;
234}
235
236// static
Ben Murdochc5610432016-08-08 18:44:38 +0100237bool 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
260bool 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
Ben Murdoch61f157c2016-09-16 13:49:30 +0100278bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) {
279 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode);
280}
281
282// static
283bool 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
297bool 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
Ben Murdochc5610432016-08-08 18:44:38 +0100307 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
314const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 DCHECK(bytecode <= Bytecode::kLast);
316 switch (bytecode) {
317#define CASE(Name, ...) \
318 case Bytecode::k##Name: \
Ben Murdochc5610432016-08-08 18:44:38 +0100319 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 BYTECODE_LIST(CASE)
321#undef CASE
322 }
323 UNREACHABLE();
Ben Murdochc5610432016-08-08 18:44:38 +0100324 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325}
326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327// static
Ben Murdoch61f157c2016-09-16 13:49:30 +0100328const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) {
Ben Murdochc5610432016-08-08 18:44:38 +0100329 DCHECK(bytecode <= Bytecode::kLast);
330 switch (bytecode) {
331#define CASE(Name, ...) \
332 case Bytecode::k##Name: \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100333 return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos();
Ben Murdochc5610432016-08-08 18:44:38 +0100334 BYTECODE_LIST(CASE)
335#undef CASE
336 }
337 UNREACHABLE();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100338 return nullptr;
339}
340
341// static
342OperandSize 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
349const 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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361}
362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100364int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
365 DCHECK(bytecode <= Bytecode::kLast);
366 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100367#define CASE(Name, ...) \
368 case Bytecode::k##Name: \
369 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100370 return Name##Trait::kRegisterOperandBitmap;
371 BYTECODE_LIST(CASE)
372#undef CASE
373 }
374 UNREACHABLE();
375 return false;
376}
377
378// static
Ben Murdochda12d292016-06-02 14:46:10 +0100379int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
380 OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100381 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
Ben Murdochda12d292016-06-02 14:46:10 +0100382 // 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 }
Ben Murdochda12d292016-06-02 14:46:10 +0100389 return offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390}
391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392// static
Ben Murdochda12d292016-06-02 14:46:10 +0100393OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
394 OperandScale operand_scale) {
395 return static_cast<OperandSize>(
396 ScaledOperandSize(operand_type, operand_scale));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397}
398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399// static
400bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
401 return bytecode == Bytecode::kJumpIfTrue ||
402 bytecode == Bytecode::kJumpIfFalse ||
403 bytecode == Bytecode::kJumpIfToBooleanTrue ||
404 bytecode == Bytecode::kJumpIfToBooleanFalse ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100405 bytecode == Bytecode::kJumpIfNotHole ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 bytecode == Bytecode::kJumpIfNull ||
407 bytecode == Bytecode::kJumpIfUndefined;
408}
409
410
411// static
412bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
413 return bytecode == Bytecode::kJumpIfTrueConstant ||
414 bytecode == Bytecode::kJumpIfFalseConstant ||
415 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
416 bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100417 bytecode == Bytecode::kJumpIfNotHoleConstant ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418 bytecode == Bytecode::kJumpIfNullConstant ||
419 bytecode == Bytecode::kJumpIfUndefinedConstant;
420}
421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422// static
423bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
424 return IsConditionalJumpImmediate(bytecode) ||
Ben Murdochda12d292016-06-02 14:46:10 +0100425 IsConditionalJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426}
427
428
429// static
430bool Bytecodes::IsJumpImmediate(Bytecode bytecode) {
431 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode);
432}
433
434
435// static
436bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
437 return bytecode == Bytecode::kJumpConstant ||
438 IsConditionalJumpConstant(bytecode);
439}
440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441// static
442bool Bytecodes::IsJump(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100443 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444}
445
Ben Murdochc5610432016-08-08 18:44:38 +0100446// static
447bool 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
455Bytecode 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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471
472// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100473bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
474 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
Ben Murdochda12d292016-06-02 14:46:10 +0100475 bytecode == Bytecode::kNew;
476}
477
478// static
479bool Bytecodes::IsCallRuntime(Bytecode bytecode) {
480 return bytecode == Bytecode::kCallRuntime ||
481 bytecode == Bytecode::kCallRuntimeForPair ||
482 bytecode == Bytecode::kInvokeIntrinsic;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100483}
484
485// static
486bool 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
Ben Murdochc5610432016-08-08 18:44:38 +0100499bool Bytecodes::IsLdarOrStar(Bytecode bytecode) {
500 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
501}
502
503// static
Ben Murdochda12d292016-06-02 14:46:10 +0100504bool 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
518bool 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
532 return bytecode == Bytecode::kReturn || IsJump(bytecode);
533}
534
Ben Murdoch097c5b22016-05-18 11:27:45 +0100535// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100536bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100537 return operand_type == OperandType::kMaybeReg;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100538}
539
540// static
541bool 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
558bool 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
576bool 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
Ben Murdochda12d292016-06-02 14:46:10 +0100593// static
Ben Murdochc5610432016-08-08 18:44:38 +0100594int 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
Ben Murdochda12d292016-06-02 14:46:10 +0100612bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
613 switch (operand_type) {
614#define CASE(Name, _) \
615 case OperandType::k##Name: \
Ben Murdoch61f157c2016-09-16 13:49:30 +0100616 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
Ben Murdochda12d292016-06-02 14:46:10 +0100617 OPERAND_TYPE_LIST(CASE)
618#undef CASE
Ben Murdoch097c5b22016-05-18 11:27:45 +0100619 }
Ben Murdochda12d292016-06-02 14:46:10 +0100620 UNREACHABLE();
621 return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100622}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100623
Ben Murdochda12d292016-06-02 14:46:10 +0100624// static
Ben Murdochc5610432016-08-08 18:44:38 +0100625OperandSize Bytecodes::SizeForSignedOperand(int value) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100626 if (value >= kMinInt8 && value <= kMaxInt8) {
Ben Murdochc5610432016-08-08 18:44:38 +0100627 return OperandSize::kByte;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100628 } else if (value >= kMinInt16 && value <= kMaxInt16) {
Ben Murdochc5610432016-08-08 18:44:38 +0100629 return OperandSize::kShort;
630 } else {
631 return OperandSize::kQuad;
632 }
633}
634
635// static
Ben Murdoch61f157c2016-09-16 13:49:30 +0100636OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) {
Ben Murdochc5610432016-08-08 18:44:38 +0100637 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
Ben Murdochda12d292016-06-02 14:46:10 +0100646// static
647Register 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
657int32_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
675uint32_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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691
692// static
693std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
694 int parameter_count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
Ben Murdochda12d292016-06-02 14:46:10 +0100696 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]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 }
Ben Murdochda12d292016-06-02 14:46:10 +0100703
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 const int kBytecodeColumnSize = 6;
Ben Murdochda12d292016-06-02 14:46:10 +0100717 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 os << " ";
719 }
720
Ben Murdochda12d292016-06-02 14:46:10 +0100721 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722
Ben Murdoch097c5b22016-05-18 11:27:45 +0100723 // Operands for the debug break are from the original instruction.
724 if (IsDebugBreak(bytecode)) return os;
725
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726 int number_of_operands = NumberOfOperands(bytecode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100727 int range = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 for (int i = 0; i < number_of_operands; i++) {
729 OperandType op_type = GetOperandType(bytecode, i);
730 const uint8_t* operand_start =
Ben Murdochda12d292016-06-02 14:46:10 +0100731 &bytecode_start[prefix_offset +
732 GetOperandOffset(bytecode, i, operand_scale)];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000733 switch (op_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100734 case interpreter::OperandType::kRegCount:
735 os << "#"
736 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100738 case interpreter::OperandType::kIdx:
739 case interpreter::OperandType::kRuntimeId:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100740 case interpreter::OperandType::kIntrinsicId:
Ben Murdochda12d292016-06-02 14:46:10 +0100741 os << "["
742 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
743 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000744 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100745 case interpreter::OperandType::kImm:
746 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
747 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100749 case interpreter::OperandType::kFlag8:
750 os << "#"
751 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100753 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);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100758 os << reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 break;
760 }
Ben Murdochda12d292016-06-02 14:46:10 +0100761 case interpreter::OperandType::kRegOutTriple:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100762 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100763 case interpreter::OperandType::kRegOutPair:
764 case interpreter::OperandType::kRegPair: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100766 Register first_reg =
767 DecodeRegisterOperand(operand_start, op_type, operand_scale);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100768 Register last_reg = Register(first_reg.index() + range);
769 os << first_reg.ToString(parameter_count) << "-"
770 << last_reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000771 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
Ben Murdochda12d292016-06-02 14:46:10 +0100784// static
785bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
786 OperandScale operand_scale) {
787 return operand_scale == OperandScale::kSingle ||
788 Bytecodes::IsBytecodeWithScalableOperands(bytecode);
789}
790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
792 return os << Bytecodes::ToString(bytecode);
793}
794
Ben Murdochda12d292016-06-02 14:46:10 +0100795std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) {
796 return os << Bytecodes::AccumulatorUseToString(use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797}
798
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
800 return os << Bytecodes::OperandSizeToString(operand_size);
801}
802
Ben Murdochda12d292016-06-02 14:46:10 +0100803std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) {
804 return os << Bytecodes::OperandScaleToString(operand_scale);
805}
806
807std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
808 return os << Bytecodes::OperandTypeToString(operand_type);
809}
810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811static const int kLastParamRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100812 (InterpreterFrameConstants::kRegisterFileFromFp -
813 InterpreterFrameConstants::kLastParamFromFp) /
814 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815static const int kFunctionClosureRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100816 (InterpreterFrameConstants::kRegisterFileFromFp -
817 StandardFrameConstants::kFunctionOffset) /
818 kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100819static const int kCurrentContextRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100820 (InterpreterFrameConstants::kRegisterFileFromFp -
821 StandardFrameConstants::kContextOffset) /
822 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823static const int kNewTargetRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100824 (InterpreterFrameConstants::kRegisterFileFromFp -
825 InterpreterFrameConstants::kNewTargetFromFp) /
826 kPointerSize;
827static const int kBytecodeArrayRegisterIndex =
828 (InterpreterFrameConstants::kRegisterFileFromFp -
829 InterpreterFrameConstants::kBytecodeArrayFromFp) /
830 kPointerSize;
831static const int kBytecodeOffsetRegisterIndex =
832 (InterpreterFrameConstants::kRegisterFileFromFp -
833 InterpreterFrameConstants::kBytecodeOffsetFromFp) /
834 kPointerSize;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100835static const int kCallerPCOffsetRegisterIndex =
836 (InterpreterFrameConstants::kRegisterFileFromFp -
837 InterpreterFrameConstants::kCallerPCOffsetFromFp) /
838 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839
840Register Register::FromParameterIndex(int index, int parameter_count) {
841 DCHECK_GE(index, 0);
842 DCHECK_LT(index, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
844 DCHECK_LT(register_index, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 return Register(register_index);
846}
847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848int Register::ToParameterIndex(int parameter_count) const {
849 DCHECK(is_parameter());
850 return index() - kLastParamRegisterIndex + parameter_count - 1;
851}
852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853Register Register::function_closure() {
854 return Register(kFunctionClosureRegisterIndex);
855}
856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857bool Register::is_function_closure() const {
858 return index() == kFunctionClosureRegisterIndex;
859}
860
Ben Murdoch097c5b22016-05-18 11:27:45 +0100861Register Register::current_context() {
862 return Register(kCurrentContextRegisterIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863}
864
Ben Murdoch097c5b22016-05-18 11:27:45 +0100865bool Register::is_current_context() const {
866 return index() == kCurrentContextRegisterIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867}
868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
870
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871bool Register::is_new_target() const {
872 return index() == kNewTargetRegisterIndex;
873}
874
Ben Murdochc5610432016-08-08 18:44:38 +0100875Register Register::bytecode_array() {
876 return Register(kBytecodeArrayRegisterIndex);
877}
878
879bool Register::is_bytecode_array() const {
880 return index() == kBytecodeArrayRegisterIndex;
881}
882
883Register Register::bytecode_offset() {
884 return Register(kBytecodeOffsetRegisterIndex);
885}
886
887bool Register::is_bytecode_offset() const {
888 return index() == kBytecodeOffsetRegisterIndex;
889}
890
Ben Murdoch61f157c2016-09-16 13:49:30 +0100891// static
892Register Register::virtual_accumulator() {
893 return Register(kCallerPCOffsetRegisterIndex);
894}
895
Ben Murdochc5610432016-08-08 18:44:38 +0100896OperandSize 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907bool 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100924std::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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947} // namespace interpreter
948} // namespace internal
949} // namespace v8