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 |