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 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 __ j(NOT_EQUAL, not_smi_or_mint); | 1068 __ j(NOT_EQUAL, not_smi_or_mint); |
1069 // Mint. | 1069 // Mint. |
1070 __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize)); | 1070 __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize)); |
1071 __ pushl(FieldAddress(reg, Mint::value_offset())); | 1071 __ pushl(FieldAddress(reg, Mint::value_offset())); |
1072 __ Bind(&done); | 1072 __ Bind(&done); |
1073 } | 1073 } |
1074 | 1074 |
1075 | 1075 |
1076 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { | 1076 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { |
1077 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; | 1077 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; |
1078 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1079 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1080 TestBothArgumentsSmis(assembler, &try_mint_smi); | 1078 TestBothArgumentsSmis(assembler, &try_mint_smi); |
1081 // EAX contains the right argument. | 1079 // EAX contains the right argument. |
1082 __ cmpl(Address(ESP, + 2 * kWordSize), EAX); | 1080 __ cmpl(Address(ESP, + 2 * kWordSize), EAX); |
1083 __ j(true_condition, &is_true, Assembler::kNearJump); | 1081 __ j(true_condition, &is_true, Assembler::kNearJump); |
1084 __ Bind(&is_false); | 1082 __ Bind(&is_false); |
1085 __ LoadObject(EAX, bool_false); | 1083 __ LoadObject(EAX, Bool::False()); |
1086 __ ret(); | 1084 __ ret(); |
1087 __ Bind(&is_true); | 1085 __ Bind(&is_true); |
1088 __ LoadObject(EAX, bool_true); | 1086 __ LoadObject(EAX, Bool::True()); |
1089 __ ret(); | 1087 __ ret(); |
1090 | 1088 |
1091 // 64-bit comparison | 1089 // 64-bit comparison |
1092 Condition hi_true_cond, hi_false_cond, lo_false_cond; | 1090 Condition hi_true_cond, hi_false_cond, lo_false_cond; |
1093 switch (true_condition) { | 1091 switch (true_condition) { |
1094 case LESS: | 1092 case LESS: |
1095 case LESS_EQUAL: | 1093 case LESS_EQUAL: |
1096 hi_true_cond = LESS; | 1094 hi_true_cond = LESS; |
1097 hi_false_cond = GREATER; | 1095 hi_false_cond = GREATER; |
1098 lo_false_cond = (true_condition == LESS) ? ABOVE_EQUAL : ABOVE; | 1096 lo_false_cond = (true_condition == LESS) ? ABOVE_EQUAL : ABOVE; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1156 |
1159 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { | 1157 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { |
1160 return CompareIntegers(assembler, GREATER_EQUAL); | 1158 return CompareIntegers(assembler, GREATER_EQUAL); |
1161 } | 1159 } |
1162 | 1160 |
1163 | 1161 |
1164 // This is called for Smi, Mint and Bigint receivers. The right argument | 1162 // This is called for Smi, Mint and Bigint receivers. The right argument |
1165 // can be Smi, Mint, Bigint or double. | 1163 // can be Smi, Mint, Bigint or double. |
1166 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { | 1164 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { |
1167 Label fall_through, true_label, check_for_mint; | 1165 Label fall_through, true_label, check_for_mint; |
1168 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1169 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1170 // For integer receiver '===' check first. | 1166 // For integer receiver '===' check first. |
1171 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 1167 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
1172 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); | 1168 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); |
1173 __ j(EQUAL, &true_label, Assembler::kNearJump); | 1169 __ j(EQUAL, &true_label, Assembler::kNearJump); |
1174 __ movl(EBX, Address(ESP, + 2 * kWordSize)); | 1170 __ movl(EBX, Address(ESP, + 2 * kWordSize)); |
1175 __ orl(EAX, EBX); | 1171 __ orl(EAX, EBX); |
1176 __ testl(EAX, Immediate(kSmiTagMask)); | 1172 __ testl(EAX, Immediate(kSmiTagMask)); |
1177 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); | 1173 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); |
1178 // Both arguments are smi, '===' is good enough. | 1174 // Both arguments are smi, '===' is good enough. |
1179 __ LoadObject(EAX, bool_false); | 1175 __ LoadObject(EAX, Bool::False()); |
1180 __ ret(); | 1176 __ ret(); |
1181 __ Bind(&true_label); | 1177 __ Bind(&true_label); |
1182 __ LoadObject(EAX, bool_true); | 1178 __ LoadObject(EAX, Bool::True()); |
1183 __ ret(); | 1179 __ ret(); |
1184 | 1180 |
1185 // At least one of the arguments was not Smi. | 1181 // At least one of the arguments was not Smi. |
1186 Label receiver_not_smi; | 1182 Label receiver_not_smi; |
1187 __ Bind(&check_for_mint); | 1183 __ Bind(&check_for_mint); |
1188 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Receiver. | 1184 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Receiver. |
1189 __ testl(EAX, Immediate(kSmiTagMask)); | 1185 __ testl(EAX, Immediate(kSmiTagMask)); |
1190 __ j(NOT_ZERO, &receiver_not_smi); | 1186 __ j(NOT_ZERO, &receiver_not_smi); |
1191 | 1187 |
1192 // Left (receiver) is Smi, return false if right is not Double. | 1188 // Left (receiver) is Smi, return false if right is not Double. |
1193 // Note that an instance of Mint or Bigint never contains a value that can be | 1189 // Note that an instance of Mint or Bigint never contains a value that can be |
1194 // represented by Smi. | 1190 // represented by Smi. |
1195 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. | 1191 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. |
1196 __ CompareClassId(EAX, kDoubleCid, EDI); | 1192 __ CompareClassId(EAX, kDoubleCid, EDI); |
1197 __ j(EQUAL, &fall_through); | 1193 __ j(EQUAL, &fall_through); |
1198 __ LoadObject(EAX, bool_false); // Smi == Mint -> false. | 1194 __ LoadObject(EAX, Bool::False()); // Smi == Mint -> false. |
1199 __ ret(); | 1195 __ ret(); |
1200 | 1196 |
1201 __ Bind(&receiver_not_smi); | 1197 __ Bind(&receiver_not_smi); |
1202 // EAX:: receiver. | 1198 // EAX:: receiver. |
1203 __ CompareClassId(EAX, kMintCid, EDI); | 1199 __ CompareClassId(EAX, kMintCid, EDI); |
1204 __ j(NOT_EQUAL, &fall_through); | 1200 __ j(NOT_EQUAL, &fall_through); |
1205 // Receiver is Mint, return false if right is Smi. | 1201 // Receiver is Mint, return false if right is Smi. |
1206 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. | 1202 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. |
1207 __ testl(EAX, Immediate(kSmiTagMask)); | 1203 __ testl(EAX, Immediate(kSmiTagMask)); |
1208 __ j(NOT_ZERO, &fall_through); | 1204 __ j(NOT_ZERO, &fall_through); |
1209 __ LoadObject(EAX, bool_false); | 1205 __ LoadObject(EAX, Bool::False()); |
1210 __ ret(); | 1206 __ ret(); |
1211 // TODO(srdjan): Implement Mint == Mint comparison. | 1207 // TODO(srdjan): Implement Mint == Mint comparison. |
1212 | 1208 |
1213 __ Bind(&fall_through); | 1209 __ Bind(&fall_through); |
1214 return false; | 1210 return false; |
1215 } | 1211 } |
1216 | 1212 |
1217 | 1213 |
1218 bool Intrinsifier::Integer_equal(Assembler* assembler) { | 1214 bool Intrinsifier::Integer_equal(Assembler* assembler) { |
1219 return Integer_equalToInteger(assembler); | 1215 return Integer_equalToInteger(assembler); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); | 1266 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); |
1271 // Fall through if double. | 1267 // Fall through if double. |
1272 } | 1268 } |
1273 | 1269 |
1274 | 1270 |
1275 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown | 1271 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown |
1276 // type. Return true or false object in the register EAX. Any NaN argument | 1272 // type. Return true or false object in the register EAX. Any NaN argument |
1277 // returns false. Any non-double arg1 causes control flow to fall through to the | 1273 // returns false. Any non-double arg1 causes control flow to fall through to the |
1278 // slow case (compiled method body). | 1274 // slow case (compiled method body). |
1279 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { | 1275 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { |
1280 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1281 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1282 Label fall_through, is_false, is_true, is_smi, double_op; | 1276 Label fall_through, is_false, is_true, is_smi, double_op; |
1283 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1277 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1284 // Both arguments are double, right operand is in EAX. | 1278 // Both arguments are double, right operand is in EAX. |
1285 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 1279 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
1286 __ Bind(&double_op); | 1280 __ Bind(&double_op); |
1287 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. | 1281 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. |
1288 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1282 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
1289 __ comisd(XMM0, XMM1); | 1283 __ comisd(XMM0, XMM1); |
1290 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; | 1284 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
1291 __ j(true_condition, &is_true, Assembler::kNearJump); | 1285 __ j(true_condition, &is_true, Assembler::kNearJump); |
1292 // Fall through false. | 1286 // Fall through false. |
1293 __ Bind(&is_false); | 1287 __ Bind(&is_false); |
1294 __ LoadObject(EAX, bool_false); | 1288 __ LoadObject(EAX, Bool::False()); |
1295 __ ret(); | 1289 __ ret(); |
1296 __ Bind(&is_true); | 1290 __ Bind(&is_true); |
1297 __ LoadObject(EAX, bool_true); | 1291 __ LoadObject(EAX, Bool::True()); |
1298 __ ret(); | 1292 __ ret(); |
1299 __ Bind(&is_smi); | 1293 __ Bind(&is_smi); |
1300 __ SmiUntag(EAX); | 1294 __ SmiUntag(EAX); |
1301 __ cvtsi2sd(XMM1, EAX); | 1295 __ cvtsi2sd(XMM1, EAX); |
1302 __ jmp(&double_op); | 1296 __ jmp(&double_op); |
1303 __ Bind(&fall_through); | 1297 __ Bind(&fall_through); |
1304 return false; | 1298 return false; |
1305 } | 1299 } |
1306 | 1300 |
1307 | 1301 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 Assembler::kNearJump, | 1422 Assembler::kNearJump, |
1429 EAX); // Result register. | 1423 EAX); // Result register. |
1430 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 1424 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
1431 __ ret(); | 1425 __ ret(); |
1432 __ Bind(&fall_through); | 1426 __ Bind(&fall_through); |
1433 return false; | 1427 return false; |
1434 } | 1428 } |
1435 | 1429 |
1436 | 1430 |
1437 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1431 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
1438 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1439 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1440 Label is_true; | 1432 Label is_true; |
1441 __ movl(EAX, Address(ESP, +1 * kWordSize)); | 1433 __ movl(EAX, Address(ESP, +1 * kWordSize)); |
1442 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1434 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
1443 __ comisd(XMM0, XMM0); | 1435 __ comisd(XMM0, XMM0); |
1444 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; | 1436 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; |
1445 __ LoadObject(EAX, bool_false); | 1437 __ LoadObject(EAX, Bool::False()); |
1446 __ ret(); | 1438 __ ret(); |
1447 __ Bind(&is_true); | 1439 __ Bind(&is_true); |
1448 __ LoadObject(EAX, bool_true); | 1440 __ LoadObject(EAX, Bool::True()); |
1449 __ ret(); | 1441 __ ret(); |
1450 return true; // Method is complete, no slow case. | 1442 return true; // Method is complete, no slow case. |
1451 } | 1443 } |
1452 | 1444 |
1453 | 1445 |
1454 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { | 1446 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { |
1455 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1456 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1457 Label is_false, is_true, is_zero; | 1447 Label is_false, is_true, is_zero; |
1458 __ movl(EAX, Address(ESP, +1 * kWordSize)); | 1448 __ movl(EAX, Address(ESP, +1 * kWordSize)); |
1459 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1449 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
1460 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. | 1450 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. |
1461 __ comisd(XMM0, XMM1); | 1451 __ comisd(XMM0, XMM1); |
1462 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. | 1452 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. |
1463 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. | 1453 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. |
1464 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. | 1454 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. |
1465 __ Bind(&is_true); | 1455 __ Bind(&is_true); |
1466 __ LoadObject(EAX, bool_true); | 1456 __ LoadObject(EAX, Bool::True()); |
1467 __ ret(); | 1457 __ ret(); |
1468 __ Bind(&is_false); | 1458 __ Bind(&is_false); |
1469 __ LoadObject(EAX, bool_false); | 1459 __ LoadObject(EAX, Bool::False()); |
1470 __ ret(); | 1460 __ ret(); |
1471 __ Bind(&is_zero); | 1461 __ Bind(&is_zero); |
1472 // Check for negative zero (get the sign bit). | 1462 // Check for negative zero (get the sign bit). |
1473 __ movmskpd(EAX, XMM0); | 1463 __ movmskpd(EAX, XMM0); |
1474 __ testl(EAX, Immediate(1)); | 1464 __ testl(EAX, Immediate(1)); |
1475 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1465 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
1476 __ jmp(&is_false, Assembler::kNearJump); | 1466 __ jmp(&is_false, Assembler::kNearJump); |
1477 return true; // Method is complete, no slow case. | 1467 return true; // Method is complete, no slow case. |
1478 } | 1468 } |
1479 | 1469 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 | 1563 |
1574 bool Intrinsifier::Math_cos(Assembler* assembler) { | 1564 bool Intrinsifier::Math_cos(Assembler* assembler) { |
1575 EmitTrigonometric(assembler, kCosine); | 1565 EmitTrigonometric(assembler, kCosine); |
1576 return false; // Compile method for slow case. | 1566 return false; // Compile method for slow case. |
1577 } | 1567 } |
1578 | 1568 |
1579 | 1569 |
1580 // Identity comparison. | 1570 // Identity comparison. |
1581 bool Intrinsifier::Object_equal(Assembler* assembler) { | 1571 bool Intrinsifier::Object_equal(Assembler* assembler) { |
1582 Label is_true; | 1572 Label is_true; |
1583 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1584 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1585 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 1573 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
1586 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); | 1574 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); |
1587 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1575 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1588 __ LoadObject(EAX, bool_false); | 1576 __ LoadObject(EAX, Bool::False()); |
1589 __ ret(); | 1577 __ ret(); |
1590 __ Bind(&is_true); | 1578 __ Bind(&is_true); |
1591 __ LoadObject(EAX, bool_true); | 1579 __ LoadObject(EAX, Bool::True()); |
1592 __ ret(); | 1580 __ ret(); |
1593 return true; | 1581 return true; |
1594 } | 1582 } |
1595 | 1583 |
1596 | 1584 |
1597 static const char* kFixedSizeArrayIteratorClassName = "_FixedSizeArrayIterator"; | 1585 static const char* kFixedSizeArrayIteratorClassName = "_FixedSizeArrayIterator"; |
1598 | 1586 |
1599 | 1587 |
1600 // Class 'FixedSizeArrayIterator': | 1588 // Class 'FixedSizeArrayIterator': |
1601 // T next() { | 1589 // T next() { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 return false; | 1631 return false; |
1644 } | 1632 } |
1645 | 1633 |
1646 | 1634 |
1647 // Class 'FixedSizeArrayIterator': | 1635 // Class 'FixedSizeArrayIterator': |
1648 // bool get hasNext { | 1636 // bool get hasNext { |
1649 // return _length > _pos; | 1637 // return _length > _pos; |
1650 // } | 1638 // } |
1651 bool Intrinsifier::FixedSizeArrayIterator_getHasNext(Assembler* assembler) { | 1639 bool Intrinsifier::FixedSizeArrayIterator_getHasNext(Assembler* assembler) { |
1652 Label fall_through, is_true; | 1640 Label fall_through, is_true; |
1653 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1654 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1655 intptr_t length_offset = | 1641 intptr_t length_offset = |
1656 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length"); | 1642 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length"); |
1657 intptr_t pos_offset = | 1643 intptr_t pos_offset = |
1658 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); | 1644 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); |
1659 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Receiver. | 1645 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Receiver. |
1660 __ movl(EBX, FieldAddress(EAX, length_offset)); // Field _length. | 1646 __ movl(EBX, FieldAddress(EAX, length_offset)); // Field _length. |
1661 __ movl(EAX, FieldAddress(EAX, pos_offset)); // Field _pos. | 1647 __ movl(EAX, FieldAddress(EAX, pos_offset)); // Field _pos. |
1662 __ movl(EDI, EAX); | 1648 __ movl(EDI, EAX); |
1663 __ orl(EDI, EBX); | 1649 __ orl(EDI, EBX); |
1664 __ testl(EDI, Immediate(kSmiTagMask)); | 1650 __ testl(EDI, Immediate(kSmiTagMask)); |
1665 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length. | 1651 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length. |
1666 __ cmpl(EBX, EAX); // _length > _pos. | 1652 __ cmpl(EBX, EAX); // _length > _pos. |
1667 __ j(GREATER, &is_true, Assembler::kNearJump); | 1653 __ j(GREATER, &is_true, Assembler::kNearJump); |
1668 __ LoadObject(EAX, bool_false); | 1654 __ LoadObject(EAX, Bool::False()); |
1669 __ ret(); | 1655 __ ret(); |
1670 __ Bind(&is_true); | 1656 __ Bind(&is_true); |
1671 __ LoadObject(EAX, bool_true); | 1657 __ LoadObject(EAX, Bool::True()); |
1672 __ ret(); | 1658 __ ret(); |
1673 __ Bind(&fall_through); | 1659 __ Bind(&fall_through); |
1674 return false; | 1660 return false; |
1675 } | 1661 } |
1676 | 1662 |
1677 | 1663 |
1678 bool Intrinsifier::String_getHashCode(Assembler* assembler) { | 1664 bool Intrinsifier::String_getHashCode(Assembler* assembler) { |
1679 Label fall_through; | 1665 Label fall_through; |
1680 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1666 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
1681 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); | 1667 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); | 1699 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); |
1714 __ SmiTag(EAX); | 1700 __ SmiTag(EAX); |
1715 __ ret(); | 1701 __ ret(); |
1716 __ Bind(&fall_through); | 1702 __ Bind(&fall_through); |
1717 return false; | 1703 return false; |
1718 } | 1704 } |
1719 | 1705 |
1720 | 1706 |
1721 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { | 1707 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { |
1722 Label is_true; | 1708 Label is_true; |
1723 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
1724 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
1725 // Get length. | 1709 // Get length. |
1726 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1710 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
1727 __ movl(EAX, FieldAddress(EAX, String::length_offset())); | 1711 __ movl(EAX, FieldAddress(EAX, String::length_offset())); |
1728 __ cmpl(EAX, Immediate(Smi::RawValue(0))); | 1712 __ cmpl(EAX, Immediate(Smi::RawValue(0))); |
1729 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1713 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1730 __ LoadObject(EAX, bool_false); | 1714 __ LoadObject(EAX, Bool::False()); |
1731 __ ret(); | 1715 __ ret(); |
1732 __ Bind(&is_true); | 1716 __ Bind(&is_true); |
1733 __ LoadObject(EAX, bool_true); | 1717 __ LoadObject(EAX, Bool::True()); |
1734 __ ret(); | 1718 __ ret(); |
1735 return true; | 1719 return true; |
1736 } | 1720 } |
1737 | 1721 |
1738 #undef __ | 1722 #undef __ |
1739 } // namespace dart | 1723 } // namespace dart |
1740 | 1724 |
1741 #endif // defined TARGET_ARCH_IA32 | 1725 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |