blob: 5a67847a45c66a32443993ee62bbd67aaa5e43e2 [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) {
Ben Murdochc5610432016-08-08 18:44:38 +010077#define CASE(Name, _) \
78 case OperandScale::k##Name: \
79 return #Name;
80 OPERAND_SCALE_LIST(CASE)
81#undef CASE
Ben Murdochda12d292016-06-02 14:46:10 +010082 }
Ben Murdochc5610432016-08-08 18:44:38 +010083 UNREACHABLE();
Ben Murdochda12d292016-06-02 14:46:10 +010084 return "";
85}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086
87// static
88const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
89 switch (operand_size) {
90 case OperandSize::kNone:
91 return "None";
92 case OperandSize::kByte:
93 return "Byte";
94 case OperandSize::kShort:
95 return "Short";
Ben Murdochda12d292016-06-02 14:46:10 +010096 case OperandSize::kQuad:
97 return "Quad";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 }
99 UNREACHABLE();
100 return "";
101}
102
103
104// static
105uint8_t Bytecodes::ToByte(Bytecode bytecode) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100106 DCHECK(bytecode <= Bytecode::kLast);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 return static_cast<uint8_t>(bytecode);
108}
109
110
111// static
112Bytecode Bytecodes::FromByte(uint8_t value) {
113 Bytecode bytecode = static_cast<Bytecode>(value);
114 DCHECK(bytecode <= Bytecode::kLast);
115 return bytecode;
116}
117
118
119// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100120Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100121 DCHECK(!IsDebugBreak(bytecode));
122 if (bytecode == Bytecode::kWide) {
123 return Bytecode::kDebugBreakWide;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 }
Ben Murdochda12d292016-06-02 14:46:10 +0100125 if (bytecode == Bytecode::kExtraWide) {
126 return Bytecode::kDebugBreakExtraWide;
127 }
128 int bytecode_size = Size(bytecode, OperandScale::kSingle);
129#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \
130 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
131 return Bytecode::k##Name; \
132 }
133 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
134#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
Ben Murdoch097c5b22016-05-18 11:27:45 +0100135 UNREACHABLE();
Ben Murdochda12d292016-06-02 14:46:10 +0100136 return Bytecode::kIllegal;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100137}
138
139// static
Ben Murdochda12d292016-06-02 14:46:10 +0100140int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) {
141 int size = 1;
142 for (int i = 0; i < NumberOfOperands(bytecode); i++) {
143 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale);
144 int delta = static_cast<int>(operand_size);
145 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta)));
146 size += delta;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 }
Ben Murdochda12d292016-06-02 14:46:10 +0100148 return size;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149}
150
151
152// static
Ben Murdochc5610432016-08-08 18:44:38 +0100153size_t Bytecodes::ReturnCount(Bytecode bytecode) {
154 return bytecode == Bytecode::kReturn ? 1 : 0;
155}
156
157// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158int Bytecodes::NumberOfOperands(Bytecode bytecode) {
159 DCHECK(bytecode <= Bytecode::kLast);
160 switch (bytecode) {
161#define CASE(Name, ...) \
162 case Bytecode::k##Name: \
Ben Murdochda12d292016-06-02 14:46:10 +0100163 return BytecodeTraits<__VA_ARGS__>::kOperandCount;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 BYTECODE_LIST(CASE)
165#undef CASE
166 }
167 UNREACHABLE();
168 return 0;
169}
170
171
172// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100173int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
174 DCHECK(bytecode <= Bytecode::kLast);
175 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100176#define CASE(Name, ...) \
177 case Bytecode::k##Name: \
178 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100179 return Name##Trait::kRegisterOperandCount;
180 BYTECODE_LIST(CASE)
181#undef CASE
182 }
183 UNREACHABLE();
184 return false;
185}
186
187// static
Ben Murdochda12d292016-06-02 14:46:10 +0100188Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) {
189 switch (operand_scale) {
190 case OperandScale::kQuadruple:
191 return Bytecode::kExtraWide;
192 case OperandScale::kDouble:
193 return Bytecode::kWide;
194 default:
195 UNREACHABLE();
196 return Bytecode::kIllegal;
197 }
198}
199
200// static
201bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
202 return operand_scale != OperandScale::kSingle;
203}
204
205// static
206OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) {
207 switch (bytecode) {
208 case Bytecode::kExtraWide:
209 case Bytecode::kDebugBreakExtraWide:
210 return OperandScale::kQuadruple;
211 case Bytecode::kWide:
212 case Bytecode::kDebugBreakWide:
213 return OperandScale::kDouble;
214 default:
215 UNREACHABLE();
216 return OperandScale::kSingle;
217 }
218}
219
220// static
221AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) {
222 DCHECK(bytecode <= Bytecode::kLast);
223 switch (bytecode) {
224#define CASE(Name, ...) \
225 case Bytecode::k##Name: \
226 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse;
227 BYTECODE_LIST(CASE)
228#undef CASE
229 }
230 UNREACHABLE();
231 return AccumulatorUse::kNone;
232}
233
234// static
235bool Bytecodes::ReadsAccumulator(Bytecode bytecode) {
236 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) ==
237 AccumulatorUse::kRead;
238}
239
240// static
241bool Bytecodes::WritesAccumulator(Bytecode bytecode) {
242 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) ==
243 AccumulatorUse::kWrite;
244}
245
246// static
Ben Murdochc5610432016-08-08 18:44:38 +0100247bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) {
248 switch (bytecode) {
249 case Bytecode::kLdaTrue:
250 case Bytecode::kLdaFalse:
251 case Bytecode::kToBooleanLogicalNot:
252 case Bytecode::kLogicalNot:
253 case Bytecode::kTestEqual:
254 case Bytecode::kTestNotEqual:
255 case Bytecode::kTestEqualStrict:
256 case Bytecode::kTestLessThan:
257 case Bytecode::kTestLessThanOrEqual:
258 case Bytecode::kTestGreaterThan:
259 case Bytecode::kTestGreaterThanOrEqual:
260 case Bytecode::kTestInstanceOf:
261 case Bytecode::kTestIn:
262 case Bytecode::kForInDone:
263 return true;
264 default:
265 return false;
266 }
267}
268
269// static
270bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
271 switch (bytecode) {
272 case Bytecode::kLdaZero:
273 case Bytecode::kLdaSmi:
274 case Bytecode::kLdaUndefined:
275 case Bytecode::kLdaNull:
276 case Bytecode::kLdaTheHole:
277 case Bytecode::kLdaTrue:
278 case Bytecode::kLdaFalse:
279 case Bytecode::kLdaConstant:
280 case Bytecode::kLdar:
281 return true;
282 default:
283 return false;
284 }
285}
286
287// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
Ben Murdochc5610432016-08-08 18:44:38 +0100289 DCHECK_LE(bytecode, Bytecode::kLast);
290 DCHECK_LT(i, NumberOfOperands(bytecode));
291 DCHECK_GE(i, 0);
292 return GetOperandTypes(bytecode)[i];
293}
294
295// static
296const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 DCHECK(bytecode <= Bytecode::kLast);
298 switch (bytecode) {
299#define CASE(Name, ...) \
300 case Bytecode::k##Name: \
Ben Murdochc5610432016-08-08 18:44:38 +0100301 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 BYTECODE_LIST(CASE)
303#undef CASE
304 }
305 UNREACHABLE();
Ben Murdochc5610432016-08-08 18:44:38 +0100306 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307}
308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309// static
Ben Murdochda12d292016-06-02 14:46:10 +0100310OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i,
311 OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100312 DCHECK(bytecode <= Bytecode::kLast);
313 switch (bytecode) {
314#define CASE(Name, ...) \
315 case Bytecode::k##Name: \
316 return BytecodeTraits<__VA_ARGS__>::GetOperandSize(i, operand_scale);
317 BYTECODE_LIST(CASE)
318#undef CASE
319 }
320 UNREACHABLE();
321 return OperandSize::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322}
323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
326 DCHECK(bytecode <= Bytecode::kLast);
327 switch (bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100328#define CASE(Name, ...) \
329 case Bytecode::k##Name: \
330 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 return Name##Trait::kRegisterOperandBitmap;
332 BYTECODE_LIST(CASE)
333#undef CASE
334 }
335 UNREACHABLE();
336 return false;
337}
338
339// static
Ben Murdochda12d292016-06-02 14:46:10 +0100340int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
341 OperandScale operand_scale) {
Ben Murdochc5610432016-08-08 18:44:38 +0100342 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
Ben Murdochda12d292016-06-02 14:46:10 +0100343 // TODO(oth): restore this to a statically determined constant.
344 int offset = 1;
345 for (int operand_index = 0; operand_index < i; ++operand_index) {
346 OperandSize operand_size =
347 GetOperandSize(bytecode, operand_index, operand_scale);
348 offset += static_cast<int>(operand_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 }
Ben Murdochda12d292016-06-02 14:46:10 +0100350 return offset;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351}
352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353// static
Ben Murdochda12d292016-06-02 14:46:10 +0100354OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
355 OperandScale operand_scale) {
356 return static_cast<OperandSize>(
357 ScaledOperandSize(operand_type, operand_scale));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358}
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360// static
361bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
362 return bytecode == Bytecode::kJumpIfTrue ||
363 bytecode == Bytecode::kJumpIfFalse ||
364 bytecode == Bytecode::kJumpIfToBooleanTrue ||
365 bytecode == Bytecode::kJumpIfToBooleanFalse ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 bytecode == Bytecode::kJumpIfNotHole ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 bytecode == Bytecode::kJumpIfNull ||
368 bytecode == Bytecode::kJumpIfUndefined;
369}
370
371
372// static
373bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
374 return bytecode == Bytecode::kJumpIfTrueConstant ||
375 bytecode == Bytecode::kJumpIfFalseConstant ||
376 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
377 bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100378 bytecode == Bytecode::kJumpIfNotHoleConstant ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 bytecode == Bytecode::kJumpIfNullConstant ||
380 bytecode == Bytecode::kJumpIfUndefinedConstant;
381}
382
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383// static
384bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
385 return IsConditionalJumpImmediate(bytecode) ||
Ben Murdochda12d292016-06-02 14:46:10 +0100386 IsConditionalJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387}
388
389
390// static
391bool Bytecodes::IsJumpImmediate(Bytecode bytecode) {
392 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode);
393}
394
395
396// static
397bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
398 return bytecode == Bytecode::kJumpConstant ||
399 IsConditionalJumpConstant(bytecode);
400}
401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402// static
403bool Bytecodes::IsJump(Bytecode bytecode) {
Ben Murdochda12d292016-06-02 14:46:10 +0100404 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405}
406
Ben Murdochc5610432016-08-08 18:44:38 +0100407// static
408bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) {
409 return bytecode == Bytecode::kJumpIfToBooleanTrue ||
410 bytecode == Bytecode::kJumpIfToBooleanFalse ||
411 bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
412 bytecode == Bytecode::kJumpIfToBooleanFalseConstant;
413}
414
415// static
416Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
417 switch (bytecode) {
418 case Bytecode::kJumpIfToBooleanTrue:
419 return Bytecode::kJumpIfTrue;
420 case Bytecode::kJumpIfToBooleanFalse:
421 return Bytecode::kJumpIfFalse;
422 case Bytecode::kJumpIfToBooleanTrueConstant:
423 return Bytecode::kJumpIfTrueConstant;
424 case Bytecode::kJumpIfToBooleanFalseConstant:
425 return Bytecode::kJumpIfFalseConstant;
426 default:
427 break;
428 }
429 UNREACHABLE();
430 return Bytecode::kIllegal;
431}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432
433// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100434bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
435 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
Ben Murdochda12d292016-06-02 14:46:10 +0100436 bytecode == Bytecode::kNew;
437}
438
439// static
440bool Bytecodes::IsCallRuntime(Bytecode bytecode) {
441 return bytecode == Bytecode::kCallRuntime ||
442 bytecode == Bytecode::kCallRuntimeForPair ||
443 bytecode == Bytecode::kInvokeIntrinsic;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100444}
445
446// static
447bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
448 switch (bytecode) {
449#define CASE(Name, ...) case Bytecode::k##Name:
450 DEBUG_BREAK_BYTECODE_LIST(CASE);
451#undef CASE
452 return true;
453 default:
454 break;
455 }
456 return false;
457}
458
459// static
Ben Murdochc5610432016-08-08 18:44:38 +0100460bool Bytecodes::IsLdarOrStar(Bytecode bytecode) {
461 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
462}
463
464// static
Ben Murdochda12d292016-06-02 14:46:10 +0100465bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
466 switch (bytecode) {
467#define CASE(Name, ...) \
468 case Bytecode::k##Name: \
469 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \
470 return Name##Trait::IsScalable();
471 BYTECODE_LIST(CASE)
472#undef CASE
473 }
474 UNREACHABLE();
475 return false;
476}
477
478// static
479bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) {
480 switch (bytecode) {
481 case Bytecode::kExtraWide:
482 case Bytecode::kDebugBreakExtraWide:
483 case Bytecode::kWide:
484 case Bytecode::kDebugBreakWide:
485 return true;
486 default:
487 return false;
488 }
489}
490
491// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
493 return bytecode == Bytecode::kReturn || IsJump(bytecode);
494}
495
Ben Murdoch097c5b22016-05-18 11:27:45 +0100496// static
Ben Murdoch097c5b22016-05-18 11:27:45 +0100497bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100498 return operand_type == OperandType::kMaybeReg;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100499}
500
501// static
502bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
503 switch (operand_type) {
504#define CASE(Name, _) \
505 case OperandType::k##Name: \
506 return true;
507 REGISTER_OPERAND_TYPE_LIST(CASE)
508#undef CASE
509#define CASE(Name, _) \
510 case OperandType::k##Name: \
511 break;
512 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
513#undef CASE
514 }
515 return false;
516}
517
518// static
519bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
520 switch (operand_type) {
521#define CASE(Name, _) \
522 case OperandType::k##Name: \
523 return true;
524 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
525#undef CASE
526#define CASE(Name, _) \
527 case OperandType::k##Name: \
528 break;
529 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
530 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
531#undef CASE
532 }
533 return false;
534}
535
536// static
537bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
538 switch (operand_type) {
539#define CASE(Name, _) \
540 case OperandType::k##Name: \
541 return true;
542 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
543#undef CASE
544#define CASE(Name, _) \
545 case OperandType::k##Name: \
546 break;
547 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
548 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
549#undef CASE
550 }
551 return false;
552}
553
Ben Murdochda12d292016-06-02 14:46:10 +0100554// static
Ben Murdochc5610432016-08-08 18:44:38 +0100555int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
556 switch (operand_type) {
557 case OperandType::kMaybeReg:
558 case OperandType::kReg:
559 case OperandType::kRegOut:
560 return 1;
561 case OperandType::kRegPair:
562 case OperandType::kRegOutPair:
563 return 2;
564 case OperandType::kRegOutTriple:
565 return 3;
566 default:
567 UNREACHABLE();
568 }
569 return 0;
570}
571
572// static
Ben Murdochda12d292016-06-02 14:46:10 +0100573bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
574 switch (operand_type) {
575#define CASE(Name, _) \
576 case OperandType::k##Name: \
577 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned;
578 OPERAND_TYPE_LIST(CASE)
579#undef CASE
Ben Murdoch097c5b22016-05-18 11:27:45 +0100580 }
Ben Murdochda12d292016-06-02 14:46:10 +0100581 UNREACHABLE();
582 return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100583}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100584
Ben Murdochda12d292016-06-02 14:46:10 +0100585// static
Ben Murdochc5610432016-08-08 18:44:38 +0100586OperandSize Bytecodes::SizeForSignedOperand(int value) {
587 if (kMinInt8 <= value && value <= kMaxInt8) {
588 return OperandSize::kByte;
589 } else if (kMinInt16 <= value && value <= kMaxInt16) {
590 return OperandSize::kShort;
591 } else {
592 return OperandSize::kQuad;
593 }
594}
595
596// static
597OperandSize Bytecodes::SizeForUnsignedOperand(int value) {
598 DCHECK_GE(value, 0);
599 if (value <= kMaxUInt8) {
600 return OperandSize::kByte;
601 } else if (value <= kMaxUInt16) {
602 return OperandSize::kShort;
603 } else {
604 return OperandSize::kQuad;
605 }
606}
607
608OperandSize Bytecodes::SizeForUnsignedOperand(size_t value) {
609 if (value <= static_cast<size_t>(kMaxUInt8)) {
610 return OperandSize::kByte;
611 } else if (value <= static_cast<size_t>(kMaxUInt16)) {
612 return OperandSize::kShort;
613 } else if (value <= kMaxUInt32) {
614 return OperandSize::kQuad;
615 } else {
616 UNREACHABLE();
617 return OperandSize::kQuad;
618 }
619}
620
621OperandScale Bytecodes::OperandSizesToScale(OperandSize size0,
622 OperandSize size1,
623 OperandSize size2,
624 OperandSize size3) {
625 OperandSize upper = std::max(size0, size1);
626 OperandSize lower = std::max(size2, size3);
627 OperandSize result = std::max(upper, lower);
628 // Operand sizes have been scaled before calling this function.
629 // Currently all scalable operands are byte sized at
630 // OperandScale::kSingle.
631 STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
632 static_cast<int>(OperandScale::kSingle) &&
633 static_cast<int>(OperandSize::kShort) ==
634 static_cast<int>(OperandScale::kDouble) &&
635 static_cast<int>(OperandSize::kQuad) ==
636 static_cast<int>(OperandScale::kQuadruple));
637 OperandScale operand_scale = static_cast<OperandScale>(result);
638 DCHECK(operand_scale == OperandScale::kSingle ||
639 operand_scale == OperandScale::kDouble ||
640 operand_scale == OperandScale::kQuadruple);
641 return operand_scale;
Ben Murdochda12d292016-06-02 14:46:10 +0100642}
643
644// static
645Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start,
646 OperandType operand_type,
647 OperandScale operand_scale) {
648 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
649 int32_t operand =
650 DecodeSignedOperand(operand_start, operand_type, operand_scale);
651 return Register::FromOperand(operand);
652}
653
654// static
655int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start,
656 OperandType operand_type,
657 OperandScale operand_scale) {
658 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
659 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
660 case OperandSize::kByte:
661 return static_cast<int8_t>(*operand_start);
662 case OperandSize::kShort:
663 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
664 case OperandSize::kQuad:
665 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
666 case OperandSize::kNone:
667 UNREACHABLE();
668 }
669 return 0;
670}
671
672// static
673uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start,
674 OperandType operand_type,
675 OperandScale operand_scale) {
676 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
677 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
678 case OperandSize::kByte:
679 return *operand_start;
680 case OperandSize::kShort:
681 return ReadUnalignedUInt16(operand_start);
682 case OperandSize::kQuad:
683 return ReadUnalignedUInt32(operand_start);
684 case OperandSize::kNone:
685 UNREACHABLE();
686 }
687 return 0;
688}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689
690// static
691std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
692 int parameter_count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
Ben Murdochda12d292016-06-02 14:46:10 +0100694 int prefix_offset = 0;
695 OperandScale operand_scale = OperandScale::kSingle;
696 if (IsPrefixScalingBytecode(bytecode)) {
697 prefix_offset = 1;
698 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
699 bytecode = Bytecodes::FromByte(bytecode_start[1]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 }
Ben Murdochda12d292016-06-02 14:46:10 +0100701
702 // Prepare to print bytecode and operands as hex digits.
703 std::ios saved_format(nullptr);
704 saved_format.copyfmt(saved_format);
705 os.fill('0');
706 os.flags(std::ios::hex);
707
708 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
709 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
710 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
711 }
712 os.copyfmt(saved_format);
713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 const int kBytecodeColumnSize = 6;
Ben Murdochda12d292016-06-02 14:46:10 +0100715 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 os << " ";
717 }
718
Ben Murdochda12d292016-06-02 14:46:10 +0100719 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720
Ben Murdoch097c5b22016-05-18 11:27:45 +0100721 // Operands for the debug break are from the original instruction.
722 if (IsDebugBreak(bytecode)) return os;
723
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 int number_of_operands = NumberOfOperands(bytecode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100725 int range = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726 for (int i = 0; i < number_of_operands; i++) {
727 OperandType op_type = GetOperandType(bytecode, i);
728 const uint8_t* operand_start =
Ben Murdochda12d292016-06-02 14:46:10 +0100729 &bytecode_start[prefix_offset +
730 GetOperandOffset(bytecode, i, operand_scale)];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 switch (op_type) {
Ben Murdochda12d292016-06-02 14:46:10 +0100732 case interpreter::OperandType::kRegCount:
733 os << "#"
734 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100736 case interpreter::OperandType::kIdx:
737 case interpreter::OperandType::kRuntimeId:
738 os << "["
739 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
740 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100742 case interpreter::OperandType::kImm:
743 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
744 << "]";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100746 case interpreter::OperandType::kFlag8:
747 os << "#"
748 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100750 case interpreter::OperandType::kMaybeReg:
751 case interpreter::OperandType::kReg:
752 case interpreter::OperandType::kRegOut: {
753 Register reg =
754 DecodeRegisterOperand(operand_start, op_type, operand_scale);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100755 os << reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 break;
757 }
Ben Murdochda12d292016-06-02 14:46:10 +0100758 case interpreter::OperandType::kRegOutTriple:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100759 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100760 case interpreter::OperandType::kRegOutPair:
761 case interpreter::OperandType::kRegPair: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100762 range += 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100763 Register first_reg =
764 DecodeRegisterOperand(operand_start, op_type, operand_scale);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765 Register last_reg = Register(first_reg.index() + range);
766 os << first_reg.ToString(parameter_count) << "-"
767 << last_reg.ToString(parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 break;
769 }
770 case interpreter::OperandType::kNone:
771 UNREACHABLE();
772 break;
773 }
774 if (i != number_of_operands - 1) {
775 os << ", ";
776 }
777 }
778 return os;
779}
780
Ben Murdochda12d292016-06-02 14:46:10 +0100781// static
782bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
783 OperandScale operand_scale) {
784 return operand_scale == OperandScale::kSingle ||
785 Bytecodes::IsBytecodeWithScalableOperands(bytecode);
786}
787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
789 return os << Bytecodes::ToString(bytecode);
790}
791
Ben Murdochda12d292016-06-02 14:46:10 +0100792std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) {
793 return os << Bytecodes::AccumulatorUseToString(use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794}
795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
797 return os << Bytecodes::OperandSizeToString(operand_size);
798}
799
Ben Murdochda12d292016-06-02 14:46:10 +0100800std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) {
801 return os << Bytecodes::OperandScaleToString(operand_scale);
802}
803
804std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
805 return os << Bytecodes::OperandTypeToString(operand_type);
806}
807
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808static const int kLastParamRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100809 (InterpreterFrameConstants::kRegisterFileFromFp -
810 InterpreterFrameConstants::kLastParamFromFp) /
811 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812static const int kFunctionClosureRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100813 (InterpreterFrameConstants::kRegisterFileFromFp -
814 StandardFrameConstants::kFunctionOffset) /
815 kPointerSize;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100816static const int kCurrentContextRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100817 (InterpreterFrameConstants::kRegisterFileFromFp -
818 StandardFrameConstants::kContextOffset) /
819 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820static const int kNewTargetRegisterIndex =
Ben Murdochc5610432016-08-08 18:44:38 +0100821 (InterpreterFrameConstants::kRegisterFileFromFp -
822 InterpreterFrameConstants::kNewTargetFromFp) /
823 kPointerSize;
824static const int kBytecodeArrayRegisterIndex =
825 (InterpreterFrameConstants::kRegisterFileFromFp -
826 InterpreterFrameConstants::kBytecodeArrayFromFp) /
827 kPointerSize;
828static const int kBytecodeOffsetRegisterIndex =
829 (InterpreterFrameConstants::kRegisterFileFromFp -
830 InterpreterFrameConstants::kBytecodeOffsetFromFp) /
831 kPointerSize;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832
833Register Register::FromParameterIndex(int index, int parameter_count) {
834 DCHECK_GE(index, 0);
835 DCHECK_LT(index, parameter_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
837 DCHECK_LT(register_index, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 return Register(register_index);
839}
840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841int Register::ToParameterIndex(int parameter_count) const {
842 DCHECK(is_parameter());
843 return index() - kLastParamRegisterIndex + parameter_count - 1;
844}
845
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846Register Register::function_closure() {
847 return Register(kFunctionClosureRegisterIndex);
848}
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850bool Register::is_function_closure() const {
851 return index() == kFunctionClosureRegisterIndex;
852}
853
Ben Murdoch097c5b22016-05-18 11:27:45 +0100854Register Register::current_context() {
855 return Register(kCurrentContextRegisterIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856}
857
Ben Murdoch097c5b22016-05-18 11:27:45 +0100858bool Register::is_current_context() const {
859 return index() == kCurrentContextRegisterIndex;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860}
861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864bool Register::is_new_target() const {
865 return index() == kNewTargetRegisterIndex;
866}
867
Ben Murdochc5610432016-08-08 18:44:38 +0100868Register Register::bytecode_array() {
869 return Register(kBytecodeArrayRegisterIndex);
870}
871
872bool Register::is_bytecode_array() const {
873 return index() == kBytecodeArrayRegisterIndex;
874}
875
876Register Register::bytecode_offset() {
877 return Register(kBytecodeOffsetRegisterIndex);
878}
879
880bool Register::is_bytecode_offset() const {
881 return index() == kBytecodeOffsetRegisterIndex;
882}
883
884OperandSize Register::SizeOfOperand() const {
885 int32_t operand = ToOperand();
886 if (operand >= kMinInt8 && operand <= kMaxInt8) {
887 return OperandSize::kByte;
888 } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
889 return OperandSize::kShort;
890 } else {
891 return OperandSize::kQuad;
892 }
893}
894
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
896 Register reg4, Register reg5) {
897 if (reg1.index() + 1 != reg2.index()) {
898 return false;
899 }
900 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
901 return false;
902 }
903 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
904 return false;
905 }
906 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
907 return false;
908 }
909 return true;
910}
911
Ben Murdoch097c5b22016-05-18 11:27:45 +0100912std::string Register::ToString(int parameter_count) {
913 if (is_current_context()) {
914 return std::string("<context>");
915 } else if (is_function_closure()) {
916 return std::string("<closure>");
917 } else if (is_new_target()) {
918 return std::string("<new.target>");
919 } else if (is_parameter()) {
920 int parameter_index = ToParameterIndex(parameter_count);
921 if (parameter_index == 0) {
922 return std::string("<this>");
923 } else {
924 std::ostringstream s;
925 s << "a" << parameter_index - 1;
926 return s.str();
927 }
928 } else {
929 std::ostringstream s;
930 s << "r" << index();
931 return s.str();
932 }
933}
934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935} // namespace interpreter
936} // namespace internal
937} // namespace v8