| 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 __ Bind(&overflow); | 980 __ Bind(&overflow); |
| 981 // Mint is rarely used on x64 (only for integers requiring 64 bit instead of | 981 // Mint is rarely used on x64 (only for integers requiring 64 bit instead of |
| 982 // 63 bits as represented by Smi). | 982 // 63 bits as represented by Smi). |
| 983 __ Bind(&fall_through); | 983 __ Bind(&fall_through); |
| 984 return false; | 984 return false; |
| 985 } | 985 } |
| 986 | 986 |
| 987 | 987 |
| 988 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { | 988 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { |
| 989 Label fall_through, true_label; | 989 Label fall_through, true_label; |
| 990 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 991 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 992 TestBothArgumentsSmis(assembler, &fall_through); | 990 TestBothArgumentsSmis(assembler, &fall_through); |
| 993 // RAX contains the right argument. | 991 // RAX contains the right argument. |
| 994 __ cmpq(Address(RSP, + 2 * kWordSize), RAX); | 992 __ cmpq(Address(RSP, + 2 * kWordSize), RAX); |
| 995 __ j(true_condition, &true_label, Assembler::kNearJump); | 993 __ j(true_condition, &true_label, Assembler::kNearJump); |
| 996 __ LoadObject(RAX, bool_false); | 994 __ LoadObject(RAX, Bool::False()); |
| 997 __ ret(); | 995 __ ret(); |
| 998 __ Bind(&true_label); | 996 __ Bind(&true_label); |
| 999 __ LoadObject(RAX, bool_true); | 997 __ LoadObject(RAX, Bool::True()); |
| 1000 __ ret(); | 998 __ ret(); |
| 1001 __ Bind(&fall_through); | 999 __ Bind(&fall_through); |
| 1002 return false; | 1000 return false; |
| 1003 } | 1001 } |
| 1004 | 1002 |
| 1005 | 1003 |
| 1006 | 1004 |
| 1007 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { | 1005 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { |
| 1008 return CompareIntegers(assembler, LESS); | 1006 return CompareIntegers(assembler, LESS); |
| 1009 } | 1007 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1026 | 1024 |
| 1027 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { | 1025 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { |
| 1028 return CompareIntegers(assembler, GREATER_EQUAL); | 1026 return CompareIntegers(assembler, GREATER_EQUAL); |
| 1029 } | 1027 } |
| 1030 | 1028 |
| 1031 | 1029 |
| 1032 // This is called for Smi, Mint and Bigint receivers. The right argument | 1030 // This is called for Smi, Mint and Bigint receivers. The right argument |
| 1033 // can be Smi, Mint, Bigint or double. | 1031 // can be Smi, Mint, Bigint or double. |
| 1034 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { | 1032 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { |
| 1035 Label fall_through, true_label, check_for_mint; | 1033 Label fall_through, true_label, check_for_mint; |
| 1036 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1037 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1038 // For integer receiver '===' check first. | 1034 // For integer receiver '===' check first. |
| 1039 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1035 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 1040 __ movq(RCX, Address(RSP, + 2 * kWordSize)); | 1036 __ movq(RCX, Address(RSP, + 2 * kWordSize)); |
| 1041 __ cmpq(RAX, RCX); | 1037 __ cmpq(RAX, RCX); |
| 1042 __ j(EQUAL, &true_label, Assembler::kNearJump); | 1038 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 1043 __ orq(RAX, RCX); | 1039 __ orq(RAX, RCX); |
| 1044 __ testq(RAX, Immediate(kSmiTagMask)); | 1040 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1045 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); | 1041 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); |
| 1046 // Both arguments are smi, '===' is good enough. | 1042 // Both arguments are smi, '===' is good enough. |
| 1047 __ LoadObject(RAX, bool_false); | 1043 __ LoadObject(RAX, Bool::False()); |
| 1048 __ ret(); | 1044 __ ret(); |
| 1049 __ Bind(&true_label); | 1045 __ Bind(&true_label); |
| 1050 __ LoadObject(RAX, bool_true); | 1046 __ LoadObject(RAX, Bool::True()); |
| 1051 __ ret(); | 1047 __ ret(); |
| 1052 | 1048 |
| 1053 // At least one of the arguments was not Smi. | 1049 // At least one of the arguments was not Smi. |
| 1054 Label receiver_not_smi; | 1050 Label receiver_not_smi; |
| 1055 __ Bind(&check_for_mint); | 1051 __ Bind(&check_for_mint); |
| 1056 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Receiver. | 1052 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Receiver. |
| 1057 __ testq(RAX, Immediate(kSmiTagMask)); | 1053 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1058 __ j(NOT_ZERO, &receiver_not_smi); | 1054 __ j(NOT_ZERO, &receiver_not_smi); |
| 1059 | 1055 |
| 1060 // Left (receiver) is Smi, return false if right is not Double. | 1056 // Left (receiver) is Smi, return false if right is not Double. |
| 1061 // Note that an instance of Mint or Bigint never contains a value that can be | 1057 // Note that an instance of Mint or Bigint never contains a value that can be |
| 1062 // represented by Smi. | 1058 // represented by Smi. |
| 1063 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1059 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 1064 __ CompareClassId(RAX, kDoubleCid); | 1060 __ CompareClassId(RAX, kDoubleCid); |
| 1065 __ j(EQUAL, &fall_through); | 1061 __ j(EQUAL, &fall_through); |
| 1066 __ LoadObject(RAX, bool_false); | 1062 __ LoadObject(RAX, Bool::False()); |
| 1067 __ ret(); | 1063 __ ret(); |
| 1068 | 1064 |
| 1069 __ Bind(&receiver_not_smi); | 1065 __ Bind(&receiver_not_smi); |
| 1070 // RAX:: receiver. | 1066 // RAX:: receiver. |
| 1071 __ CompareClassId(RAX, kMintCid); | 1067 __ CompareClassId(RAX, kMintCid); |
| 1072 __ j(NOT_EQUAL, &fall_through); | 1068 __ j(NOT_EQUAL, &fall_through); |
| 1073 // Receiver is Mint, return false if right is Smi. | 1069 // Receiver is Mint, return false if right is Smi. |
| 1074 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Right argument. | 1070 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Right argument. |
| 1075 __ testq(RAX, Immediate(kSmiTagMask)); | 1071 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1076 __ j(NOT_ZERO, &fall_through); | 1072 __ j(NOT_ZERO, &fall_through); |
| 1077 __ LoadObject(RAX, bool_false); // Smi == Mint -> false. | 1073 __ LoadObject(RAX, Bool::False()); // Smi == Mint -> false. |
| 1078 __ ret(); | 1074 __ ret(); |
| 1079 // TODO(srdjan): Implement Mint == Mint comparison. | 1075 // TODO(srdjan): Implement Mint == Mint comparison. |
| 1080 | 1076 |
| 1081 __ Bind(&fall_through); | 1077 __ Bind(&fall_through); |
| 1082 return false; | 1078 return false; |
| 1083 } | 1079 } |
| 1084 | 1080 |
| 1085 | 1081 |
| 1086 bool Intrinsifier::Integer_equal(Assembler* assembler) { | 1082 bool Intrinsifier::Integer_equal(Assembler* assembler) { |
| 1087 return Integer_equalToInteger(assembler); | 1083 return Integer_equalToInteger(assembler); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); | 1133 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); |
| 1138 // Fall through if double. | 1134 // Fall through if double. |
| 1139 } | 1135 } |
| 1140 | 1136 |
| 1141 | 1137 |
| 1142 // Both arguments on stack, left argument is a double, right argument is of | 1138 // Both arguments on stack, left argument is a double, right argument is of |
| 1143 // unknown type. Return true or false object in RAX. Any NaN argument | 1139 // unknown type. Return true or false object in RAX. Any NaN argument |
| 1144 // returns false. Any non-double argument causes control flow to fall through | 1140 // returns false. Any non-double argument causes control flow to fall through |
| 1145 // to the slow case (compiled method body). | 1141 // to the slow case (compiled method body). |
| 1146 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { | 1142 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { |
| 1147 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1148 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1149 Label fall_through, is_false, is_true, is_smi, double_op; | 1143 Label fall_through, is_false, is_true, is_smi, double_op; |
| 1150 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1144 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1151 // Both arguments are double, right operand is in RAX. | 1145 // Both arguments are double, right operand is in RAX. |
| 1152 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 1146 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
| 1153 __ Bind(&double_op); | 1147 __ Bind(&double_op); |
| 1154 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. | 1148 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. |
| 1155 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1149 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 1156 __ comisd(XMM0, XMM1); | 1150 __ comisd(XMM0, XMM1); |
| 1157 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; | 1151 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
| 1158 __ j(true_condition, &is_true, Assembler::kNearJump); | 1152 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 1159 // Fall through false. | 1153 // Fall through false. |
| 1160 __ Bind(&is_false); | 1154 __ Bind(&is_false); |
| 1161 __ LoadObject(RAX, bool_false); | 1155 __ LoadObject(RAX, Bool::False()); |
| 1162 __ ret(); | 1156 __ ret(); |
| 1163 __ Bind(&is_true); | 1157 __ Bind(&is_true); |
| 1164 __ LoadObject(RAX, bool_true); | 1158 __ LoadObject(RAX, Bool::True()); |
| 1165 __ ret(); | 1159 __ ret(); |
| 1166 __ Bind(&is_smi); | 1160 __ Bind(&is_smi); |
| 1167 __ SmiUntag(RAX); | 1161 __ SmiUntag(RAX); |
| 1168 __ cvtsi2sd(XMM1, RAX); | 1162 __ cvtsi2sd(XMM1, RAX); |
| 1169 __ jmp(&double_op); | 1163 __ jmp(&double_op); |
| 1170 __ Bind(&fall_through); | 1164 __ Bind(&fall_through); |
| 1171 return false; | 1165 return false; |
| 1172 } | 1166 } |
| 1173 | 1167 |
| 1174 | 1168 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1290 Assembler::kNearJump, | 1284 Assembler::kNearJump, |
| 1291 RAX); // Result register. | 1285 RAX); // Result register. |
| 1292 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1286 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 1293 __ ret(); | 1287 __ ret(); |
| 1294 __ Bind(&fall_through); | 1288 __ Bind(&fall_through); |
| 1295 return false; | 1289 return false; |
| 1296 } | 1290 } |
| 1297 | 1291 |
| 1298 | 1292 |
| 1299 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1293 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
| 1300 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1301 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1302 Label is_true; | 1294 Label is_true; |
| 1303 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1295 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 1304 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1296 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 1305 __ comisd(XMM0, XMM0); | 1297 __ comisd(XMM0, XMM0); |
| 1306 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; | 1298 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; |
| 1307 __ LoadObject(RAX, bool_false); | 1299 __ LoadObject(RAX, Bool::False()); |
| 1308 __ ret(); | 1300 __ ret(); |
| 1309 __ Bind(&is_true); | 1301 __ Bind(&is_true); |
| 1310 __ LoadObject(RAX, bool_true); | 1302 __ LoadObject(RAX, Bool::True()); |
| 1311 __ ret(); | 1303 __ ret(); |
| 1312 return true; // Method is complete, no slow case. | 1304 return true; // Method is complete, no slow case. |
| 1313 } | 1305 } |
| 1314 | 1306 |
| 1315 | 1307 |
| 1316 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { | 1308 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { |
| 1317 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1318 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1319 Label is_false, is_true, is_zero; | 1309 Label is_false, is_true, is_zero; |
| 1320 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1310 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 1321 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1311 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 1322 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. | 1312 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. |
| 1323 __ comisd(XMM0, XMM1); | 1313 __ comisd(XMM0, XMM1); |
| 1324 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. | 1314 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. |
| 1325 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. | 1315 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. |
| 1326 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. | 1316 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. |
| 1327 __ Bind(&is_true); | 1317 __ Bind(&is_true); |
| 1328 __ LoadObject(RAX, bool_true); | 1318 __ LoadObject(RAX, Bool::True()); |
| 1329 __ ret(); | 1319 __ ret(); |
| 1330 __ Bind(&is_false); | 1320 __ Bind(&is_false); |
| 1331 __ LoadObject(RAX, bool_false); | 1321 __ LoadObject(RAX, Bool::False()); |
| 1332 __ ret(); | 1322 __ ret(); |
| 1333 __ Bind(&is_zero); | 1323 __ Bind(&is_zero); |
| 1334 // Check for negative zero (get the sign bit). | 1324 // Check for negative zero (get the sign bit). |
| 1335 __ movmskpd(RAX, XMM0); | 1325 __ movmskpd(RAX, XMM0); |
| 1336 __ testq(RAX, Immediate(1)); | 1326 __ testq(RAX, Immediate(1)); |
| 1337 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1327 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| 1338 __ jmp(&is_false, Assembler::kNearJump); | 1328 __ jmp(&is_false, Assembler::kNearJump); |
| 1339 return true; // Method is complete, no slow case. | 1329 return true; // Method is complete, no slow case. |
| 1340 } | 1330 } |
| 1341 | 1331 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 | 1425 |
| 1436 bool Intrinsifier::Math_cos(Assembler* assembler) { | 1426 bool Intrinsifier::Math_cos(Assembler* assembler) { |
| 1437 EmitTrigonometric(assembler, kCosine); | 1427 EmitTrigonometric(assembler, kCosine); |
| 1438 return false; // Compile method for slow case. | 1428 return false; // Compile method for slow case. |
| 1439 } | 1429 } |
| 1440 | 1430 |
| 1441 | 1431 |
| 1442 // Identity comparison. | 1432 // Identity comparison. |
| 1443 bool Intrinsifier::Object_equal(Assembler* assembler) { | 1433 bool Intrinsifier::Object_equal(Assembler* assembler) { |
| 1444 Label is_true; | 1434 Label is_true; |
| 1445 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1446 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1447 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1435 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 1448 __ cmpq(RAX, Address(RSP, + 2 * kWordSize)); | 1436 __ cmpq(RAX, Address(RSP, + 2 * kWordSize)); |
| 1449 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1437 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1450 __ LoadObject(RAX, bool_false); | 1438 __ LoadObject(RAX, Bool::False()); |
| 1451 __ ret(); | 1439 __ ret(); |
| 1452 __ Bind(&is_true); | 1440 __ Bind(&is_true); |
| 1453 __ LoadObject(RAX, bool_true); | 1441 __ LoadObject(RAX, Bool::True()); |
| 1454 __ ret(); | 1442 __ ret(); |
| 1455 return true; | 1443 return true; |
| 1456 } | 1444 } |
| 1457 | 1445 |
| 1458 | 1446 |
| 1459 static intptr_t GetOffsetForField(const char* class_name_p, | 1447 static intptr_t GetOffsetForField(const char* class_name_p, |
| 1460 const char* field_name_p) { | 1448 const char* field_name_p) { |
| 1461 const String& class_name = String::Handle(Symbols::New(class_name_p)); | 1449 const String& class_name = String::Handle(Symbols::New(class_name_p)); |
| 1462 const String& field_name = String::Handle(Symbols::New(field_name_p)); | 1450 const String& field_name = String::Handle(Symbols::New(field_name_p)); |
| 1463 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 1451 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 return false; | 1506 return false; |
| 1519 } | 1507 } |
| 1520 | 1508 |
| 1521 | 1509 |
| 1522 // Class 'FixedSizeArrayIterator': | 1510 // Class 'FixedSizeArrayIterator': |
| 1523 // bool get hasNext { | 1511 // bool get hasNext { |
| 1524 // return _length > _pos; | 1512 // return _length > _pos; |
| 1525 // } | 1513 // } |
| 1526 bool Intrinsifier::FixedSizeArrayIterator_getHasNext(Assembler* assembler) { | 1514 bool Intrinsifier::FixedSizeArrayIterator_getHasNext(Assembler* assembler) { |
| 1527 Label fall_through, is_true; | 1515 Label fall_through, is_true; |
| 1528 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1529 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1530 const intptr_t length_offset = | 1516 const intptr_t length_offset = |
| 1531 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length"); | 1517 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length"); |
| 1532 const intptr_t pos_offset = | 1518 const intptr_t pos_offset = |
| 1533 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); | 1519 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); |
| 1534 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver. | 1520 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver. |
| 1535 __ movq(RCX, FieldAddress(RAX, length_offset)); // Field _length. | 1521 __ movq(RCX, FieldAddress(RAX, length_offset)); // Field _length. |
| 1536 __ movq(RAX, FieldAddress(RAX, pos_offset)); // Field _pos. | 1522 __ movq(RAX, FieldAddress(RAX, pos_offset)); // Field _pos. |
| 1537 __ movq(RDI, RAX); | 1523 __ movq(RDI, RAX); |
| 1538 __ orq(RDI, RCX); | 1524 __ orq(RDI, RCX); |
| 1539 __ testq(RDI, Immediate(kSmiTagMask)); | 1525 __ testq(RDI, Immediate(kSmiTagMask)); |
| 1540 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length/_pos. | 1526 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length/_pos. |
| 1541 __ cmpq(RCX, RAX); // _length > _pos. | 1527 __ cmpq(RCX, RAX); // _length > _pos. |
| 1542 __ j(GREATER, &is_true, Assembler::kNearJump); | 1528 __ j(GREATER, &is_true, Assembler::kNearJump); |
| 1543 __ LoadObject(RAX, bool_false); | 1529 __ LoadObject(RAX, Bool::False()); |
| 1544 __ ret(); | 1530 __ ret(); |
| 1545 __ Bind(&is_true); | 1531 __ Bind(&is_true); |
| 1546 __ LoadObject(RAX, bool_true); | 1532 __ LoadObject(RAX, Bool::True()); |
| 1547 __ ret(); | 1533 __ ret(); |
| 1548 __ Bind(&fall_through); | 1534 __ Bind(&fall_through); |
| 1549 return false; | 1535 return false; |
| 1550 } | 1536 } |
| 1551 | 1537 |
| 1552 | 1538 |
| 1553 bool Intrinsifier::String_getHashCode(Assembler* assembler) { | 1539 bool Intrinsifier::String_getHashCode(Assembler* assembler) { |
| 1554 Label fall_through; | 1540 Label fall_through; |
| 1555 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1541 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1556 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1542 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); | 1574 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); |
| 1589 __ SmiTag(RAX); | 1575 __ SmiTag(RAX); |
| 1590 __ ret(); | 1576 __ ret(); |
| 1591 __ Bind(&fall_through); | 1577 __ Bind(&fall_through); |
| 1592 return false; | 1578 return false; |
| 1593 } | 1579 } |
| 1594 | 1580 |
| 1595 | 1581 |
| 1596 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { | 1582 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { |
| 1597 Label is_true; | 1583 Label is_true; |
| 1598 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1599 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1600 // Get length. | 1584 // Get length. |
| 1601 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1585 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1602 __ movq(RAX, FieldAddress(RAX, String::length_offset())); | 1586 __ movq(RAX, FieldAddress(RAX, String::length_offset())); |
| 1603 __ cmpq(RAX, Immediate(Smi::RawValue(0))); | 1587 __ cmpq(RAX, Immediate(Smi::RawValue(0))); |
| 1604 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1588 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1605 __ LoadObject(RAX, bool_false); | 1589 __ LoadObject(RAX, Bool::False()); |
| 1606 __ ret(); | 1590 __ ret(); |
| 1607 __ Bind(&is_true); | 1591 __ Bind(&is_true); |
| 1608 __ LoadObject(RAX, bool_true); | 1592 __ LoadObject(RAX, Bool::True()); |
| 1609 __ ret(); | 1593 __ ret(); |
| 1610 return true; | 1594 return true; |
| 1611 } | 1595 } |
| 1612 | 1596 |
| 1613 #undef __ | 1597 #undef __ |
| 1614 | 1598 |
| 1615 } // namespace dart | 1599 } // namespace dart |
| 1616 | 1600 |
| 1617 #endif // defined TARGET_ARCH_X64 | 1601 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |