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 #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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 // This snippet of inlined code uses the following registers: | 65 // This snippet of inlined code uses the following registers: |
66 // RAX, RCX, R13 | 66 // RAX, RCX, R13 |
67 // and the newly allocated object is returned in RAX. | 67 // and the newly allocated object is returned in RAX. |
68 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; | 68 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; |
69 const intptr_t kArrayOffset = 1 * kWordSize; | 69 const intptr_t kArrayOffset = 1 * kWordSize; |
70 Label fall_through; | 70 Label fall_through; |
71 | 71 |
72 // Try allocating in new space. | 72 // Try allocating in new space. |
73 const Class& cls = Class::Handle( | 73 const Class& cls = Class::Handle( |
74 Isolate::Current()->object_store()->growable_object_array_class()); | 74 Isolate::Current()->object_store()->growable_object_array_class()); |
75 __ TryAllocate(cls, &fall_through, Assembler::kFarJump, RAX, kNoRegister); | 75 __ TryAllocate(cls, &fall_through, Assembler::kFarJump, RAX); |
76 | 76 |
77 // Store backing array object in growable array object. | 77 // Store backing array object in growable array object. |
78 __ movq(RCX, Address(RSP, kArrayOffset)); // data argument. | 78 __ movq(RCX, Address(RSP, kArrayOffset)); // data argument. |
79 // RAX is new, no barrier needed. | 79 // RAX is new, no barrier needed. |
80 __ InitializeFieldNoBarrier( | 80 __ InitializeFieldNoBarrier( |
81 RAX, | 81 RAX, |
82 FieldAddress(RAX, GrowableObjectArray::data_offset()), | 82 FieldAddress(RAX, GrowableObjectArray::data_offset()), |
83 RCX); | 83 RCX); |
84 | 84 |
85 // RAX: new growable array object start as a tagged pointer. | 85 // RAX: new growable array object start as a tagged pointer. |
(...skipping 28 matching lines...) Expand all Loading... |
114 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset())); | 114 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset())); |
115 __ j(EQUAL, &fall_through); // Must grow data. | 115 __ j(EQUAL, &fall_through); // Must grow data. |
116 // len = len + 1; | 116 // len = len + 1; |
117 __ IncrementSmiField(FieldAddress(RAX, GrowableObjectArray::length_offset()), | 117 __ IncrementSmiField(FieldAddress(RAX, GrowableObjectArray::length_offset()), |
118 1); | 118 1); |
119 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Value | 119 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Value |
120 ASSERT(kSmiTagShift == 1); | 120 ASSERT(kSmiTagShift == 1); |
121 __ StoreIntoObject(RDX, | 121 __ StoreIntoObject(RDX, |
122 FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()), | 122 FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()), |
123 RAX); | 123 RAX); |
124 __ LoadObject(RAX, Object::null_object(), PP); | 124 __ LoadObject(RAX, Object::null_object()); |
125 __ ret(); | 125 __ ret(); |
126 __ Bind(&fall_through); | 126 __ Bind(&fall_through); |
127 } | 127 } |
128 | 128 |
129 | 129 |
130 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ | 130 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ |
131 Label fall_through; \ | 131 Label fall_through; \ |
132 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ | 132 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ |
133 __ MaybeTraceAllocation(cid, &fall_through, false); \ | 133 __ MaybeTraceAllocation(cid, &fall_through, false); \ |
134 __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */ \ | 134 __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */ \ |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 __ Bind(&fall_through); | 576 __ Bind(&fall_through); |
577 } | 577 } |
578 | 578 |
579 | 579 |
580 static void CompareIntegers(Assembler* assembler, Condition true_condition) { | 580 static void CompareIntegers(Assembler* assembler, Condition true_condition) { |
581 Label fall_through, true_label; | 581 Label fall_through, true_label; |
582 TestBothArgumentsSmis(assembler, &fall_through); | 582 TestBothArgumentsSmis(assembler, &fall_through); |
583 // RAX contains the right argument. | 583 // RAX contains the right argument. |
584 __ cmpq(Address(RSP, + 2 * kWordSize), RAX); | 584 __ cmpq(Address(RSP, + 2 * kWordSize), RAX); |
585 __ j(true_condition, &true_label, Assembler::kNearJump); | 585 __ j(true_condition, &true_label, Assembler::kNearJump); |
586 __ LoadObject(RAX, Bool::False(), PP); | 586 __ LoadObject(RAX, Bool::False()); |
587 __ ret(); | 587 __ ret(); |
588 __ Bind(&true_label); | 588 __ Bind(&true_label); |
589 __ LoadObject(RAX, Bool::True(), PP); | 589 __ LoadObject(RAX, Bool::True()); |
590 __ ret(); | 590 __ ret(); |
591 __ Bind(&fall_through); | 591 __ Bind(&fall_through); |
592 } | 592 } |
593 | 593 |
594 | 594 |
595 void Intrinsifier::Integer_lessThan(Assembler* assembler) { | 595 void Intrinsifier::Integer_lessThan(Assembler* assembler) { |
596 CompareIntegers(assembler, LESS); | 596 CompareIntegers(assembler, LESS); |
597 } | 597 } |
598 | 598 |
599 | 599 |
(...skipping 26 matching lines...) Expand all Loading... |
626 | 626 |
627 // For integer receiver '===' check first. | 627 // For integer receiver '===' check first. |
628 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); | 628 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); |
629 __ movq(RCX, Address(RSP, + kReceiverOffset * kWordSize)); | 629 __ movq(RCX, Address(RSP, + kReceiverOffset * kWordSize)); |
630 __ cmpq(RAX, RCX); | 630 __ cmpq(RAX, RCX); |
631 __ j(EQUAL, &true_label, Assembler::kNearJump); | 631 __ j(EQUAL, &true_label, Assembler::kNearJump); |
632 __ orq(RAX, RCX); | 632 __ orq(RAX, RCX); |
633 __ testq(RAX, Immediate(kSmiTagMask)); | 633 __ testq(RAX, Immediate(kSmiTagMask)); |
634 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); | 634 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); |
635 // Both arguments are smi, '===' is good enough. | 635 // Both arguments are smi, '===' is good enough. |
636 __ LoadObject(RAX, Bool::False(), PP); | 636 __ LoadObject(RAX, Bool::False()); |
637 __ ret(); | 637 __ ret(); |
638 __ Bind(&true_label); | 638 __ Bind(&true_label); |
639 __ LoadObject(RAX, Bool::True(), PP); | 639 __ LoadObject(RAX, Bool::True()); |
640 __ ret(); | 640 __ ret(); |
641 | 641 |
642 // At least one of the arguments was not Smi. | 642 // At least one of the arguments was not Smi. |
643 Label receiver_not_smi; | 643 Label receiver_not_smi; |
644 __ Bind(&check_for_mint); | 644 __ Bind(&check_for_mint); |
645 __ movq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); | 645 __ movq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); |
646 __ testq(RAX, Immediate(kSmiTagMask)); | 646 __ testq(RAX, Immediate(kSmiTagMask)); |
647 __ j(NOT_ZERO, &receiver_not_smi); | 647 __ j(NOT_ZERO, &receiver_not_smi); |
648 | 648 |
649 // Left (receiver) is Smi, return false if right is not Double. | 649 // Left (receiver) is Smi, return false if right is not Double. |
650 // Note that an instance of Mint or Bigint never contains a value that can be | 650 // Note that an instance of Mint or Bigint never contains a value that can be |
651 // represented by Smi. | 651 // represented by Smi. |
652 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); | 652 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); |
653 __ CompareClassId(RAX, kDoubleCid); | 653 __ CompareClassId(RAX, kDoubleCid); |
654 __ j(EQUAL, &fall_through); | 654 __ j(EQUAL, &fall_through); |
655 __ LoadObject(RAX, Bool::False(), PP); | 655 __ LoadObject(RAX, Bool::False()); |
656 __ ret(); | 656 __ ret(); |
657 | 657 |
658 __ Bind(&receiver_not_smi); | 658 __ Bind(&receiver_not_smi); |
659 // RAX:: receiver. | 659 // RAX:: receiver. |
660 __ CompareClassId(RAX, kMintCid); | 660 __ CompareClassId(RAX, kMintCid); |
661 __ j(NOT_EQUAL, &fall_through); | 661 __ j(NOT_EQUAL, &fall_through); |
662 // Receiver is Mint, return false if right is Smi. | 662 // Receiver is Mint, return false if right is Smi. |
663 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); | 663 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); |
664 __ testq(RAX, Immediate(kSmiTagMask)); | 664 __ testq(RAX, Immediate(kSmiTagMask)); |
665 __ j(NOT_ZERO, &fall_through); | 665 __ j(NOT_ZERO, &fall_through); |
666 // Smi == Mint -> false. | 666 // Smi == Mint -> false. |
667 __ LoadObject(RAX, Bool::False(), PP); | 667 __ LoadObject(RAX, Bool::False()); |
668 __ ret(); | 668 __ ret(); |
669 // TODO(srdjan): Implement Mint == Mint comparison. | 669 // TODO(srdjan): Implement Mint == Mint comparison. |
670 | 670 |
671 __ Bind(&fall_through); | 671 __ Bind(&fall_through); |
672 } | 672 } |
673 | 673 |
674 | 674 |
675 void Intrinsifier::Integer_equal(Assembler* assembler) { | 675 void Intrinsifier::Integer_equal(Assembler* assembler) { |
676 Integer_equalToInteger(assembler); | 676 Integer_equalToInteger(assembler); |
677 } | 677 } |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1255 // Both arguments are double, right operand is in RAX. | 1255 // Both arguments are double, right operand is in RAX. |
1256 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 1256 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
1257 __ Bind(&double_op); | 1257 __ Bind(&double_op); |
1258 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. | 1258 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. |
1259 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1259 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
1260 __ comisd(XMM0, XMM1); | 1260 __ comisd(XMM0, XMM1); |
1261 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; | 1261 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
1262 __ j(true_condition, &is_true, Assembler::kNearJump); | 1262 __ j(true_condition, &is_true, Assembler::kNearJump); |
1263 // Fall through false. | 1263 // Fall through false. |
1264 __ Bind(&is_false); | 1264 __ Bind(&is_false); |
1265 __ LoadObject(RAX, Bool::False(), PP); | 1265 __ LoadObject(RAX, Bool::False()); |
1266 __ ret(); | 1266 __ ret(); |
1267 __ Bind(&is_true); | 1267 __ Bind(&is_true); |
1268 __ LoadObject(RAX, Bool::True(), PP); | 1268 __ LoadObject(RAX, Bool::True()); |
1269 __ ret(); | 1269 __ ret(); |
1270 __ Bind(&is_smi); | 1270 __ Bind(&is_smi); |
1271 __ SmiUntag(RAX); | 1271 __ SmiUntag(RAX); |
1272 __ cvtsi2sdq(XMM1, RAX); | 1272 __ cvtsi2sdq(XMM1, RAX); |
1273 __ jmp(&double_op); | 1273 __ jmp(&double_op); |
1274 __ Bind(&fall_through); | 1274 __ Bind(&fall_through); |
1275 } | 1275 } |
1276 | 1276 |
1277 | 1277 |
1278 void Intrinsifier::Double_greaterThan(Assembler* assembler) { | 1278 void Intrinsifier::Double_greaterThan(Assembler* assembler) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 case Token::kSUB: __ subsd(XMM0, XMM1); break; | 1314 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
1315 case Token::kMUL: __ mulsd(XMM0, XMM1); break; | 1315 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
1316 case Token::kDIV: __ divsd(XMM0, XMM1); break; | 1316 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
1317 default: UNREACHABLE(); | 1317 default: UNREACHABLE(); |
1318 } | 1318 } |
1319 const Class& double_class = Class::Handle( | 1319 const Class& double_class = Class::Handle( |
1320 Isolate::Current()->object_store()->double_class()); | 1320 Isolate::Current()->object_store()->double_class()); |
1321 __ TryAllocate(double_class, | 1321 __ TryAllocate(double_class, |
1322 &fall_through, | 1322 &fall_through, |
1323 Assembler::kFarJump, | 1323 Assembler::kFarJump, |
1324 RAX, // Result register. | 1324 RAX); // Result register. |
1325 kNoRegister); // Pool pointer might not be loaded. | |
1326 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1325 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
1327 __ ret(); | 1326 __ ret(); |
1328 __ Bind(&fall_through); | 1327 __ Bind(&fall_through); |
1329 } | 1328 } |
1330 | 1329 |
1331 | 1330 |
1332 void Intrinsifier::Double_add(Assembler* assembler) { | 1331 void Intrinsifier::Double_add(Assembler* assembler) { |
1333 DoubleArithmeticOperations(assembler, Token::kADD); | 1332 DoubleArithmeticOperations(assembler, Token::kADD); |
1334 } | 1333 } |
1335 | 1334 |
(...skipping 23 matching lines...) Expand all Loading... |
1359 __ SmiUntag(RAX); | 1358 __ SmiUntag(RAX); |
1360 __ cvtsi2sdq(XMM1, RAX); | 1359 __ cvtsi2sdq(XMM1, RAX); |
1361 __ movq(RAX, Address(RSP, + 2 * kWordSize)); | 1360 __ movq(RAX, Address(RSP, + 2 * kWordSize)); |
1362 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1361 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
1363 __ mulsd(XMM0, XMM1); | 1362 __ mulsd(XMM0, XMM1); |
1364 const Class& double_class = Class::Handle( | 1363 const Class& double_class = Class::Handle( |
1365 Isolate::Current()->object_store()->double_class()); | 1364 Isolate::Current()->object_store()->double_class()); |
1366 __ TryAllocate(double_class, | 1365 __ TryAllocate(double_class, |
1367 &fall_through, | 1366 &fall_through, |
1368 Assembler::kFarJump, | 1367 Assembler::kFarJump, |
1369 RAX, // Result register. | 1368 RAX); // Result register. |
1370 kNoRegister); // Pool pointer might not be loaded. | |
1371 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1369 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
1372 __ ret(); | 1370 __ ret(); |
1373 __ Bind(&fall_through); | 1371 __ Bind(&fall_through); |
1374 } | 1372 } |
1375 | 1373 |
1376 | 1374 |
1377 // Left is double right is integer (Bigint, Mint or Smi) | 1375 // Left is double right is integer (Bigint, Mint or Smi) |
1378 void Intrinsifier::DoubleFromInteger(Assembler* assembler) { | 1376 void Intrinsifier::DoubleFromInteger(Assembler* assembler) { |
1379 Label fall_through; | 1377 Label fall_through; |
1380 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1378 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
1381 __ testq(RAX, Immediate(kSmiTagMask)); | 1379 __ testq(RAX, Immediate(kSmiTagMask)); |
1382 __ j(NOT_ZERO, &fall_through); | 1380 __ j(NOT_ZERO, &fall_through); |
1383 // Is Smi. | 1381 // Is Smi. |
1384 __ SmiUntag(RAX); | 1382 __ SmiUntag(RAX); |
1385 __ cvtsi2sdq(XMM0, RAX); | 1383 __ cvtsi2sdq(XMM0, RAX); |
1386 const Class& double_class = Class::Handle( | 1384 const Class& double_class = Class::Handle( |
1387 Isolate::Current()->object_store()->double_class()); | 1385 Isolate::Current()->object_store()->double_class()); |
1388 __ TryAllocate(double_class, | 1386 __ TryAllocate(double_class, |
1389 &fall_through, | 1387 &fall_through, |
1390 Assembler::kFarJump, | 1388 Assembler::kFarJump, |
1391 RAX, // Result register. | 1389 RAX); // Result register. |
1392 kNoRegister); // Pool pointer might not be loaded. | |
1393 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1390 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
1394 __ ret(); | 1391 __ ret(); |
1395 __ Bind(&fall_through); | 1392 __ Bind(&fall_through); |
1396 } | 1393 } |
1397 | 1394 |
1398 | 1395 |
1399 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1396 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
1400 Label is_true; | 1397 Label is_true; |
1401 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1398 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
1402 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1399 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
1403 __ comisd(XMM0, XMM0); | 1400 __ comisd(XMM0, XMM0); |
1404 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; | 1401 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; |
1405 __ LoadObject(RAX, Bool::False(), PP); | 1402 __ LoadObject(RAX, Bool::False()); |
1406 __ ret(); | 1403 __ ret(); |
1407 __ Bind(&is_true); | 1404 __ Bind(&is_true); |
1408 __ LoadObject(RAX, Bool::True(), PP); | 1405 __ LoadObject(RAX, Bool::True()); |
1409 __ ret(); | 1406 __ ret(); |
1410 } | 1407 } |
1411 | 1408 |
1412 | 1409 |
1413 void Intrinsifier::Double_getIsNegative(Assembler* assembler) { | 1410 void Intrinsifier::Double_getIsNegative(Assembler* assembler) { |
1414 Label is_false, is_true, is_zero; | 1411 Label is_false, is_true, is_zero; |
1415 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1412 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
1416 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1413 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
1417 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. | 1414 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. |
1418 __ comisd(XMM0, XMM1); | 1415 __ comisd(XMM0, XMM1); |
1419 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. | 1416 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. |
1420 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. | 1417 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. |
1421 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. | 1418 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. |
1422 __ Bind(&is_true); | 1419 __ Bind(&is_true); |
1423 __ LoadObject(RAX, Bool::True(), PP); | 1420 __ LoadObject(RAX, Bool::True()); |
1424 __ ret(); | 1421 __ ret(); |
1425 __ Bind(&is_false); | 1422 __ Bind(&is_false); |
1426 __ LoadObject(RAX, Bool::False(), PP); | 1423 __ LoadObject(RAX, Bool::False()); |
1427 __ ret(); | 1424 __ ret(); |
1428 __ Bind(&is_zero); | 1425 __ Bind(&is_zero); |
1429 // Check for negative zero (get the sign bit). | 1426 // Check for negative zero (get the sign bit). |
1430 __ movmskpd(RAX, XMM0); | 1427 __ movmskpd(RAX, XMM0); |
1431 __ testq(RAX, Immediate(1)); | 1428 __ testq(RAX, Immediate(1)); |
1432 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1429 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
1433 __ jmp(&is_false, Assembler::kNearJump); | 1430 __ jmp(&is_false, Assembler::kNearJump); |
1434 } | 1431 } |
1435 | 1432 |
1436 | 1433 |
(...skipping 18 matching lines...) Expand all Loading... |
1455 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1452 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1456 // Argument is double and is in RAX. | 1453 // Argument is double and is in RAX. |
1457 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 1454 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
1458 __ Bind(&double_op); | 1455 __ Bind(&double_op); |
1459 __ sqrtsd(XMM0, XMM1); | 1456 __ sqrtsd(XMM0, XMM1); |
1460 const Class& double_class = Class::Handle( | 1457 const Class& double_class = Class::Handle( |
1461 Isolate::Current()->object_store()->double_class()); | 1458 Isolate::Current()->object_store()->double_class()); |
1462 __ TryAllocate(double_class, | 1459 __ TryAllocate(double_class, |
1463 &fall_through, | 1460 &fall_through, |
1464 Assembler::kFarJump, | 1461 Assembler::kFarJump, |
1465 RAX, // Result register. | 1462 RAX); // Result register. |
1466 kNoRegister); // Pool pointer might not be loaded. | |
1467 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 1463 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
1468 __ ret(); | 1464 __ ret(); |
1469 __ Bind(&is_smi); | 1465 __ Bind(&is_smi); |
1470 __ SmiUntag(RAX); | 1466 __ SmiUntag(RAX); |
1471 __ cvtsi2sdq(XMM1, RAX); | 1467 __ cvtsi2sdq(XMM1, RAX); |
1472 __ jmp(&double_op); | 1468 __ jmp(&double_op); |
1473 __ Bind(&fall_through); | 1469 __ Bind(&fall_through); |
1474 } | 1470 } |
1475 | 1471 |
1476 | 1472 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 | 1508 |
1513 // Identity comparison. | 1509 // Identity comparison. |
1514 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1510 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
1515 Label is_true; | 1511 Label is_true; |
1516 const intptr_t kReceiverOffset = 2; | 1512 const intptr_t kReceiverOffset = 2; |
1517 const intptr_t kArgumentOffset = 1; | 1513 const intptr_t kArgumentOffset = 1; |
1518 | 1514 |
1519 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); | 1515 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); |
1520 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); | 1516 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); |
1521 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1517 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1522 __ LoadObject(RAX, Bool::False(), PP); | 1518 __ LoadObject(RAX, Bool::False()); |
1523 __ ret(); | 1519 __ ret(); |
1524 __ Bind(&is_true); | 1520 __ Bind(&is_true); |
1525 __ LoadObject(RAX, Bool::True(), PP); | 1521 __ LoadObject(RAX, Bool::True()); |
1526 __ ret(); | 1522 __ ret(); |
1527 } | 1523 } |
1528 | 1524 |
1529 | 1525 |
1530 // Return type quickly for simple types (not parameterized and not signature). | 1526 // Return type quickly for simple types (not parameterized and not signature). |
1531 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { | 1527 void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
1532 Label fall_through; | 1528 Label fall_through; |
1533 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 1529 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
1534 __ LoadClassIdMayBeSmi(RCX, RAX); | 1530 __ LoadClassIdMayBeSmi(RCX, RAX); |
1535 | 1531 |
1536 // RCX: untagged cid of instance (RAX). | 1532 // RCX: untagged cid of instance (RAX). |
1537 __ LoadClassById(RDI, RCX, PP); | 1533 __ LoadClassById(RDI, RCX); |
1538 // RDI: class of instance (RAX). | 1534 // RDI: class of instance (RAX). |
1539 __ movq(RCX, FieldAddress(RDI, Class::signature_function_offset())); | 1535 __ movq(RCX, FieldAddress(RDI, Class::signature_function_offset())); |
1540 __ CompareObject(RCX, Object::null_object(), PP); | 1536 __ CompareObject(RCX, Object::null_object()); |
1541 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1537 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
1542 | 1538 |
1543 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); | 1539 __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset())); |
1544 __ cmpq(RCX, Immediate(0)); | 1540 __ cmpq(RCX, Immediate(0)); |
1545 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1541 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
1546 __ movq(RAX, FieldAddress(RDI, Class::canonical_types_offset())); | 1542 __ movq(RAX, FieldAddress(RDI, Class::canonical_types_offset())); |
1547 __ CompareObject(RAX, Object::null_object(), PP); | 1543 __ CompareObject(RAX, Object::null_object()); |
1548 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. | 1544 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Not yet set. |
1549 __ ret(); | 1545 __ ret(); |
1550 | 1546 |
1551 __ Bind(&fall_through); | 1547 __ Bind(&fall_through); |
1552 } | 1548 } |
1553 | 1549 |
1554 | 1550 |
1555 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1551 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1556 Label fall_through; | 1552 Label fall_through; |
1557 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1553 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 1601 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
1606 __ CompareClassId(RAX, kOneByteStringCid); | 1602 __ CompareClassId(RAX, kOneByteStringCid); |
1607 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); | 1603 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); |
1608 __ SmiUntag(RCX); | 1604 __ SmiUntag(RCX); |
1609 __ movzxb(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); | 1605 __ movzxb(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); |
1610 __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols)); | 1606 __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols)); |
1611 __ j(GREATER_EQUAL, &fall_through); | 1607 __ j(GREATER_EQUAL, &fall_through); |
1612 const ExternalLabel symbols_label( | 1608 const ExternalLabel symbols_label( |
1613 reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 1609 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
1614 __ pushq(PP); | 1610 __ pushq(PP); |
1615 __ LoadPoolPointer(PP); | 1611 __ LoadPoolPointer(); |
1616 assembler->set_constant_pool_allowed(true); | 1612 assembler->set_constant_pool_allowed(true); |
1617 __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable, PP); | 1613 __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable); |
1618 assembler->set_constant_pool_allowed(false); | 1614 assembler->set_constant_pool_allowed(false); |
1619 __ popq(PP); | 1615 __ popq(PP); |
1620 __ movq(RAX, Address(RAX, | 1616 __ movq(RAX, Address(RAX, |
1621 RCX, | 1617 RCX, |
1622 TIMES_8, | 1618 TIMES_8, |
1623 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 1619 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
1624 __ ret(); | 1620 __ ret(); |
1625 | 1621 |
1626 __ Bind(&try_two_byte_string); | 1622 __ Bind(&try_two_byte_string); |
1627 __ CompareClassId(RAX, kTwoByteStringCid); | 1623 __ CompareClassId(RAX, kTwoByteStringCid); |
1628 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1624 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
1629 ASSERT(kSmiTagShift == 1); | 1625 ASSERT(kSmiTagShift == 1); |
1630 __ movzxw(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); | 1626 __ movzxw(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); |
1631 __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols)); | 1627 __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols)); |
1632 __ j(GREATER_EQUAL, &fall_through); | 1628 __ j(GREATER_EQUAL, &fall_through); |
1633 __ pushq(PP); | 1629 __ pushq(PP); |
1634 __ LoadPoolPointer(PP); | 1630 __ LoadPoolPointer(); |
1635 assembler->set_constant_pool_allowed(true); | 1631 assembler->set_constant_pool_allowed(true); |
1636 __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable, PP); | 1632 __ LoadExternalLabel(RAX, &symbols_label, kNotPatchable); |
1637 assembler->set_constant_pool_allowed(false); | 1633 assembler->set_constant_pool_allowed(false); |
1638 __ popq(PP); | 1634 __ popq(PP); |
1639 __ movq(RAX, Address(RAX, | 1635 __ movq(RAX, Address(RAX, |
1640 RCX, | 1636 RCX, |
1641 TIMES_8, | 1637 TIMES_8, |
1642 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 1638 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
1643 __ ret(); | 1639 __ ret(); |
1644 | 1640 |
1645 __ Bind(&fall_through); | 1641 __ Bind(&fall_through); |
1646 } | 1642 } |
1647 | 1643 |
1648 | 1644 |
1649 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { | 1645 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { |
1650 Label is_true; | 1646 Label is_true; |
1651 // Get length. | 1647 // Get length. |
1652 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1648 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
1653 __ movq(RAX, FieldAddress(RAX, String::length_offset())); | 1649 __ movq(RAX, FieldAddress(RAX, String::length_offset())); |
1654 __ cmpq(RAX, Immediate(Smi::RawValue(0))); | 1650 __ cmpq(RAX, Immediate(Smi::RawValue(0))); |
1655 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1651 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1656 __ LoadObject(RAX, Bool::False(), PP); | 1652 __ LoadObject(RAX, Bool::False()); |
1657 __ ret(); | 1653 __ ret(); |
1658 __ Bind(&is_true); | 1654 __ Bind(&is_true); |
1659 __ LoadObject(RAX, Bool::True(), PP); | 1655 __ LoadObject(RAX, Bool::True()); |
1660 __ ret(); | 1656 __ ret(); |
1661 } | 1657 } |
1662 | 1658 |
1663 | 1659 |
1664 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { | 1660 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { |
1665 Label compute_hash; | 1661 Label compute_hash; |
1666 __ movq(RBX, Address(RSP, + 1 * kWordSize)); // OneByteString object. | 1662 __ movq(RBX, Address(RSP, + 1 * kWordSize)); // OneByteString object. |
1667 __ movq(RAX, FieldAddress(RBX, String::hash_offset())); | 1663 __ movq(RAX, FieldAddress(RBX, String::hash_offset())); |
1668 __ cmpq(RAX, Immediate(0)); | 1664 __ cmpq(RAX, Immediate(0)); |
1669 __ j(EQUAL, &compute_hash, Assembler::kNearJump); | 1665 __ j(EQUAL, &compute_hash, Assembler::kNearJump); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1921 __ movzxw(RDX, | 1917 __ movzxw(RDX, |
1922 FieldAddress(RCX, RDI, TIMES_2, TwoByteString::data_offset())); | 1918 FieldAddress(RCX, RDI, TIMES_2, TwoByteString::data_offset())); |
1923 } else { | 1919 } else { |
1924 UNIMPLEMENTED(); | 1920 UNIMPLEMENTED(); |
1925 } | 1921 } |
1926 __ cmpq(RBX, RDX); | 1922 __ cmpq(RBX, RDX); |
1927 __ j(NOT_EQUAL, &is_false, Assembler::kNearJump); | 1923 __ j(NOT_EQUAL, &is_false, Assembler::kNearJump); |
1928 __ jmp(&loop, Assembler::kNearJump); | 1924 __ jmp(&loop, Assembler::kNearJump); |
1929 | 1925 |
1930 __ Bind(&is_true); | 1926 __ Bind(&is_true); |
1931 __ LoadObject(RAX, Bool::True(), PP); | 1927 __ LoadObject(RAX, Bool::True()); |
1932 __ ret(); | 1928 __ ret(); |
1933 | 1929 |
1934 __ Bind(&is_false); | 1930 __ Bind(&is_false); |
1935 __ LoadObject(RAX, Bool::False(), PP); | 1931 __ LoadObject(RAX, Bool::False()); |
1936 __ ret(); | 1932 __ ret(); |
1937 | 1933 |
1938 __ Bind(&fall_through); | 1934 __ Bind(&fall_through); |
1939 } | 1935 } |
1940 | 1936 |
1941 | 1937 |
1942 void Intrinsifier::OneByteString_equality(Assembler* assembler) { | 1938 void Intrinsifier::OneByteString_equality(Assembler* assembler) { |
1943 StringEquality(assembler, kOneByteStringCid); | 1939 StringEquality(assembler, kOneByteStringCid); |
1944 } | 1940 } |
1945 | 1941 |
(...skipping 13 matching lines...) Expand all Loading... |
1959 // Incoming registers: | 1955 // Incoming registers: |
1960 // RAX: Function. (Will be loaded with the specialized matcher function.) | 1956 // RAX: Function. (Will be loaded with the specialized matcher function.) |
1961 // RCX: Unknown. (Must be GC safe on tail call.) | 1957 // RCX: Unknown. (Must be GC safe on tail call.) |
1962 // R10: Arguments descriptor. (Will be preserved.) | 1958 // R10: Arguments descriptor. (Will be preserved.) |
1963 | 1959 |
1964 // Load the specialized function pointer into RAX. Leverage the fact the | 1960 // Load the specialized function pointer into RAX. Leverage the fact the |
1965 // string CIDs as well as stored function pointers are in sequence. | 1961 // string CIDs as well as stored function pointers are in sequence. |
1966 __ movq(RBX, Address(RSP, kRegExpParamOffset)); | 1962 __ movq(RBX, Address(RSP, kRegExpParamOffset)); |
1967 __ movq(RDI, Address(RSP, kStringParamOffset)); | 1963 __ movq(RDI, Address(RSP, kStringParamOffset)); |
1968 __ LoadClassId(RDI, RDI); | 1964 __ LoadClassId(RDI, RDI); |
1969 __ SubImmediate(RDI, Immediate(kOneByteStringCid), PP); | 1965 __ SubImmediate(RDI, Immediate(kOneByteStringCid)); |
1970 __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8, | 1966 __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8, |
1971 JSRegExp::function_offset(kOneByteStringCid))); | 1967 JSRegExp::function_offset(kOneByteStringCid))); |
1972 | 1968 |
1973 // Registers are now set up for the lazy compile stub. It expects the function | 1969 // Registers are now set up for the lazy compile stub. It expects the function |
1974 // in RAX, the argument descriptor in R10, and IC-Data in RCX. | 1970 // in RAX, the argument descriptor in R10, and IC-Data in RCX. |
1975 static const intptr_t arg_count = RegExpMacroAssembler::kParamCount; | 1971 static const intptr_t arg_count = RegExpMacroAssembler::kParamCount; |
1976 __ LoadObject(R10, | 1972 __ LoadObject(R10, |
1977 Array::ZoneHandle(ArgumentsDescriptor::New(arg_count)), PP); | 1973 Array::ZoneHandle(ArgumentsDescriptor::New(arg_count))); |
1978 __ xorq(RCX, RCX); | 1974 __ xorq(RCX, RCX); |
1979 | 1975 |
1980 // Tail-call the function. | 1976 // Tail-call the function. |
1981 __ movq(RDI, FieldAddress(RAX, Function::instructions_offset())); | 1977 __ movq(RDI, FieldAddress(RAX, Function::instructions_offset())); |
1982 __ addq(RDI, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1978 __ addq(RDI, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1983 __ jmp(RDI); | 1979 __ jmp(RDI); |
1984 } | 1980 } |
1985 | 1981 |
1986 | 1982 |
1987 // On stack: user tag (+1), return-address (+0). | 1983 // On stack: user tag (+1), return-address (+0). |
(...skipping 25 matching lines...) Expand all Loading... |
2013 __ LoadIsolate(RAX); | 2009 __ LoadIsolate(RAX); |
2014 __ movq(RAX, Address(RAX, Isolate::current_tag_offset())); | 2010 __ movq(RAX, Address(RAX, Isolate::current_tag_offset())); |
2015 __ ret(); | 2011 __ ret(); |
2016 } | 2012 } |
2017 | 2013 |
2018 #undef __ | 2014 #undef __ |
2019 | 2015 |
2020 } // namespace dart | 2016 } // namespace dart |
2021 | 2017 |
2022 #endif // defined TARGET_ARCH_X64 | 2018 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |