OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 friend class FastCodeGenerator; | 745 friend class FastCodeGenerator; |
746 friend class FullCodeGenerator; | 746 friend class FullCodeGenerator; |
747 friend class FullCodeGenSyntaxChecker; | 747 friend class FullCodeGenSyntaxChecker; |
748 | 748 |
749 friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc | 749 friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc |
750 | 750 |
751 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); | 751 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); |
752 }; | 752 }; |
753 | 753 |
754 | 754 |
755 // Compute a transcendental math function natively, or call the | |
756 // TranscendentalCache runtime function. | |
757 class TranscendentalCacheStub: public CodeStub { | |
758 public: | |
759 explicit TranscendentalCacheStub(TranscendentalCache::Type type) | |
760 : type_(type) {} | |
761 void Generate(MacroAssembler* masm); | |
762 private: | |
763 TranscendentalCache::Type type_; | |
764 Major MajorKey() { return TranscendentalCache; } | |
765 int MinorKey() { return type_; } | |
766 Runtime::FunctionId RuntimeFunction(); | |
767 void GenerateOperation(MacroAssembler* masm, Label* on_nan_result); | |
768 }; | |
769 | |
770 | |
771 class ToBooleanStub: public CodeStub { | |
772 public: | |
773 ToBooleanStub() { } | |
774 | |
775 void Generate(MacroAssembler* masm); | |
776 | |
777 private: | |
778 Major MajorKey() { return ToBoolean; } | |
779 int MinorKey() { return 0; } | |
780 }; | |
781 | |
782 | |
783 // Flag that indicates how to generate code for the stub GenericBinaryOpStub. | |
784 enum GenericBinaryFlags { | |
785 NO_GENERIC_BINARY_FLAGS = 0, | |
786 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub. | |
787 }; | |
788 | |
789 | |
790 class GenericBinaryOpStub: public CodeStub { | |
791 public: | |
792 GenericBinaryOpStub(Token::Value op, | |
793 OverwriteMode mode, | |
794 GenericBinaryFlags flags, | |
795 TypeInfo operands_type = TypeInfo::Unknown()) | |
796 : op_(op), | |
797 mode_(mode), | |
798 flags_(flags), | |
799 args_in_registers_(false), | |
800 args_reversed_(false), | |
801 static_operands_type_(operands_type), | |
802 runtime_operands_type_(BinaryOpIC::DEFAULT), | |
803 name_(NULL) { | |
804 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); | |
805 } | |
806 | |
807 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) | |
808 : op_(OpBits::decode(key)), | |
809 mode_(ModeBits::decode(key)), | |
810 flags_(FlagBits::decode(key)), | |
811 args_in_registers_(ArgsInRegistersBits::decode(key)), | |
812 args_reversed_(ArgsReversedBits::decode(key)), | |
813 static_operands_type_(TypeInfo::ExpandedRepresentation( | |
814 StaticTypeInfoBits::decode(key))), | |
815 runtime_operands_type_(type_info), | |
816 name_(NULL) { | |
817 } | |
818 | |
819 // Generate code to call the stub with the supplied arguments. This will add | |
820 // code at the call site to prepare arguments either in registers or on the | |
821 // stack together with the actual call. | |
822 void GenerateCall(MacroAssembler* masm, Register left, Register right); | |
823 void GenerateCall(MacroAssembler* masm, Register left, Smi* right); | |
824 void GenerateCall(MacroAssembler* masm, Smi* left, Register right); | |
825 | |
826 Result GenerateCall(MacroAssembler* masm, | |
827 VirtualFrame* frame, | |
828 Result* left, | |
829 Result* right); | |
830 | |
831 private: | |
832 Token::Value op_; | |
833 OverwriteMode mode_; | |
834 GenericBinaryFlags flags_; | |
835 bool args_in_registers_; // Arguments passed in registers not on the stack. | |
836 bool args_reversed_; // Left and right argument are swapped. | |
837 | |
838 // Number type information of operands, determined by code generator. | |
839 TypeInfo static_operands_type_; | |
840 | |
841 // Operand type information determined at runtime. | |
842 BinaryOpIC::TypeInfo runtime_operands_type_; | |
843 | |
844 char* name_; | |
845 | |
846 const char* GetName(); | |
847 | |
848 #ifdef DEBUG | |
849 void Print() { | |
850 PrintF("GenericBinaryOpStub %d (op %s), " | |
851 "(mode %d, flags %d, registers %d, reversed %d, only_numbers %s)\n", | |
852 MinorKey(), | |
853 Token::String(op_), | |
854 static_cast<int>(mode_), | |
855 static_cast<int>(flags_), | |
856 static_cast<int>(args_in_registers_), | |
857 static_cast<int>(args_reversed_), | |
858 static_operands_type_.ToString()); | |
859 } | |
860 #endif | |
861 | |
862 // Minor key encoding in 17 bits TTNNNFRAOOOOOOOMM. | |
863 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; | |
864 class OpBits: public BitField<Token::Value, 2, 7> {}; | |
865 class ArgsInRegistersBits: public BitField<bool, 9, 1> {}; | |
866 class ArgsReversedBits: public BitField<bool, 10, 1> {}; | |
867 class FlagBits: public BitField<GenericBinaryFlags, 11, 1> {}; | |
868 class StaticTypeInfoBits: public BitField<int, 12, 3> {}; | |
869 class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 15, 2> {}; | |
870 | |
871 Major MajorKey() { return GenericBinaryOp; } | |
872 int MinorKey() { | |
873 // Encode the parameters in a unique 18 bit value. | |
874 return OpBits::encode(op_) | |
875 | ModeBits::encode(mode_) | |
876 | FlagBits::encode(flags_) | |
877 | ArgsInRegistersBits::encode(args_in_registers_) | |
878 | ArgsReversedBits::encode(args_reversed_) | |
879 | StaticTypeInfoBits::encode( | |
880 static_operands_type_.ThreeBitRepresentation()) | |
881 | RuntimeTypeInfoBits::encode(runtime_operands_type_); | |
882 } | |
883 | |
884 void Generate(MacroAssembler* masm); | |
885 void GenerateSmiCode(MacroAssembler* masm, Label* slow); | |
886 void GenerateLoadArguments(MacroAssembler* masm); | |
887 void GenerateReturn(MacroAssembler* masm); | |
888 void GenerateRegisterArgsPush(MacroAssembler* masm); | |
889 void GenerateTypeTransition(MacroAssembler* masm); | |
890 | |
891 bool ArgsInRegistersSupported() { | |
892 return (op_ == Token::ADD) || (op_ == Token::SUB) | |
893 || (op_ == Token::MUL) || (op_ == Token::DIV); | |
894 } | |
895 bool IsOperationCommutative() { | |
896 return (op_ == Token::ADD) || (op_ == Token::MUL); | |
897 } | |
898 | |
899 void SetArgsInRegisters() { args_in_registers_ = true; } | |
900 void SetArgsReversed() { args_reversed_ = true; } | |
901 bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; } | |
902 bool HasArgsInRegisters() { return args_in_registers_; } | |
903 bool HasArgsReversed() { return args_reversed_; } | |
904 | |
905 bool ShouldGenerateSmiCode() { | |
906 return HasSmiCodeInStub() && | |
907 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS && | |
908 runtime_operands_type_ != BinaryOpIC::STRINGS; | |
909 } | |
910 | |
911 bool ShouldGenerateFPCode() { | |
912 return runtime_operands_type_ != BinaryOpIC::STRINGS; | |
913 } | |
914 | |
915 virtual int GetCodeKind() { return Code::BINARY_OP_IC; } | |
916 | |
917 virtual InlineCacheState GetICState() { | |
918 return BinaryOpIC::ToState(runtime_operands_type_); | |
919 } | |
920 }; | |
921 | |
922 class StringHelper : public AllStatic { | |
923 public: | |
924 // Generate code for copying characters using a simple loop. This should only | |
925 // be used in places where the number of characters is small and the | |
926 // additional setup and checking in GenerateCopyCharactersREP adds too much | |
927 // overhead. Copying of overlapping regions is not supported. | |
928 static void GenerateCopyCharacters(MacroAssembler* masm, | |
929 Register dest, | |
930 Register src, | |
931 Register count, | |
932 bool ascii); | |
933 | |
934 // Generate code for copying characters using the rep movs instruction. | |
935 // Copies rcx characters from rsi to rdi. Copying of overlapping regions is | |
936 // not supported. | |
937 static void GenerateCopyCharactersREP(MacroAssembler* masm, | |
938 Register dest, // Must be rdi. | |
939 Register src, // Must be rsi. | |
940 Register count, // Must be rcx. | |
941 bool ascii); | |
942 | |
943 | |
944 // Probe the symbol table for a two character string. If the string is | |
945 // not found by probing a jump to the label not_found is performed. This jump | |
946 // does not guarantee that the string is not in the symbol table. If the | |
947 // string is found the code falls through with the string in register rax. | |
948 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | |
949 Register c1, | |
950 Register c2, | |
951 Register scratch1, | |
952 Register scratch2, | |
953 Register scratch3, | |
954 Register scratch4, | |
955 Label* not_found); | |
956 | |
957 // Generate string hash. | |
958 static void GenerateHashInit(MacroAssembler* masm, | |
959 Register hash, | |
960 Register character, | |
961 Register scratch); | |
962 static void GenerateHashAddCharacter(MacroAssembler* masm, | |
963 Register hash, | |
964 Register character, | |
965 Register scratch); | |
966 static void GenerateHashGetHash(MacroAssembler* masm, | |
967 Register hash, | |
968 Register scratch); | |
969 | |
970 private: | |
971 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); | |
972 }; | |
973 | |
974 | |
975 // Flag that indicates how to generate code for the stub StringAddStub. | |
976 enum StringAddFlags { | |
977 NO_STRING_ADD_FLAGS = 0, | |
978 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub. | |
979 }; | |
980 | |
981 | |
982 class StringAddStub: public CodeStub { | |
983 public: | |
984 explicit StringAddStub(StringAddFlags flags) { | |
985 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0); | |
986 } | |
987 | |
988 private: | |
989 Major MajorKey() { return StringAdd; } | |
990 int MinorKey() { return string_check_ ? 0 : 1; } | |
991 | |
992 void Generate(MacroAssembler* masm); | |
993 | |
994 // Should the stub check whether arguments are strings? | |
995 bool string_check_; | |
996 }; | |
997 | |
998 | |
999 class SubStringStub: public CodeStub { | |
1000 public: | |
1001 SubStringStub() {} | |
1002 | |
1003 private: | |
1004 Major MajorKey() { return SubString; } | |
1005 int MinorKey() { return 0; } | |
1006 | |
1007 void Generate(MacroAssembler* masm); | |
1008 }; | |
1009 | |
1010 | |
1011 class StringCompareStub: public CodeStub { | |
1012 public: | |
1013 explicit StringCompareStub() {} | |
1014 | |
1015 // Compare two flat ascii strings and returns result in rax after popping two | |
1016 // arguments from the stack. | |
1017 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | |
1018 Register left, | |
1019 Register right, | |
1020 Register scratch1, | |
1021 Register scratch2, | |
1022 Register scratch3, | |
1023 Register scratch4); | |
1024 | |
1025 private: | |
1026 Major MajorKey() { return StringCompare; } | |
1027 int MinorKey() { return 0; } | |
1028 | |
1029 void Generate(MacroAssembler* masm); | |
1030 }; | |
1031 | |
1032 | |
1033 class NumberToStringStub: public CodeStub { | |
1034 public: | |
1035 NumberToStringStub() { } | |
1036 | |
1037 // Generate code to do a lookup in the number string cache. If the number in | |
1038 // the register object is found in the cache the generated code falls through | |
1039 // with the result in the result register. The object and the result register | |
1040 // can be the same. If the number is not found in the cache the code jumps to | |
1041 // the label not_found with only the content of register object unchanged. | |
1042 static void GenerateLookupNumberStringCache(MacroAssembler* masm, | |
1043 Register object, | |
1044 Register result, | |
1045 Register scratch1, | |
1046 Register scratch2, | |
1047 bool object_is_smi, | |
1048 Label* not_found); | |
1049 | |
1050 private: | |
1051 static void GenerateConvertHashCodeToIndex(MacroAssembler* masm, | |
1052 Register hash, | |
1053 Register mask); | |
1054 | |
1055 Major MajorKey() { return NumberToString; } | |
1056 int MinorKey() { return 0; } | |
1057 | |
1058 void Generate(MacroAssembler* masm); | |
1059 | |
1060 const char* GetName() { return "NumberToStringStub"; } | |
1061 | |
1062 #ifdef DEBUG | |
1063 void Print() { | |
1064 PrintF("NumberToStringStub\n"); | |
1065 } | |
1066 #endif | |
1067 }; | |
1068 | |
1069 | |
1070 class RecordWriteStub : public CodeStub { | |
1071 public: | |
1072 RecordWriteStub(Register object, Register addr, Register scratch) | |
1073 : object_(object), addr_(addr), scratch_(scratch) { } | |
1074 | |
1075 void Generate(MacroAssembler* masm); | |
1076 | |
1077 private: | |
1078 Register object_; | |
1079 Register addr_; | |
1080 Register scratch_; | |
1081 | |
1082 #ifdef DEBUG | |
1083 void Print() { | |
1084 PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n", | |
1085 object_.code(), addr_.code(), scratch_.code()); | |
1086 } | |
1087 #endif | |
1088 | |
1089 // Minor key encoding in 12 bits. 4 bits for each of the three | |
1090 // registers (object, address and scratch) OOOOAAAASSSS. | |
1091 class ScratchBits : public BitField<uint32_t, 0, 4> {}; | |
1092 class AddressBits : public BitField<uint32_t, 4, 4> {}; | |
1093 class ObjectBits : public BitField<uint32_t, 8, 4> {}; | |
1094 | |
1095 Major MajorKey() { return RecordWrite; } | |
1096 | |
1097 int MinorKey() { | |
1098 // Encode the registers. | |
1099 return ObjectBits::encode(object_.code()) | | |
1100 AddressBits::encode(addr_.code()) | | |
1101 ScratchBits::encode(scratch_.code()); | |
1102 } | |
1103 }; | |
1104 | |
1105 | |
1106 } } // namespace v8::internal | 755 } } // namespace v8::internal |
1107 | 756 |
1108 #endif // V8_X64_CODEGEN_X64_H_ | 757 #endif // V8_X64_CODEGEN_X64_H_ |
OLD | NEW |