Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // | 4 // |
| 5 // The intrinsic code below is executed before a method has built its frame. | 5 // The intrinsic code below is executed before a method has built its frame. |
| 6 // The return address is on the stack and the arguments below it. | 6 // The return address is on the stack and the arguments below it. |
| 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. | 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. |
| 8 // Each intrinsification method returns true if the corresponding | 8 // Each intrinsification method returns true if the corresponding |
| 9 // Dart method was intrinsified. | 9 // Dart method was intrinsified. |
| 10 | 10 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 V(Double, <, Double_lessThan) \ | 57 V(Double, <, Double_lessThan) \ |
| 58 V(Double, <=, Double_lessEqualThan) \ | 58 V(Double, <=, Double_lessEqualThan) \ |
| 59 V(Double, ==, Double_equal) \ | 59 V(Double, ==, Double_equal) \ |
| 60 V(Double, +, Double_add) \ | 60 V(Double, +, Double_add) \ |
| 61 V(Double, -, Double_sub) \ | 61 V(Double, -, Double_sub) \ |
| 62 V(Double, *, Double_mul) \ | 62 V(Double, *, Double_mul) \ |
| 63 V(Double, /, Double_div) \ | 63 V(Double, /, Double_div) \ |
| 64 V(Double, toDouble, Double_toDouble) \ | 64 V(Double, toDouble, Double_toDouble) \ |
| 65 V(Double, mulFromInteger, Double_mulFromInteger) \ | 65 V(Double, mulFromInteger, Double_mulFromInteger) \ |
| 66 V(Double, Double.fromInteger, Double_fromInteger) \ | 66 V(Double, Double.fromInteger, Double_fromInteger) \ |
| 67 V(Double, isNaN, Double_isNaN) \ | |
| 68 V(Double, isNegative, Double_isNegative) \ | |
| 67 V(ObjectArray, ObjectArray., ObjectArray_Allocate) \ | 69 V(ObjectArray, ObjectArray., ObjectArray_Allocate) \ |
| 68 V(ObjectArray, get:length, Array_getLength) \ | 70 V(ObjectArray, get:length, Array_getLength) \ |
| 69 V(ObjectArray, [], Array_getIndexed) \ | 71 V(ObjectArray, [], Array_getIndexed) \ |
| 70 V(ObjectArray, []=, Array_setIndexed) \ | 72 V(ObjectArray, []=, Array_setIndexed) \ |
| 71 V(GrowableObjectArray, get:length, GrowableArray_getLength) \ | 73 V(GrowableObjectArray, get:length, GrowableArray_getLength) \ |
| 72 V(GrowableObjectArray, [], GrowableArray_getIndexed) \ | 74 V(GrowableObjectArray, [], GrowableArray_getIndexed) \ |
| 73 V(GrowableObjectArray, []=, GrowableArray_setIndexed) \ | 75 V(GrowableObjectArray, []=, GrowableArray_setIndexed) \ |
| 74 V(ImmutableArray, [], Array_getIndexed) \ | 76 V(ImmutableArray, [], Array_getIndexed) \ |
| 75 V(ImmutableArray, get:length, Array_getLength) \ | 77 V(ImmutableArray, get:length, Array_getLength) \ |
| 76 V(Math, sqrt, Math_sqrt) \ | 78 V(Math, sqrt, Math_sqrt) \ |
| 79 V(Math, sin, Math_sin) \ | |
| 80 V(Math, cos, Math_cos) \ | |
| 77 V(Object, ==, Object_equal) \ | 81 V(Object, ==, Object_equal) \ |
| 78 V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \ | 82 V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \ |
| 79 V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \ | 83 V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \ |
| 80 V(StringBase, get:length, String_getLength) \ | 84 V(StringBase, get:length, String_getLength) \ |
| 81 V(StringBase, charCodeAt, String_charCodeAt) \ | 85 V(StringBase, charCodeAt, String_charCodeAt) \ |
| 82 V(StringBase, hashCode, String_hashCode) \ | 86 V(StringBase, hashCode, String_hashCode) \ |
| 83 V(StringBase, isEmpty, String_isEmpty) \ | 87 V(StringBase, isEmpty, String_isEmpty) \ |
| 84 | 88 |
| 85 #define __ assembler-> | 89 #define __ assembler-> |
| 86 | 90 |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 EBX, // Class register. | 856 EBX, // Class register. |
| 853 &fall_through, | 857 &fall_through, |
| 854 EAX); // Result register. | 858 EAX); // Result register. |
| 855 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 859 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 856 __ ret(); | 860 __ ret(); |
| 857 __ Bind(&fall_through); | 861 __ Bind(&fall_through); |
| 858 return false; | 862 return false; |
| 859 } | 863 } |
| 860 | 864 |
| 861 | 865 |
| 866 static bool Double_isNaN(Assembler* assembler) { | |
| 867 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 868 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 869 Label is_true; | |
| 870 __ movl(EAX, Address(ESP, +1 * kWordSize)); | |
| 871 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | |
| 872 __ comisd(XMM0, XMM0); | |
| 873 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; | |
| 874 __ LoadObject(EAX, bool_false); | |
| 875 __ ret(); | |
| 876 __ Bind(&is_true); | |
| 877 __ LoadObject(EAX, bool_true); | |
| 878 __ ret(); | |
| 879 return true; // Method is complete, no slow case. | |
| 880 } | |
| 881 | |
| 882 | |
| 883 static bool Double_isNegative(Assembler* assembler) { | |
| 884 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 885 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 886 Label is_false, is_true, is_zero, is_nan; | |
| 887 __ movl(EAX, Address(ESP, +1 * kWordSize)); | |
| 888 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | |
| 889 __ xorps(XMM1, XMM1); // 0.0 -> XMM1. | |
| 890 __ comisd(XMM0, XMM1); | |
| 891 __ j(PARITY_EVEN, &is_nan, Assembler::kNearJump); // NaN -> false. | |
| 892 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. | |
| 893 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. | |
| 894 __ Bind(&is_true); | |
| 895 __ LoadObject(EAX, bool_true); | |
| 896 __ ret(); | |
| 897 __ Bind(&is_false); | |
| 898 __ Bind(&is_nan); | |
|
siva
2012/02/02 00:04:26
Why do you have two labels pointing to the same lo
| |
| 899 __ LoadObject(EAX, bool_false); | |
| 900 __ ret(); | |
| 901 __ Bind(&is_zero); | |
| 902 // Check for negative zero (get the sign bit). | |
| 903 __ movmskpd(EAX, XMM0); | |
| 904 __ testl(EAX, Immediate(1)); | |
| 905 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | |
| 906 __ jmp(&is_false, Assembler::kNearJump); | |
| 907 return true; // Method is complete, no slow case. | |
| 908 } | |
| 909 | |
| 910 | |
| 862 // Argument type is not known | 911 // Argument type is not known |
| 863 static bool Math_sqrt(Assembler* assembler) { | 912 static bool Math_sqrt(Assembler* assembler) { |
| 864 Label fall_through, is_smi, double_op; | 913 Label fall_through, is_smi, double_op; |
| 865 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 914 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 866 // Argument is double and is in EAX, class in EBX. | 915 // Argument is double and is in EAX, class in EBX. |
| 867 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 916 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
| 868 __ Bind(&double_op); | 917 __ Bind(&double_op); |
| 869 __ sqrtsd(XMM0, XMM1); | 918 __ sqrtsd(XMM0, XMM1); |
| 870 const Class& double_class = Class::ZoneHandle( | 919 const Class& double_class = Class::ZoneHandle( |
| 871 Isolate::Current()->object_store()->double_class()); | 920 Isolate::Current()->object_store()->double_class()); |
| 872 __ LoadObject(EBX, double_class); | 921 __ LoadObject(EBX, double_class); |
| 873 AssemblerMacros::TryAllocate(assembler, | 922 AssemblerMacros::TryAllocate(assembler, |
| 874 double_class, | 923 double_class, |
| 875 EBX, // Class register. | 924 EBX, // Class register. |
| 876 &fall_through, | 925 &fall_through, |
| 877 EAX); // Result register. | 926 EAX); // Result register. |
| 878 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 927 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 879 __ ret(); | 928 __ ret(); |
| 880 __ Bind(&is_smi); | 929 __ Bind(&is_smi); |
| 881 __ SmiUntag(EAX); | 930 __ SmiUntag(EAX); |
| 882 __ cvtsi2sd(XMM1, EAX); | 931 __ cvtsi2sd(XMM1, EAX); |
| 883 __ jmp(&double_op); | 932 __ jmp(&double_op); |
| 884 __ Bind(&fall_through); | 933 __ Bind(&fall_through); |
| 885 return false; | 934 return false; |
| 886 } | 935 } |
| 887 | 936 |
| 888 | 937 |
| 938 enum TrigonometricFunctions { | |
| 939 kSine, | |
| 940 kCosine, | |
| 941 }; | |
| 942 | |
| 943 | |
| 944 static bool EmitTrigonometric(Assembler* assembler, | |
| 945 TrigonometricFunctions kind) { | |
| 946 Label fall_through, is_smi, double_op; | |
| 947 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | |
| 948 // Argument is double and is in EAX. | |
| 949 __ fldl(FieldAddress(EAX, Double::value_offset())); | |
| 950 __ Bind(&double_op); | |
| 951 switch (kind) { | |
| 952 case kSine: __ fsin(); break; | |
| 953 case kCosine: __ fcos(); break; | |
| 954 default: | |
| 955 UNREACHABLE(); | |
| 956 } | |
| 957 const Class& double_class = Class::ZoneHandle( | |
| 958 Isolate::Current()->object_store()->double_class()); | |
| 959 __ LoadObject(EBX, double_class); | |
| 960 AssemblerMacros::TryAllocate(assembler, | |
| 961 double_class, | |
| 962 EBX, // Class register. | |
| 963 &fall_through, | |
| 964 EAX); // Result register. | |
| 965 __ fstpl(FieldAddress(EAX, Double::value_offset())); | |
| 966 __ ret(); | |
| 967 | |
| 968 __ Bind(&is_smi); // smi -> double. | |
| 969 __ SmiUntag(EAX); | |
| 970 __ pushl(EAX); | |
| 971 __ filds(Address(ESP, 0)); | |
| 972 __ popl(EAX); | |
| 973 __ jmp(&double_op); | |
| 974 | |
| 975 __ Bind(&fall_through); | |
| 976 } | |
| 977 | |
| 978 | |
| 979 static bool Math_sin(Assembler* assembler) { | |
| 980 EmitTrigonometric(assembler, kSine); | |
| 981 return false; // Compile method for slow case. | |
| 982 } | |
| 983 | |
| 984 | |
| 985 static bool Math_cos(Assembler* assembler) { | |
| 986 EmitTrigonometric(assembler, kCosine); | |
| 987 return false; // Compile method for slow case. | |
| 988 } | |
| 989 | |
| 990 | |
| 889 // Identity comparison. | 991 // Identity comparison. |
| 890 static bool Object_equal(Assembler* assembler) { | 992 static bool Object_equal(Assembler* assembler) { |
| 891 Label is_true; | 993 Label is_true; |
| 892 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 994 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 893 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 995 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 894 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 996 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 895 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); | 997 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); |
| 896 __ j(EQUAL, &is_true, Assembler::kNearJump); | 998 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 897 __ LoadObject(EAX, bool_false); | 999 __ LoadObject(EAX, bool_false); |
| 898 __ ret(); | 1000 __ ret(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1060 } \ | 1162 } \ |
| 1061 | 1163 |
| 1062 INTRINSIC_LIST(FIND_INTRINSICS); | 1164 INTRINSIC_LIST(FIND_INTRINSICS); |
| 1063 #undef FIND_INTRINSICS | 1165 #undef FIND_INTRINSICS |
| 1064 return false; | 1166 return false; |
| 1065 } | 1167 } |
| 1066 | 1168 |
| 1067 } // namespace dart | 1169 } // namespace dart |
| 1068 | 1170 |
| 1069 #endif // defined TARGET_ARCH_IA32 | 1171 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |