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/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/globals.h" | 10 #include "src/code-stubs.h" |
| 11 #include "src/frames.h" |
11 #include "src/interpreter/bytecode-traits.h" | 12 #include "src/interpreter/bytecode-traits.h" |
| 13 #include "src/interpreter/interpreter.h" |
12 | 14 |
13 namespace v8 { | 15 namespace v8 { |
14 namespace internal { | 16 namespace internal { |
15 namespace interpreter { | 17 namespace interpreter { |
16 | 18 |
17 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; | 19 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; |
18 | 20 |
19 // static | 21 // static |
20 const char* Bytecodes::ToString(Bytecode bytecode) { | 22 const char* Bytecodes::ToString(Bytecode bytecode) { |
21 switch (bytecode) { | 23 switch (bytecode) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 case OperandSize::kShort: | 97 case OperandSize::kShort: |
96 return "Short"; | 98 return "Short"; |
97 case OperandSize::kQuad: | 99 case OperandSize::kQuad: |
98 return "Quad"; | 100 return "Quad"; |
99 } | 101 } |
100 UNREACHABLE(); | 102 UNREACHABLE(); |
101 return ""; | 103 return ""; |
102 } | 104 } |
103 | 105 |
104 // static | 106 // static |
105 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | |
106 DCHECK_LE(bytecode, Bytecode::kLast); | |
107 return static_cast<uint8_t>(bytecode); | |
108 } | |
109 | |
110 // static | |
111 Bytecode Bytecodes::FromByte(uint8_t value) { | 107 Bytecode Bytecodes::FromByte(uint8_t value) { |
112 Bytecode bytecode = static_cast<Bytecode>(value); | 108 Bytecode bytecode = static_cast<Bytecode>(value); |
113 DCHECK(bytecode <= Bytecode::kLast); | 109 DCHECK(bytecode <= Bytecode::kLast); |
114 return bytecode; | 110 return bytecode; |
115 } | 111 } |
116 | 112 |
117 // static | 113 // static |
118 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 114 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
119 DCHECK(!IsDebugBreak(bytecode)); | 115 DCHECK(!IsDebugBreak(bytecode)); |
120 if (bytecode == Bytecode::kWide) { | 116 if (bytecode == Bytecode::kWide) { |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { | 373 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
378 return bytecode == Bytecode::kJumpIfTrue || | 374 return bytecode == Bytecode::kJumpIfTrue || |
379 bytecode == Bytecode::kJumpIfFalse || | 375 bytecode == Bytecode::kJumpIfFalse || |
380 bytecode == Bytecode::kJumpIfToBooleanTrue || | 376 bytecode == Bytecode::kJumpIfToBooleanTrue || |
381 bytecode == Bytecode::kJumpIfToBooleanFalse || | 377 bytecode == Bytecode::kJumpIfToBooleanFalse || |
382 bytecode == Bytecode::kJumpIfNotHole || | 378 bytecode == Bytecode::kJumpIfNotHole || |
383 bytecode == Bytecode::kJumpIfNull || | 379 bytecode == Bytecode::kJumpIfNull || |
384 bytecode == Bytecode::kJumpIfUndefined; | 380 bytecode == Bytecode::kJumpIfUndefined; |
385 } | 381 } |
386 | 382 |
| 383 |
387 // static | 384 // static |
388 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { | 385 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
389 return bytecode == Bytecode::kJumpIfTrueConstant || | 386 return bytecode == Bytecode::kJumpIfTrueConstant || |
390 bytecode == Bytecode::kJumpIfFalseConstant || | 387 bytecode == Bytecode::kJumpIfFalseConstant || |
391 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | 388 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
392 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || | 389 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
393 bytecode == Bytecode::kJumpIfNotHoleConstant || | 390 bytecode == Bytecode::kJumpIfNotHoleConstant || |
394 bytecode == Bytecode::kJumpIfNullConstant || | 391 bytecode == Bytecode::kJumpIfNullConstant || |
395 bytecode == Bytecode::kJumpIfUndefinedConstant; | 392 bytecode == Bytecode::kJumpIfUndefinedConstant; |
396 } | 393 } |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 if (value <= kMaxUInt8) { | 615 if (value <= kMaxUInt8) { |
619 return OperandSize::kByte; | 616 return OperandSize::kByte; |
620 } else if (value <= kMaxUInt16) { | 617 } else if (value <= kMaxUInt16) { |
621 return OperandSize::kShort; | 618 return OperandSize::kShort; |
622 } else { | 619 } else { |
623 return OperandSize::kQuad; | 620 return OperandSize::kQuad; |
624 } | 621 } |
625 } | 622 } |
626 | 623 |
627 // static | 624 // static |
| 625 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, |
| 626 OperandType operand_type, |
| 627 OperandScale operand_scale) { |
| 628 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); |
| 629 int32_t operand = |
| 630 DecodeSignedOperand(operand_start, operand_type, operand_scale); |
| 631 return Register::FromOperand(operand); |
| 632 } |
| 633 |
| 634 // static |
| 635 int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start, |
| 636 OperandType operand_type, |
| 637 OperandScale operand_scale) { |
| 638 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type)); |
| 639 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
| 640 case OperandSize::kByte: |
| 641 return static_cast<int8_t>(*operand_start); |
| 642 case OperandSize::kShort: |
| 643 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start)); |
| 644 case OperandSize::kQuad: |
| 645 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start)); |
| 646 case OperandSize::kNone: |
| 647 UNREACHABLE(); |
| 648 } |
| 649 return 0; |
| 650 } |
| 651 |
| 652 // static |
| 653 uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start, |
| 654 OperandType operand_type, |
| 655 OperandScale operand_scale) { |
| 656 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type)); |
| 657 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
| 658 case OperandSize::kByte: |
| 659 return *operand_start; |
| 660 case OperandSize::kShort: |
| 661 return ReadUnalignedUInt16(operand_start); |
| 662 case OperandSize::kQuad: |
| 663 return ReadUnalignedUInt32(operand_start); |
| 664 case OperandSize::kNone: |
| 665 UNREACHABLE(); |
| 666 } |
| 667 return 0; |
| 668 } |
| 669 |
| 670 // static |
| 671 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
| 672 int parameter_count) { |
| 673 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
| 674 int prefix_offset = 0; |
| 675 OperandScale operand_scale = OperandScale::kSingle; |
| 676 if (IsPrefixScalingBytecode(bytecode)) { |
| 677 prefix_offset = 1; |
| 678 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode); |
| 679 bytecode = Bytecodes::FromByte(bytecode_start[1]); |
| 680 } |
| 681 |
| 682 // Prepare to print bytecode and operands as hex digits. |
| 683 std::ios saved_format(nullptr); |
| 684 saved_format.copyfmt(saved_format); |
| 685 os.fill('0'); |
| 686 os.flags(std::ios::hex); |
| 687 |
| 688 int bytecode_size = Bytecodes::Size(bytecode, operand_scale); |
| 689 for (int i = 0; i < prefix_offset + bytecode_size; i++) { |
| 690 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' '; |
| 691 } |
| 692 os.copyfmt(saved_format); |
| 693 |
| 694 const int kBytecodeColumnSize = 6; |
| 695 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) { |
| 696 os << " "; |
| 697 } |
| 698 |
| 699 os << Bytecodes::ToString(bytecode, operand_scale) << " "; |
| 700 |
| 701 // Operands for the debug break are from the original instruction. |
| 702 if (IsDebugBreak(bytecode)) return os; |
| 703 |
| 704 int number_of_operands = NumberOfOperands(bytecode); |
| 705 int range = 0; |
| 706 for (int i = 0; i < number_of_operands; i++) { |
| 707 OperandType op_type = GetOperandType(bytecode, i); |
| 708 const uint8_t* operand_start = |
| 709 &bytecode_start[prefix_offset + |
| 710 GetOperandOffset(bytecode, i, operand_scale)]; |
| 711 switch (op_type) { |
| 712 case interpreter::OperandType::kRegCount: |
| 713 os << "#" |
| 714 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); |
| 715 break; |
| 716 case interpreter::OperandType::kIdx: |
| 717 case interpreter::OperandType::kRuntimeId: |
| 718 case interpreter::OperandType::kIntrinsicId: |
| 719 os << "[" |
| 720 << DecodeUnsignedOperand(operand_start, op_type, operand_scale) |
| 721 << "]"; |
| 722 break; |
| 723 case interpreter::OperandType::kImm: |
| 724 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale) |
| 725 << "]"; |
| 726 break; |
| 727 case interpreter::OperandType::kFlag8: |
| 728 os << "#" |
| 729 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); |
| 730 break; |
| 731 case interpreter::OperandType::kMaybeReg: |
| 732 case interpreter::OperandType::kReg: |
| 733 case interpreter::OperandType::kRegOut: { |
| 734 Register reg = |
| 735 DecodeRegisterOperand(operand_start, op_type, operand_scale); |
| 736 os << reg.ToString(parameter_count); |
| 737 break; |
| 738 } |
| 739 case interpreter::OperandType::kRegOutTriple: |
| 740 range += 1; |
| 741 case interpreter::OperandType::kRegOutPair: |
| 742 case interpreter::OperandType::kRegPair: { |
| 743 range += 1; |
| 744 Register first_reg = |
| 745 DecodeRegisterOperand(operand_start, op_type, operand_scale); |
| 746 Register last_reg = Register(first_reg.index() + range); |
| 747 os << first_reg.ToString(parameter_count) << "-" |
| 748 << last_reg.ToString(parameter_count); |
| 749 break; |
| 750 } |
| 751 case interpreter::OperandType::kNone: |
| 752 UNREACHABLE(); |
| 753 break; |
| 754 } |
| 755 if (i != number_of_operands - 1) { |
| 756 os << ", "; |
| 757 } |
| 758 } |
| 759 return os; |
| 760 } |
| 761 |
| 762 // static |
628 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, | 763 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, |
629 OperandScale operand_scale) { | 764 OperandScale operand_scale) { |
630 return operand_scale == OperandScale::kSingle || | 765 return operand_scale == OperandScale::kSingle || |
631 Bytecodes::IsBytecodeWithScalableOperands(bytecode); | 766 Bytecodes::IsBytecodeWithScalableOperands(bytecode); |
632 } | 767 } |
633 | 768 |
634 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 769 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
635 return os << Bytecodes::ToString(bytecode); | 770 return os << Bytecodes::ToString(bytecode); |
636 } | 771 } |
637 | 772 |
638 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { | 773 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { |
639 return os << Bytecodes::AccumulatorUseToString(use); | 774 return os << Bytecodes::AccumulatorUseToString(use); |
640 } | 775 } |
641 | 776 |
642 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { | 777 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
643 return os << Bytecodes::OperandSizeToString(operand_size); | 778 return os << Bytecodes::OperandSizeToString(operand_size); |
644 } | 779 } |
645 | 780 |
646 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { | 781 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { |
647 return os << Bytecodes::OperandScaleToString(operand_scale); | 782 return os << Bytecodes::OperandScaleToString(operand_scale); |
648 } | 783 } |
649 | 784 |
650 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | 785 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
651 return os << Bytecodes::OperandTypeToString(operand_type); | 786 return os << Bytecodes::OperandTypeToString(operand_type); |
652 } | 787 } |
653 | 788 |
| 789 static const int kLastParamRegisterIndex = |
| 790 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 791 InterpreterFrameConstants::kLastParamFromFp) / |
| 792 kPointerSize; |
| 793 static const int kFunctionClosureRegisterIndex = |
| 794 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 795 StandardFrameConstants::kFunctionOffset) / |
| 796 kPointerSize; |
| 797 static const int kCurrentContextRegisterIndex = |
| 798 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 799 StandardFrameConstants::kContextOffset) / |
| 800 kPointerSize; |
| 801 static const int kNewTargetRegisterIndex = |
| 802 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 803 InterpreterFrameConstants::kNewTargetFromFp) / |
| 804 kPointerSize; |
| 805 static const int kBytecodeArrayRegisterIndex = |
| 806 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 807 InterpreterFrameConstants::kBytecodeArrayFromFp) / |
| 808 kPointerSize; |
| 809 static const int kBytecodeOffsetRegisterIndex = |
| 810 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 811 InterpreterFrameConstants::kBytecodeOffsetFromFp) / |
| 812 kPointerSize; |
| 813 static const int kCallerPCOffsetRegisterIndex = |
| 814 (InterpreterFrameConstants::kRegisterFileFromFp - |
| 815 InterpreterFrameConstants::kCallerPCOffsetFromFp) / |
| 816 kPointerSize; |
| 817 |
| 818 Register Register::FromParameterIndex(int index, int parameter_count) { |
| 819 DCHECK_GE(index, 0); |
| 820 DCHECK_LT(index, parameter_count); |
| 821 int register_index = kLastParamRegisterIndex - parameter_count + index + 1; |
| 822 DCHECK_LT(register_index, 0); |
| 823 return Register(register_index); |
| 824 } |
| 825 |
| 826 int Register::ToParameterIndex(int parameter_count) const { |
| 827 DCHECK(is_parameter()); |
| 828 return index() - kLastParamRegisterIndex + parameter_count - 1; |
| 829 } |
| 830 |
| 831 Register Register::function_closure() { |
| 832 return Register(kFunctionClosureRegisterIndex); |
| 833 } |
| 834 |
| 835 bool Register::is_function_closure() const { |
| 836 return index() == kFunctionClosureRegisterIndex; |
| 837 } |
| 838 |
| 839 Register Register::current_context() { |
| 840 return Register(kCurrentContextRegisterIndex); |
| 841 } |
| 842 |
| 843 bool Register::is_current_context() const { |
| 844 return index() == kCurrentContextRegisterIndex; |
| 845 } |
| 846 |
| 847 Register Register::new_target() { return Register(kNewTargetRegisterIndex); } |
| 848 |
| 849 bool Register::is_new_target() const { |
| 850 return index() == kNewTargetRegisterIndex; |
| 851 } |
| 852 |
| 853 Register Register::bytecode_array() { |
| 854 return Register(kBytecodeArrayRegisterIndex); |
| 855 } |
| 856 |
| 857 bool Register::is_bytecode_array() const { |
| 858 return index() == kBytecodeArrayRegisterIndex; |
| 859 } |
| 860 |
| 861 Register Register::bytecode_offset() { |
| 862 return Register(kBytecodeOffsetRegisterIndex); |
| 863 } |
| 864 |
| 865 bool Register::is_bytecode_offset() const { |
| 866 return index() == kBytecodeOffsetRegisterIndex; |
| 867 } |
| 868 |
| 869 // static |
| 870 Register Register::virtual_accumulator() { |
| 871 return Register(kCallerPCOffsetRegisterIndex); |
| 872 } |
| 873 |
| 874 OperandSize Register::SizeOfOperand() const { |
| 875 int32_t operand = ToOperand(); |
| 876 if (operand >= kMinInt8 && operand <= kMaxInt8) { |
| 877 return OperandSize::kByte; |
| 878 } else if (operand >= kMinInt16 && operand <= kMaxInt16) { |
| 879 return OperandSize::kShort; |
| 880 } else { |
| 881 return OperandSize::kQuad; |
| 882 } |
| 883 } |
| 884 |
| 885 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3, |
| 886 Register reg4, Register reg5) { |
| 887 if (reg1.index() + 1 != reg2.index()) { |
| 888 return false; |
| 889 } |
| 890 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) { |
| 891 return false; |
| 892 } |
| 893 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) { |
| 894 return false; |
| 895 } |
| 896 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) { |
| 897 return false; |
| 898 } |
| 899 return true; |
| 900 } |
| 901 |
| 902 std::string Register::ToString(int parameter_count) { |
| 903 if (is_current_context()) { |
| 904 return std::string("<context>"); |
| 905 } else if (is_function_closure()) { |
| 906 return std::string("<closure>"); |
| 907 } else if (is_new_target()) { |
| 908 return std::string("<new.target>"); |
| 909 } else if (is_parameter()) { |
| 910 int parameter_index = ToParameterIndex(parameter_count); |
| 911 if (parameter_index == 0) { |
| 912 return std::string("<this>"); |
| 913 } else { |
| 914 std::ostringstream s; |
| 915 s << "a" << parameter_index - 1; |
| 916 return s.str(); |
| 917 } |
| 918 } else { |
| 919 std::ostringstream s; |
| 920 s << "r" << index(); |
| 921 return s.str(); |
| 922 } |
| 923 } |
| 924 |
| 925 // static |
| 926 uint8_t CreateObjectLiteralFlags::Encode(bool fast_clone_supported, |
| 927 int properties_count, |
| 928 int runtime_flags) { |
| 929 uint8_t result = FlagsBits::encode(runtime_flags); |
| 930 if (fast_clone_supported) { |
| 931 STATIC_ASSERT( |
| 932 FastCloneShallowObjectStub::kMaximumClonedProperties <= |
| 933 1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift); |
| 934 DCHECK_LE(properties_count, |
| 935 FastCloneShallowObjectStub::kMaximumClonedProperties); |
| 936 result |= CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode( |
| 937 properties_count); |
| 938 } |
| 939 return result; |
| 940 } |
| 941 |
| 942 // static |
| 943 uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope) { |
| 944 uint8_t result = PretenuredBit::encode(pretenure); |
| 945 if (!FLAG_always_opt && !FLAG_prepare_always_opt && |
| 946 pretenure == NOT_TENURED && is_function_scope) { |
| 947 result |= FastNewClosureBit::encode(true); |
| 948 } |
| 949 return result; |
| 950 } |
| 951 |
654 } // namespace interpreter | 952 } // namespace interpreter |
655 } // namespace internal | 953 } // namespace internal |
656 } // namespace v8 | 954 } // namespace v8 |
OLD | NEW |