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 |