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