| 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 |