| 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 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 EAX); // Result register. | 1035 EAX); // Result register. |
| 1036 // EBX and EDI are not objects but integer values. | 1036 // EBX and EDI are not objects but integer values. |
| 1037 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); | 1037 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); |
| 1038 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); | 1038 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); |
| 1039 __ ret(); | 1039 __ ret(); |
| 1040 __ Bind(&fall_through); | 1040 __ Bind(&fall_through); |
| 1041 return false; | 1041 return false; |
| 1042 } | 1042 } |
| 1043 | 1043 |
| 1044 | 1044 |
| 1045 static void Push64SmiOrMint(Assembler* assembler, |
| 1046 Register reg, |
| 1047 Register tmp, |
| 1048 Label* not_smi_or_mint) { |
| 1049 Label not_smi, done; |
| 1050 __ testl(reg, Immediate(kSmiTagMask)); |
| 1051 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1052 __ SmiUntag(reg); |
| 1053 // Sign extend to 64 bit |
| 1054 __ movl(tmp, reg); |
| 1055 __ sarl(tmp, Immediate(31)); |
| 1056 __ pushl(tmp); |
| 1057 __ pushl(reg); |
| 1058 __ jmp(&done); |
| 1059 __ Bind(¬_smi); |
| 1060 __ CompareClassId(reg, kMintCid, tmp); |
| 1061 __ j(NOT_EQUAL, not_smi_or_mint); |
| 1062 // Mint. |
| 1063 __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize)); |
| 1064 __ pushl(FieldAddress(reg, Mint::value_offset())); |
| 1065 __ Bind(&done); |
| 1066 } |
| 1067 |
| 1068 |
| 1045 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { | 1069 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { |
| 1046 Label fall_through, true_label; | 1070 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; |
| 1047 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1071 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1048 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1072 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1049 TestBothArgumentsSmis(assembler, &fall_through); | 1073 TestBothArgumentsSmis(assembler, &try_mint_smi); |
| 1050 // EAX contains the right argument. | 1074 // EAX contains the right argument. |
| 1051 __ cmpl(Address(ESP, + 2 * kWordSize), EAX); | 1075 __ cmpl(Address(ESP, + 2 * kWordSize), EAX); |
| 1052 __ j(true_condition, &true_label, Assembler::kNearJump); | 1076 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 1077 __ Bind(&is_false); |
| 1053 __ LoadObject(EAX, bool_false); | 1078 __ LoadObject(EAX, bool_false); |
| 1054 __ ret(); | 1079 __ ret(); |
| 1055 __ Bind(&true_label); | 1080 __ Bind(&is_true); |
| 1056 __ LoadObject(EAX, bool_true); | 1081 __ LoadObject(EAX, bool_true); |
| 1057 __ ret(); | 1082 __ ret(); |
| 1083 |
| 1084 // 64-bit comparison |
| 1085 Condition hi_true_cond, hi_false_cond, lo_false_cond; |
| 1086 switch (true_condition) { |
| 1087 case LESS: |
| 1088 case LESS_EQUAL: |
| 1089 hi_true_cond = LESS; |
| 1090 hi_false_cond = GREATER; |
| 1091 lo_false_cond = (true_condition == LESS) ? ABOVE_EQUAL : ABOVE; |
| 1092 break; |
| 1093 case GREATER: |
| 1094 case GREATER_EQUAL: |
| 1095 hi_true_cond = GREATER; |
| 1096 hi_false_cond = LESS; |
| 1097 lo_false_cond = (true_condition == GREATER) ? BELOW_EQUAL : BELOW; |
| 1098 break; |
| 1099 default: |
| 1100 UNREACHABLE(); |
| 1101 } |
| 1102 __ Bind(&try_mint_smi); |
| 1103 // Note that EDX and ECX must be preserved in case we fall through to main |
| 1104 // method. |
| 1105 // EAX contains the right argument. |
| 1106 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Left argument. |
| 1107 // Push left as 64 bit integer. |
| 1108 Push64SmiOrMint(assembler, EBX, EDI, &fall_through); |
| 1109 // Push right as 64 bit integer. |
| 1110 Push64SmiOrMint(assembler, EAX, EDI, &drop_two_fall_through); |
| 1111 __ popl(EBX); // Right.LO. |
| 1112 __ popl(ECX); // Right.HI. |
| 1113 __ popl(EAX); // Left.LO. |
| 1114 __ popl(EDX); // Left.HI. |
| 1115 __ cmpl(EDX, ECX); // cmpl left.HI, right.HI. |
| 1116 __ j(hi_false_cond, &is_false, Assembler::kNearJump); |
| 1117 __ j(hi_true_cond, &is_true, Assembler::kNearJump); |
| 1118 __ cmpl(EAX, EBX); // cmpl left.LO, right.LO. |
| 1119 __ j(lo_false_cond, &is_false, Assembler::kNearJump); |
| 1120 // Else is true. |
| 1121 __ jmp(&is_true); |
| 1122 |
| 1123 __ Bind(&drop_two_fall_through); |
| 1124 __ Drop(2); |
| 1058 __ Bind(&fall_through); | 1125 __ Bind(&fall_through); |
| 1059 return false; | 1126 return false; |
| 1060 } | 1127 } |
| 1061 | 1128 |
| 1062 | 1129 |
| 1063 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { | |
| 1064 return CompareIntegers(assembler, LESS); | |
| 1065 } | |
| 1066 | |
| 1067 | 1130 |
| 1068 bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { | 1131 bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { |
| 1069 return CompareIntegers(assembler, LESS); | 1132 return CompareIntegers(assembler, LESS); |
| 1070 } | 1133 } |
| 1071 | 1134 |
| 1072 | 1135 |
| 1136 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { |
| 1137 return Integer_greaterThanFromInt(assembler); |
| 1138 } |
| 1139 |
| 1140 |
| 1073 bool Intrinsifier::Integer_greaterThan(Assembler* assembler) { | 1141 bool Intrinsifier::Integer_greaterThan(Assembler* assembler) { |
| 1074 return CompareIntegers(assembler, GREATER); | 1142 return CompareIntegers(assembler, GREATER); |
| 1075 } | 1143 } |
| 1076 | 1144 |
| 1077 | 1145 |
| 1078 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { | 1146 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { |
| 1079 return CompareIntegers(assembler, LESS_EQUAL); | 1147 return CompareIntegers(assembler, LESS_EQUAL); |
| 1080 } | 1148 } |
| 1081 | 1149 |
| 1082 | 1150 |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1663 __ Bind(&is_true); | 1731 __ Bind(&is_true); |
| 1664 __ LoadObject(EAX, bool_true); | 1732 __ LoadObject(EAX, bool_true); |
| 1665 __ ret(); | 1733 __ ret(); |
| 1666 return true; | 1734 return true; |
| 1667 } | 1735 } |
| 1668 | 1736 |
| 1669 #undef __ | 1737 #undef __ |
| 1670 } // namespace dart | 1738 } // namespace dart |
| 1671 | 1739 |
| 1672 #endif // defined TARGET_ARCH_IA32 | 1740 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |