| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 |
| 11 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 11 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 12 #if defined(TARGET_ARCH_IA32) | 12 #if defined(TARGET_ARCH_IA32) |
| 13 | 13 |
| 14 #include "vm/intrinsifier.h" | 14 #include "vm/intrinsifier.h" |
| 15 | 15 |
| 16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
| 17 #include "vm/assembler_macros.h" | |
| 18 #include "vm/object.h" | 17 #include "vm/object.h" |
| 19 #include "vm/object_store.h" | 18 #include "vm/object_store.h" |
| 20 #include "vm/os.h" | 19 #include "vm/os.h" |
| 21 #include "vm/stub_code.h" | 20 #include "vm/stub_code.h" |
| 22 #include "vm/symbols.h" | 21 #include "vm/symbols.h" |
| 23 | 22 |
| 24 namespace dart { | 23 namespace dart { |
| 25 | 24 |
| 26 DECLARE_FLAG(bool, enable_type_checks); | 25 DECLARE_FLAG(bool, enable_type_checks); |
| 27 | 26 |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 // TODO(srdjan): Implement negative values, for now fall through. | 924 // TODO(srdjan): Implement negative values, for now fall through. |
| 926 __ j(LESS, &fall_through, Assembler::kNearJump); | 925 __ j(LESS, &fall_through, Assembler::kNearJump); |
| 927 __ SmiUntag(EBX); | 926 __ SmiUntag(EBX); |
| 928 __ movl(EAX, EBX); | 927 __ movl(EAX, EBX); |
| 929 __ shll(EBX, ECX); | 928 __ shll(EBX, ECX); |
| 930 __ xorl(EDI, EDI); | 929 __ xorl(EDI, EDI); |
| 931 __ shld(EDI, EAX); | 930 __ shld(EDI, EAX); |
| 932 // Result in EDI (high) and EBX (low). | 931 // Result in EDI (high) and EBX (low). |
| 933 const Class& mint_class = Class::Handle( | 932 const Class& mint_class = Class::Handle( |
| 934 Isolate::Current()->object_store()->mint_class()); | 933 Isolate::Current()->object_store()->mint_class()); |
| 935 AssemblerMacros::TryAllocate(assembler, | 934 __ TryAllocate(mint_class, |
| 936 mint_class, | 935 &fall_through, |
| 937 &fall_through, | 936 Assembler::kNearJump, |
| 938 Assembler::kNearJump, | 937 EAX); // Result register. |
| 939 EAX); // Result register. | |
| 940 // EBX and EDI are not objects but integer values. | 938 // EBX and EDI are not objects but integer values. |
| 941 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); | 939 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); |
| 942 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); | 940 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); |
| 943 __ ret(); | 941 __ ret(); |
| 944 __ Bind(&fall_through); | 942 __ Bind(&fall_through); |
| 945 return false; | 943 return false; |
| 946 } | 944 } |
| 947 | 945 |
| 948 | 946 |
| 949 static void Push64SmiOrMint(Assembler* assembler, | 947 static void Push64SmiOrMint(Assembler* assembler, |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1235 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
| 1238 switch (kind) { | 1236 switch (kind) { |
| 1239 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1237 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| 1240 case Token::kSUB: __ subsd(XMM0, XMM1); break; | 1238 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
| 1241 case Token::kMUL: __ mulsd(XMM0, XMM1); break; | 1239 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
| 1242 case Token::kDIV: __ divsd(XMM0, XMM1); break; | 1240 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
| 1243 default: UNREACHABLE(); | 1241 default: UNREACHABLE(); |
| 1244 } | 1242 } |
| 1245 const Class& double_class = Class::Handle( | 1243 const Class& double_class = Class::Handle( |
| 1246 Isolate::Current()->object_store()->double_class()); | 1244 Isolate::Current()->object_store()->double_class()); |
| 1247 AssemblerMacros::TryAllocate(assembler, | 1245 __ TryAllocate(double_class, |
| 1248 double_class, | 1246 &fall_through, |
| 1249 &fall_through, | 1247 Assembler::kNearJump, |
| 1250 Assembler::kNearJump, | 1248 EAX); // Result register. |
| 1251 EAX); // Result register. | |
| 1252 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 1249 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 1253 __ ret(); | 1250 __ ret(); |
| 1254 __ Bind(&fall_through); | 1251 __ Bind(&fall_through); |
| 1255 return false; | 1252 return false; |
| 1256 } | 1253 } |
| 1257 | 1254 |
| 1258 | 1255 |
| 1259 bool Intrinsifier::Double_add(Assembler* assembler) { | 1256 bool Intrinsifier::Double_add(Assembler* assembler) { |
| 1260 return DoubleArithmeticOperations(assembler, Token::kADD); | 1257 return DoubleArithmeticOperations(assembler, Token::kADD); |
| 1261 } | 1258 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1284 __ testl(EAX, Immediate(kSmiTagMask)); | 1281 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1285 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); | 1282 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); |
| 1286 // Is Smi. | 1283 // Is Smi. |
| 1287 __ SmiUntag(EAX); | 1284 __ SmiUntag(EAX); |
| 1288 __ cvtsi2sd(XMM1, EAX); | 1285 __ cvtsi2sd(XMM1, EAX); |
| 1289 __ movl(EAX, Address(ESP, + 2 * kWordSize)); | 1286 __ movl(EAX, Address(ESP, + 2 * kWordSize)); |
| 1290 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1287 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
| 1291 __ mulsd(XMM0, XMM1); | 1288 __ mulsd(XMM0, XMM1); |
| 1292 const Class& double_class = Class::Handle( | 1289 const Class& double_class = Class::Handle( |
| 1293 Isolate::Current()->object_store()->double_class()); | 1290 Isolate::Current()->object_store()->double_class()); |
| 1294 AssemblerMacros::TryAllocate(assembler, | 1291 __ TryAllocate(double_class, |
| 1295 double_class, | 1292 &fall_through, |
| 1296 &fall_through, | 1293 Assembler::kNearJump, |
| 1297 Assembler::kNearJump, | 1294 EAX); // Result register. |
| 1298 EAX); // Result register. | |
| 1299 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 1295 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 1300 __ ret(); | 1296 __ ret(); |
| 1301 __ Bind(&fall_through); | 1297 __ Bind(&fall_through); |
| 1302 return false; | 1298 return false; |
| 1303 } | 1299 } |
| 1304 | 1300 |
| 1305 | 1301 |
| 1306 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1302 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { |
| 1307 Label fall_through; | 1303 Label fall_through; |
| 1308 __ movl(EAX, Address(ESP, +1 * kWordSize)); | 1304 __ movl(EAX, Address(ESP, +1 * kWordSize)); |
| 1309 __ testl(EAX, Immediate(kSmiTagMask)); | 1305 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1310 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); | 1306 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); |
| 1311 // Is Smi. | 1307 // Is Smi. |
| 1312 __ SmiUntag(EAX); | 1308 __ SmiUntag(EAX); |
| 1313 __ cvtsi2sd(XMM0, EAX); | 1309 __ cvtsi2sd(XMM0, EAX); |
| 1314 const Class& double_class = Class::Handle( | 1310 const Class& double_class = Class::Handle( |
| 1315 Isolate::Current()->object_store()->double_class()); | 1311 Isolate::Current()->object_store()->double_class()); |
| 1316 AssemblerMacros::TryAllocate(assembler, | 1312 __ TryAllocate(double_class, |
| 1317 double_class, | 1313 &fall_through, |
| 1318 &fall_through, | 1314 Assembler::kNearJump, |
| 1319 Assembler::kNearJump, | 1315 EAX); // Result register. |
| 1320 EAX); // Result register. | |
| 1321 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 1316 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 1322 __ ret(); | 1317 __ ret(); |
| 1323 __ Bind(&fall_through); | 1318 __ Bind(&fall_through); |
| 1324 return false; | 1319 return false; |
| 1325 } | 1320 } |
| 1326 | 1321 |
| 1327 | 1322 |
| 1328 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1323 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
| 1329 Label is_true; | 1324 Label is_true; |
| 1330 __ movl(EAX, Address(ESP, +1 * kWordSize)); | 1325 __ movl(EAX, Address(ESP, +1 * kWordSize)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 // Argument type is not known | 1379 // Argument type is not known |
| 1385 bool Intrinsifier::Math_sqrt(Assembler* assembler) { | 1380 bool Intrinsifier::Math_sqrt(Assembler* assembler) { |
| 1386 Label fall_through, is_smi, double_op; | 1381 Label fall_through, is_smi, double_op; |
| 1387 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1382 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1388 // Argument is double and is in EAX. | 1383 // Argument is double and is in EAX. |
| 1389 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 1384 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
| 1390 __ Bind(&double_op); | 1385 __ Bind(&double_op); |
| 1391 __ sqrtsd(XMM0, XMM1); | 1386 __ sqrtsd(XMM0, XMM1); |
| 1392 const Class& double_class = Class::Handle( | 1387 const Class& double_class = Class::Handle( |
| 1393 Isolate::Current()->object_store()->double_class()); | 1388 Isolate::Current()->object_store()->double_class()); |
| 1394 AssemblerMacros::TryAllocate(assembler, | 1389 __ TryAllocate(double_class, |
| 1395 double_class, | 1390 &fall_through, |
| 1396 &fall_through, | 1391 Assembler::kNearJump, |
| 1397 Assembler::kNearJump, | 1392 EAX); // Result register. |
| 1398 EAX); // Result register. | |
| 1399 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 1393 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 1400 __ ret(); | 1394 __ ret(); |
| 1401 __ Bind(&is_smi); | 1395 __ Bind(&is_smi); |
| 1402 __ SmiUntag(EAX); | 1396 __ SmiUntag(EAX); |
| 1403 __ cvtsi2sd(XMM1, EAX); | 1397 __ cvtsi2sd(XMM1, EAX); |
| 1404 __ jmp(&double_op); | 1398 __ jmp(&double_op); |
| 1405 __ Bind(&fall_through); | 1399 __ Bind(&fall_through); |
| 1406 return false; | 1400 return false; |
| 1407 } | 1401 } |
| 1408 | 1402 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1422 __ Bind(&double_op); | 1416 __ Bind(&double_op); |
| 1423 switch (kind) { | 1417 switch (kind) { |
| 1424 case kSine: __ fsin(); break; | 1418 case kSine: __ fsin(); break; |
| 1425 case kCosine: __ fcos(); break; | 1419 case kCosine: __ fcos(); break; |
| 1426 default: | 1420 default: |
| 1427 UNREACHABLE(); | 1421 UNREACHABLE(); |
| 1428 } | 1422 } |
| 1429 const Class& double_class = Class::Handle( | 1423 const Class& double_class = Class::Handle( |
| 1430 Isolate::Current()->object_store()->double_class()); | 1424 Isolate::Current()->object_store()->double_class()); |
| 1431 Label alloc_failed; | 1425 Label alloc_failed; |
| 1432 AssemblerMacros::TryAllocate(assembler, | 1426 __ TryAllocate(double_class, |
| 1433 double_class, | 1427 &alloc_failed, |
| 1434 &alloc_failed, | 1428 Assembler::kNearJump, |
| 1435 Assembler::kNearJump, | 1429 EAX); // Result register. |
| 1436 EAX); // Result register. | |
| 1437 __ fstpl(FieldAddress(EAX, Double::value_offset())); | 1430 __ fstpl(FieldAddress(EAX, Double::value_offset())); |
| 1438 __ ret(); | 1431 __ ret(); |
| 1439 | 1432 |
| 1440 __ Bind(&is_smi); // smi -> double. | 1433 __ Bind(&is_smi); // smi -> double. |
| 1441 __ SmiUntag(EAX); | 1434 __ SmiUntag(EAX); |
| 1442 __ pushl(EAX); | 1435 __ pushl(EAX); |
| 1443 __ filds(Address(ESP, 0)); | 1436 __ filds(Address(ESP, 0)); |
| 1444 __ popl(EAX); | 1437 __ popl(EAX); |
| 1445 __ jmp(&double_op); | 1438 __ jmp(&double_op); |
| 1446 | 1439 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 __ SmiTag(EAX); | 1597 __ SmiTag(EAX); |
| 1605 __ movl(FieldAddress(EBX, String::hash_offset()), EAX); | 1598 __ movl(FieldAddress(EBX, String::hash_offset()), EAX); |
| 1606 __ ret(); | 1599 __ ret(); |
| 1607 return true; | 1600 return true; |
| 1608 } | 1601 } |
| 1609 | 1602 |
| 1610 #undef __ | 1603 #undef __ |
| 1611 } // namespace dart | 1604 } // namespace dart |
| 1612 | 1605 |
| 1613 #endif // defined TARGET_ARCH_IA32 | 1606 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |