| 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/code-stubs.h" | 10 #include "src/globals.h" |
| 11 #include "src/frames.h" | |
| 12 #include "src/interpreter/bytecode-traits.h" | 11 #include "src/interpreter/bytecode-traits.h" |
| 13 #include "src/interpreter/interpreter.h" | |
| 14 | 12 |
| 15 namespace v8 { | 13 namespace v8 { |
| 16 namespace internal { | 14 namespace internal { |
| 17 namespace interpreter { | 15 namespace interpreter { |
| 18 | 16 |
| 19 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; | 17 STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; |
| 20 | 18 |
| 21 // static | 19 // static |
| 22 const char* Bytecodes::ToString(Bytecode bytecode) { | 20 const char* Bytecodes::ToString(Bytecode bytecode) { |
| 23 switch (bytecode) { | 21 switch (bytecode) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 case OperandSize::kShort: | 95 case OperandSize::kShort: |
| 98 return "Short"; | 96 return "Short"; |
| 99 case OperandSize::kQuad: | 97 case OperandSize::kQuad: |
| 100 return "Quad"; | 98 return "Quad"; |
| 101 } | 99 } |
| 102 UNREACHABLE(); | 100 UNREACHABLE(); |
| 103 return ""; | 101 return ""; |
| 104 } | 102 } |
| 105 | 103 |
| 106 // static | 104 // 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 |
| 107 Bytecode Bytecodes::FromByte(uint8_t value) { | 111 Bytecode Bytecodes::FromByte(uint8_t value) { |
| 108 Bytecode bytecode = static_cast<Bytecode>(value); | 112 Bytecode bytecode = static_cast<Bytecode>(value); |
| 109 DCHECK(bytecode <= Bytecode::kLast); | 113 DCHECK(bytecode <= Bytecode::kLast); |
| 110 return bytecode; | 114 return bytecode; |
| 111 } | 115 } |
| 112 | 116 |
| 113 // static | 117 // static |
| 114 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { | 118 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
| 115 DCHECK(!IsDebugBreak(bytecode)); | 119 DCHECK(!IsDebugBreak(bytecode)); |
| 116 if (bytecode == Bytecode::kWide) { | 120 if (bytecode == Bytecode::kWide) { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { | 377 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
| 374 return bytecode == Bytecode::kJumpIfTrue || | 378 return bytecode == Bytecode::kJumpIfTrue || |
| 375 bytecode == Bytecode::kJumpIfFalse || | 379 bytecode == Bytecode::kJumpIfFalse || |
| 376 bytecode == Bytecode::kJumpIfToBooleanTrue || | 380 bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 377 bytecode == Bytecode::kJumpIfToBooleanFalse || | 381 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 378 bytecode == Bytecode::kJumpIfNotHole || | 382 bytecode == Bytecode::kJumpIfNotHole || |
| 379 bytecode == Bytecode::kJumpIfNull || | 383 bytecode == Bytecode::kJumpIfNull || |
| 380 bytecode == Bytecode::kJumpIfUndefined; | 384 bytecode == Bytecode::kJumpIfUndefined; |
| 381 } | 385 } |
| 382 | 386 |
| 383 | |
| 384 // static | 387 // static |
| 385 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { | 388 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
| 386 return bytecode == Bytecode::kJumpIfTrueConstant || | 389 return bytecode == Bytecode::kJumpIfTrueConstant || |
| 387 bytecode == Bytecode::kJumpIfFalseConstant || | 390 bytecode == Bytecode::kJumpIfFalseConstant || |
| 388 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || | 391 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 389 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || | 392 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
| 390 bytecode == Bytecode::kJumpIfNotHoleConstant || | 393 bytecode == Bytecode::kJumpIfNotHoleConstant || |
| 391 bytecode == Bytecode::kJumpIfNullConstant || | 394 bytecode == Bytecode::kJumpIfNullConstant || |
| 392 bytecode == Bytecode::kJumpIfUndefinedConstant; | 395 bytecode == Bytecode::kJumpIfUndefinedConstant; |
| 393 } | 396 } |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 if (value <= kMaxUInt8) { | 618 if (value <= kMaxUInt8) { |
| 616 return OperandSize::kByte; | 619 return OperandSize::kByte; |
| 617 } else if (value <= kMaxUInt16) { | 620 } else if (value <= kMaxUInt16) { |
| 618 return OperandSize::kShort; | 621 return OperandSize::kShort; |
| 619 } else { | 622 } else { |
| 620 return OperandSize::kQuad; | 623 return OperandSize::kQuad; |
| 621 } | 624 } |
| 622 } | 625 } |
| 623 | 626 |
| 624 // static | 627 // 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 | |
| 763 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, | 628 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, |
| 764 OperandScale operand_scale) { | 629 OperandScale operand_scale) { |
| 765 return operand_scale == OperandScale::kSingle || | 630 return operand_scale == OperandScale::kSingle || |
| 766 Bytecodes::IsBytecodeWithScalableOperands(bytecode); | 631 Bytecodes::IsBytecodeWithScalableOperands(bytecode); |
| 767 } | 632 } |
| 768 | 633 |
| 769 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 634 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
| 770 return os << Bytecodes::ToString(bytecode); | 635 return os << Bytecodes::ToString(bytecode); |
| 771 } | 636 } |
| 772 | 637 |
| 773 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { | 638 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { |
| 774 return os << Bytecodes::AccumulatorUseToString(use); | 639 return os << Bytecodes::AccumulatorUseToString(use); |
| 775 } | 640 } |
| 776 | 641 |
| 777 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { | 642 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
| 778 return os << Bytecodes::OperandSizeToString(operand_size); | 643 return os << Bytecodes::OperandSizeToString(operand_size); |
| 779 } | 644 } |
| 780 | 645 |
| 781 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { | 646 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { |
| 782 return os << Bytecodes::OperandScaleToString(operand_scale); | 647 return os << Bytecodes::OperandScaleToString(operand_scale); |
| 783 } | 648 } |
| 784 | 649 |
| 785 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | 650 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
| 786 return os << Bytecodes::OperandTypeToString(operand_type); | 651 return os << Bytecodes::OperandTypeToString(operand_type); |
| 787 } | 652 } |
| 788 | 653 |
| 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 | |
| 952 } // namespace interpreter | 654 } // namespace interpreter |
| 953 } // namespace internal | 655 } // namespace internal |
| 954 } // namespace v8 | 656 } // namespace v8 |
| OLD | NEW |