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 |