OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/frames.h" | 9 #include "src/frames.h" |
10 #include "src/interpreter/bytecode-traits.h" | 10 #include "src/interpreter/bytecode-traits.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 OPERAND_TYPE_LIST(CASE) | 67 OPERAND_TYPE_LIST(CASE) |
68 #undef CASE | 68 #undef CASE |
69 } | 69 } |
70 UNREACHABLE(); | 70 UNREACHABLE(); |
71 return ""; | 71 return ""; |
72 } | 72 } |
73 | 73 |
74 // static | 74 // static |
75 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { | 75 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { |
76 switch (operand_scale) { | 76 switch (operand_scale) { |
77 case OperandScale::kSingle: | 77 #define CASE(Name, _) \ |
78 return "Single"; | 78 case OperandScale::k##Name: \ |
79 case OperandScale::kDouble: | 79 return #Name; |
80 return "Double"; | 80 OPERAND_SCALE_LIST(CASE) |
81 case OperandScale::kQuadruple: | 81 #undef CASE |
82 return "Quadruple"; | |
83 case OperandScale::kInvalid: | |
84 UNREACHABLE(); | |
85 } | 82 } |
| 83 UNREACHABLE(); |
86 return ""; | 84 return ""; |
87 } | 85 } |
88 | 86 |
89 // static | 87 // static |
90 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | 88 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
91 switch (operand_size) { | 89 switch (operand_size) { |
92 case OperandSize::kNone: | 90 case OperandSize::kNone: |
93 return "None"; | 91 return "None"; |
94 case OperandSize::kByte: | 92 case OperandSize::kByte: |
95 return "Byte"; | 93 return "Byte"; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 AccumulatorUse::kRead; | 232 AccumulatorUse::kRead; |
235 } | 233 } |
236 | 234 |
237 // static | 235 // static |
238 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { | 236 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { |
239 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == | 237 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == |
240 AccumulatorUse::kWrite; | 238 AccumulatorUse::kWrite; |
241 } | 239 } |
242 | 240 |
243 // static | 241 // static |
| 242 bool Bytecodes::WritesAccumulatorWithBoolean(Bytecode bytecode) { |
| 243 switch (bytecode) { |
| 244 case Bytecode::kLdaTrue: |
| 245 case Bytecode::kLdaFalse: |
| 246 case Bytecode::kLogicalNot: |
| 247 case Bytecode::kTestEqual: |
| 248 case Bytecode::kTestNotEqual: |
| 249 case Bytecode::kTestEqualStrict: |
| 250 case Bytecode::kTestLessThan: |
| 251 case Bytecode::kTestLessThanOrEqual: |
| 252 case Bytecode::kTestGreaterThan: |
| 253 case Bytecode::kTestGreaterThanOrEqual: |
| 254 case Bytecode::kTestInstanceOf: |
| 255 case Bytecode::kTestIn: |
| 256 case Bytecode::kForInDone: |
| 257 return true; |
| 258 default: |
| 259 return false; |
| 260 } |
| 261 } |
| 262 |
| 263 // static |
| 264 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { |
| 265 switch (bytecode) { |
| 266 case Bytecode::kLdaZero: |
| 267 case Bytecode::kLdaSmi: |
| 268 case Bytecode::kLdaUndefined: |
| 269 case Bytecode::kLdaNull: |
| 270 case Bytecode::kLdaTheHole: |
| 271 case Bytecode::kLdaTrue: |
| 272 case Bytecode::kLdaFalse: |
| 273 case Bytecode::kLdaConstant: |
| 274 case Bytecode::kLdar: |
| 275 return true; |
| 276 default: |
| 277 return false; |
| 278 } |
| 279 } |
| 280 |
| 281 // static |
244 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 282 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
| 283 DCHECK_LE(bytecode, Bytecode::kLast); |
| 284 DCHECK_LT(i, NumberOfOperands(bytecode)); |
| 285 DCHECK_GE(i, 0); |
| 286 return GetOperandTypes(bytecode)[i]; |
| 287 } |
| 288 |
| 289 // static |
| 290 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { |
245 DCHECK(bytecode <= Bytecode::kLast); | 291 DCHECK(bytecode <= Bytecode::kLast); |
246 switch (bytecode) { | 292 switch (bytecode) { |
247 #define CASE(Name, ...) \ | 293 #define CASE(Name, ...) \ |
248 case Bytecode::k##Name: \ | 294 case Bytecode::k##Name: \ |
249 return BytecodeTraits<__VA_ARGS__>::GetOperandType(i); | 295 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); |
250 BYTECODE_LIST(CASE) | 296 BYTECODE_LIST(CASE) |
251 #undef CASE | 297 #undef CASE |
252 } | 298 } |
253 UNREACHABLE(); | 299 UNREACHABLE(); |
254 return OperandType::kNone; | 300 return nullptr; |
255 } | 301 } |
256 | 302 |
257 // static | 303 // static |
258 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, | 304 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, |
259 OperandScale operand_scale) { | 305 OperandScale operand_scale) { |
260 OperandType op_type = GetOperandType(bytecode, i); | 306 DCHECK(bytecode <= Bytecode::kLast); |
261 return ScaledOperandSize(op_type, operand_scale); | 307 switch (bytecode) { |
| 308 #define CASE(Name, ...) \ |
| 309 case Bytecode::k##Name: \ |
| 310 return BytecodeTraits<__VA_ARGS__>::GetOperandSize(i, operand_scale); |
| 311 BYTECODE_LIST(CASE) |
| 312 #undef CASE |
| 313 } |
| 314 UNREACHABLE(); |
| 315 return OperandSize::kNone; |
262 } | 316 } |
263 | 317 |
264 // static | 318 // static |
265 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { | 319 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
266 DCHECK(bytecode <= Bytecode::kLast); | 320 DCHECK(bytecode <= Bytecode::kLast); |
267 switch (bytecode) { | 321 switch (bytecode) { |
268 #define CASE(Name, ...) \ | 322 #define CASE(Name, ...) \ |
269 case Bytecode::k##Name: \ | 323 case Bytecode::k##Name: \ |
270 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ | 324 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
271 return Name##Trait::kRegisterOperandBitmap; | 325 return Name##Trait::kRegisterOperandBitmap; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 390 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
337 return bytecode == Bytecode::kJumpConstant || | 391 return bytecode == Bytecode::kJumpConstant || |
338 IsConditionalJumpConstant(bytecode); | 392 IsConditionalJumpConstant(bytecode); |
339 } | 393 } |
340 | 394 |
341 // static | 395 // static |
342 bool Bytecodes::IsJump(Bytecode bytecode) { | 396 bool Bytecodes::IsJump(Bytecode bytecode) { |
343 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); | 397 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
344 } | 398 } |
345 | 399 |
| 400 // static |
| 401 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { |
| 402 return bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 403 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 404 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 405 bytecode == Bytecode::kJumpIfToBooleanFalseConstant; |
| 406 } |
| 407 |
| 408 // static |
| 409 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
| 410 switch (bytecode) { |
| 411 case Bytecode::kJumpIfToBooleanTrue: |
| 412 return Bytecode::kJumpIfTrue; |
| 413 case Bytecode::kJumpIfToBooleanFalse: |
| 414 return Bytecode::kJumpIfFalse; |
| 415 case Bytecode::kJumpIfToBooleanTrueConstant: |
| 416 return Bytecode::kJumpIfTrueConstant; |
| 417 case Bytecode::kJumpIfToBooleanFalseConstant: |
| 418 return Bytecode::kJumpIfFalseConstant; |
| 419 default: |
| 420 UNREACHABLE(); |
| 421 } |
| 422 } |
346 | 423 |
347 // static | 424 // static |
348 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { | 425 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
349 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || | 426 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
350 bytecode == Bytecode::kNew; | 427 bytecode == Bytecode::kNew; |
351 } | 428 } |
352 | 429 |
353 // static | 430 // static |
354 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { | 431 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
355 return bytecode == Bytecode::kCallRuntime || | 432 return bytecode == Bytecode::kCallRuntime || |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 case OperandType::k##Name: \ | 531 case OperandType::k##Name: \ |
455 break; | 532 break; |
456 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 533 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
457 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 534 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
458 #undef CASE | 535 #undef CASE |
459 } | 536 } |
460 return false; | 537 return false; |
461 } | 538 } |
462 | 539 |
463 // static | 540 // static |
| 541 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { |
| 542 switch (operand_type) { |
| 543 case OperandType::kMaybeReg: |
| 544 case OperandType::kReg: |
| 545 case OperandType::kRegOut: |
| 546 return 1; |
| 547 case OperandType::kRegPair: |
| 548 case OperandType::kRegOutPair: |
| 549 return 2; |
| 550 case OperandType::kRegOutTriple: |
| 551 return 3; |
| 552 default: |
| 553 UNREACHABLE(); |
| 554 } |
| 555 return 0; |
| 556 } |
| 557 |
| 558 // static |
464 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { | 559 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
465 switch (operand_type) { | 560 switch (operand_type) { |
466 #define CASE(Name, _) \ | 561 #define CASE(Name, _) \ |
467 case OperandType::k##Name: \ | 562 case OperandType::k##Name: \ |
468 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned; | 563 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned; |
469 OPERAND_TYPE_LIST(CASE) | 564 OPERAND_TYPE_LIST(CASE) |
470 #undef CASE | 565 #undef CASE |
471 } | 566 } |
472 UNREACHABLE(); | 567 UNREACHABLE(); |
473 return false; | 568 return false; |
474 } | 569 } |
475 | 570 |
476 // static | 571 // static |
477 OperandScale Bytecodes::NextOperandScale(OperandScale operand_scale) { | 572 OperandSize Bytecodes::SizeForSignedOperand(int value) { |
478 DCHECK(operand_scale >= OperandScale::kSingle && | 573 if (kMinInt8 <= value && value <= kMaxInt8) { |
479 operand_scale <= OperandScale::kMaxValid); | 574 return OperandSize::kByte; |
480 return static_cast<OperandScale>(2 * static_cast<int>(operand_scale)); | 575 } else if (kMinInt16 <= value && value <= kMaxInt16) { |
| 576 return OperandSize::kShort; |
| 577 } else { |
| 578 return OperandSize::kQuad; |
| 579 } |
481 } | 580 } |
482 | 581 |
483 // static | 582 // static |
| 583 OperandSize Bytecodes::SizeForUnsignedOperand(int value) { |
| 584 DCHECK_GE(value, 0); |
| 585 if (value <= kMaxUInt8) { |
| 586 return OperandSize::kByte; |
| 587 } else if (value <= kMaxUInt16) { |
| 588 return OperandSize::kShort; |
| 589 } else { |
| 590 return OperandSize::kQuad; |
| 591 } |
| 592 } |
| 593 |
| 594 OperandSize Bytecodes::SizeForUnsignedOperand(size_t value) { |
| 595 if (value <= static_cast<size_t>(kMaxUInt8)) { |
| 596 return OperandSize::kByte; |
| 597 } else if (value <= static_cast<size_t>(kMaxUInt16)) { |
| 598 return OperandSize::kShort; |
| 599 } else if (value <= kMaxUInt32) { |
| 600 return OperandSize::kQuad; |
| 601 } else { |
| 602 UNREACHABLE(); |
| 603 return OperandSize::kQuad; |
| 604 } |
| 605 } |
| 606 |
| 607 OperandScale Bytecodes::OperandSizesToScale(OperandSize size0, |
| 608 OperandSize size1, |
| 609 OperandSize size2, |
| 610 OperandSize size3) { |
| 611 OperandSize upper = std::max(size0, size1); |
| 612 OperandSize lower = std::max(size2, size3); |
| 613 OperandSize result = std::max(upper, lower); |
| 614 // Operand sizes have been scaled before calling this function. |
| 615 // Currently all scalable operands are byte sized at |
| 616 // OperandScale::kSingle. |
| 617 STATIC_ASSERT(static_cast<int>(OperandSize::kByte) == |
| 618 static_cast<int>(OperandScale::kSingle) && |
| 619 static_cast<int>(OperandSize::kShort) == |
| 620 static_cast<int>(OperandScale::kDouble) && |
| 621 static_cast<int>(OperandSize::kQuad) == |
| 622 static_cast<int>(OperandScale::kQuadruple)); |
| 623 OperandScale operand_scale = static_cast<OperandScale>(result); |
| 624 DCHECK(operand_scale == OperandScale::kSingle || |
| 625 operand_scale == OperandScale::kDouble || |
| 626 operand_scale == OperandScale::kQuadruple); |
| 627 return operand_scale; |
| 628 } |
| 629 |
| 630 // static |
484 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, | 631 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, |
485 OperandType operand_type, | 632 OperandType operand_type, |
486 OperandScale operand_scale) { | 633 OperandScale operand_scale) { |
487 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); | 634 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); |
488 int32_t operand = | 635 int32_t operand = |
489 DecodeSignedOperand(operand_start, operand_type, operand_scale); | 636 DecodeSignedOperand(operand_start, operand_type, operand_scale); |
490 return Register::FromOperand(operand); | 637 return Register::FromOperand(operand); |
491 } | 638 } |
492 | 639 |
493 // static | 640 // static |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } else { | 914 } else { |
768 std::ostringstream s; | 915 std::ostringstream s; |
769 s << "r" << index(); | 916 s << "r" << index(); |
770 return s.str(); | 917 return s.str(); |
771 } | 918 } |
772 } | 919 } |
773 | 920 |
774 } // namespace interpreter | 921 } // namespace interpreter |
775 } // namespace internal | 922 } // namespace internal |
776 } // namespace v8 | 923 } // namespace v8 |
OLD | NEW |