OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { | 797 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { |
798 return CompareIntegers(assembler, LESS_EQUAL); | 798 return CompareIntegers(assembler, LESS_EQUAL); |
799 } | 799 } |
800 | 800 |
801 | 801 |
802 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { | 802 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { |
803 return CompareIntegers(assembler, GREATER_EQUAL); | 803 return CompareIntegers(assembler, GREATER_EQUAL); |
804 } | 804 } |
805 | 805 |
806 | 806 |
807 // This is called for Smi, Mint and Bigint receivers. Bigints are not handled. | 807 // This is called for Smi, Mint and Bigint receivers. The right argument |
| 808 // can be Smi, Mint, Bigint or double. |
808 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { | 809 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { |
809 Label fall_through, true_label, check_for_mint; | 810 Label fall_through, true_label, check_for_mint; |
810 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 811 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
811 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 812 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
812 // For integer receiver '===' check first. | 813 // For integer receiver '===' check first. |
813 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 814 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
814 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); | 815 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); |
815 __ j(EQUAL, &true_label, Assembler::kNearJump); | 816 __ j(EQUAL, &true_label, Assembler::kNearJump); |
816 __ movl(EBX, Address(ESP, + 2 * kWordSize)); | 817 __ movl(EBX, Address(ESP, + 2 * kWordSize)); |
817 __ orl(EAX, EBX); | 818 __ orl(EAX, EBX); |
818 __ testl(EAX, Immediate(kSmiTagMask)); | 819 __ testl(EAX, Immediate(kSmiTagMask)); |
819 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); | 820 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); |
820 // Both arguments are smi, '===' is good enough. | 821 // Both arguments are smi, '===' is good enough. |
821 __ LoadObject(EAX, bool_false); | 822 __ LoadObject(EAX, bool_false); |
822 __ ret(); | 823 __ ret(); |
823 __ Bind(&true_label); | 824 __ Bind(&true_label); |
824 __ LoadObject(EAX, bool_true); | 825 __ LoadObject(EAX, bool_true); |
825 __ ret(); | 826 __ ret(); |
826 | 827 |
827 // At least one of the arguments was not Smi, inline code for Smi/Mint | 828 // At least one of the arguments was not Smi. |
828 // equality comparison. | |
829 Label receiver_not_smi; | 829 Label receiver_not_smi; |
830 __ Bind(&check_for_mint); | 830 __ Bind(&check_for_mint); |
831 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Receiver. | 831 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Receiver. |
832 __ testl(EAX, Immediate(kSmiTagMask)); | 832 __ testl(EAX, Immediate(kSmiTagMask)); |
833 __ j(NOT_ZERO, &receiver_not_smi); | 833 __ j(NOT_ZERO, &receiver_not_smi); |
834 | 834 |
835 // Note that an instance of Mint never contains a value that can be | 835 // Left (receiver) is Smi, return false if right is not Double. |
| 836 // Note that an instance of Mint or Bigint never contains a value that can be |
836 // represented by Smi. | 837 // represented by Smi. |
837 // Left is Smi, return false if right is Mint, otherwise fall through. | |
838 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. | 838 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. |
839 __ CompareClassId(EAX, kMint, EDI); | 839 __ CompareClassId(EAX, kDouble, EDI); |
840 __ j(NOT_EQUAL, &fall_through); | 840 __ j(EQUAL, &fall_through); |
841 __ LoadObject(EAX, bool_false); // Smi == Mint -> false. | 841 __ LoadObject(EAX, bool_false); // Smi == Mint -> false. |
842 __ ret(); | 842 __ ret(); |
843 | 843 |
844 __ Bind(&receiver_not_smi); | 844 __ Bind(&receiver_not_smi); |
845 // EAX:: receiver. | 845 // EAX:: receiver. |
846 __ CompareClassId(EAX, kMint, EDI); | 846 __ CompareClassId(EAX, kMint, EDI); |
847 __ j(NOT_EQUAL, &fall_through); | 847 __ j(NOT_EQUAL, &fall_through); |
848 // Receiver is Mint, return false if right is Smi. | 848 // Receiver is Mint, return false if right is Smi. |
849 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. | 849 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. |
850 __ testl(EAX, Immediate(kSmiTagMask)); | 850 __ testl(EAX, Immediate(kSmiTagMask)); |
851 __ j(NOT_ZERO, &fall_through); | 851 __ j(NOT_ZERO, &fall_through); |
852 __ LoadObject(EAX, bool_false); // Smi == Mint -> false. | 852 __ LoadObject(EAX, bool_false); |
853 __ ret(); | 853 __ ret(); |
854 // TODO(srdjan): Implement Mint == Mint comparison. | 854 // TODO(srdjan): Implement Mint == Mint comparison. |
855 | 855 |
856 __ Bind(&fall_through); | 856 __ Bind(&fall_through); |
857 return false; | 857 return false; |
858 } | 858 } |
859 | 859 |
860 | 860 |
861 bool Intrinsifier::Integer_equal(Assembler* assembler) { | 861 bool Intrinsifier::Integer_equal(Assembler* assembler) { |
862 return Integer_equalToInteger(assembler); | 862 return Integer_equalToInteger(assembler); |
(...skipping 20 matching lines...) Expand all Loading... |
883 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value. | 883 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value. |
884 __ SmiUntag(EAX); // Value. | 884 __ SmiUntag(EAX); // Value. |
885 __ sarl(EAX, ECX); | 885 __ sarl(EAX, ECX); |
886 __ SmiTag(EAX); | 886 __ SmiTag(EAX); |
887 __ ret(); | 887 __ ret(); |
888 __ Bind(&fall_through); | 888 __ Bind(&fall_through); |
889 return false; | 889 return false; |
890 } | 890 } |
891 | 891 |
892 | 892 |
| 893 // Argument is Smi (receiver). |
893 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { | 894 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { |
894 Label fall_through; | |
895 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Index. | 895 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Index. |
896 __ testl(EAX, Immediate(kSmiTagMask)); | |
897 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi. | |
898 __ notl(EAX); | 896 __ notl(EAX); |
899 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 897 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
900 __ ret(); | 898 __ ret(); |
901 __ Bind(&fall_through); | 899 return true; |
902 return false; | |
903 } | 900 } |
904 | 901 |
905 | 902 |
906 // Check if the last argument is a double, jump to label 'is_smi' if smi | 903 // Check if the last argument is a double, jump to label 'is_smi' if smi |
907 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 904 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
908 // Returns the last argument in EAX. | 905 // Returns the last argument in EAX. |
909 static void TestLastArgumentIsDouble(Assembler* assembler, | 906 static void TestLastArgumentIsDouble(Assembler* assembler, |
910 Label* is_smi, | 907 Label* is_smi, |
911 Label* not_double_smi) { | 908 Label* not_double_smi) { |
912 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 909 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 } | 978 } |
982 | 979 |
983 | 980 |
984 bool Intrinsifier::Double_toDouble(Assembler* assembler) { | 981 bool Intrinsifier::Double_toDouble(Assembler* assembler) { |
985 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 982 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
986 __ ret(); | 983 __ ret(); |
987 return true; | 984 return true; |
988 } | 985 } |
989 | 986 |
990 | 987 |
991 // Expects EAX to contain right argument, left argument is on stack. Left | 988 // Expects left argument to be double (receiver). Right argument is unknown. |
992 // argument is double, right argument is of unknown type. | 989 // Both arguments are on stack. |
993 static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { | 990 static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { |
994 Label fall_through; | 991 Label fall_through; |
995 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); | 992 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); |
996 // Both arguments are double, right operand is in EAX, class in EBX. | 993 // Both arguments are double, right operand is in EAX. |
997 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 994 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
998 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. | 995 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. |
999 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 996 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
1000 switch (kind) { | 997 switch (kind) { |
1001 case Token::kADD: __ addsd(XMM0, XMM1); break; | 998 case Token::kADD: __ addsd(XMM0, XMM1); break; |
1002 case Token::kSUB: __ subsd(XMM0, XMM1); break; | 999 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
1003 case Token::kMUL: __ mulsd(XMM0, XMM1); break; | 1000 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
1004 case Token::kDIV: __ divsd(XMM0, XMM1); break; | 1001 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
1005 default: UNREACHABLE(); | 1002 default: UNREACHABLE(); |
1006 } | 1003 } |
(...skipping 23 matching lines...) Expand all Loading... |
1030 bool Intrinsifier::Double_sub(Assembler* assembler) { | 1027 bool Intrinsifier::Double_sub(Assembler* assembler) { |
1031 return DoubleArithmeticOperations(assembler, Token::kSUB); | 1028 return DoubleArithmeticOperations(assembler, Token::kSUB); |
1032 } | 1029 } |
1033 | 1030 |
1034 | 1031 |
1035 bool Intrinsifier::Double_div(Assembler* assembler) { | 1032 bool Intrinsifier::Double_div(Assembler* assembler) { |
1036 return DoubleArithmeticOperations(assembler, Token::kDIV); | 1033 return DoubleArithmeticOperations(assembler, Token::kDIV); |
1037 } | 1034 } |
1038 | 1035 |
1039 | 1036 |
1040 // Left is double right is integer (bigint or Smi) | 1037 // Left is double right is integer (Bigint, Mint or Smi) |
1041 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { | 1038 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { |
1042 Label fall_through; | 1039 Label fall_through; |
1043 // Only Smi-s allowed. | 1040 // Only Smi-s allowed. |
1044 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 1041 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
1045 __ testl(EAX, Immediate(kSmiTagMask)); | 1042 __ testl(EAX, Immediate(kSmiTagMask)); |
1046 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); | 1043 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); |
1047 // Is Smi. | 1044 // Is Smi. |
1048 __ SmiUntag(EAX); | 1045 __ SmiUntag(EAX); |
1049 __ cvtsi2sd(XMM1, EAX); | 1046 __ cvtsi2sd(XMM1, EAX); |
1050 __ movl(EAX, Address(ESP, + 2 * kWordSize)); | 1047 __ movl(EAX, Address(ESP, + 2 * kWordSize)); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 __ Bind(&is_true); | 1361 __ Bind(&is_true); |
1365 __ LoadObject(EAX, bool_true); | 1362 __ LoadObject(EAX, bool_true); |
1366 __ ret(); | 1363 __ ret(); |
1367 return true; | 1364 return true; |
1368 } | 1365 } |
1369 | 1366 |
1370 #undef __ | 1367 #undef __ |
1371 } // namespace dart | 1368 } // namespace dart |
1372 | 1369 |
1373 #endif // defined TARGET_ARCH_IA32 | 1370 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |