| 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 1387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1398 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1399 __ LoadObject(RAX, bool_false); | 1399 __ LoadObject(RAX, bool_false); |
| 1400 __ ret(); | 1400 __ ret(); |
| 1401 __ Bind(&is_true); | 1401 __ Bind(&is_true); |
| 1402 __ LoadObject(RAX, bool_true); | 1402 __ LoadObject(RAX, bool_true); |
| 1403 __ ret(); | 1403 __ ret(); |
| 1404 return true; | 1404 return true; |
| 1405 } | 1405 } |
| 1406 | 1406 |
| 1407 | 1407 |
| 1408 static intptr_t GetOffsetForField(const char* class_name_p, | |
| 1409 const char* field_name_p) { | |
| 1410 const String& class_name = String::Handle(Symbols::New(class_name_p)); | |
| 1411 const String& field_name = String::Handle(Symbols::New(field_name_p)); | |
| 1412 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | |
| 1413 const Class& cls = | |
| 1414 Class::Handle(core_lib.LookupClassAllowPrivate(class_name)); | |
| 1415 ASSERT(!cls.IsNull()); | |
| 1416 const Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | |
| 1417 ASSERT(!field.IsNull()); | |
| 1418 return field.Offset(); | |
| 1419 } | |
| 1420 | |
| 1421 | |
| 1422 static const char* kFixedSizeArrayIteratorClassName = "_FixedSizeArrayIterator"; | |
| 1423 | |
| 1424 // Class 'FixedSizeArrayIterator': | |
| 1425 // T next() { | |
| 1426 // return _array[_pos++]; | |
| 1427 // } | |
| 1428 // Intrinsify: return _array[_pos++]; | |
| 1429 // TODO(srdjan): Throw a 'StateError' exception if the iterator | |
| 1430 // has no more elements. | |
| 1431 bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) { | |
| 1432 Label fall_through; | |
| 1433 const intptr_t array_offset = | |
| 1434 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_array"); | |
| 1435 const intptr_t pos_offset = | |
| 1436 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); | |
| 1437 ASSERT((array_offset >= 0) && (pos_offset >= 0)); | |
| 1438 // Receiver is not NULL. | |
| 1439 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver. | |
| 1440 __ movq(RCX, FieldAddress(RAX, pos_offset)); // Field _pos. | |
| 1441 // '_pos' cannot be greater than array length and therefore is always Smi. | |
| 1442 #if defined(DEBUG) | |
| 1443 Label pos_ok; | |
| 1444 __ testq(RCX, Immediate(kSmiTagMask)); | |
| 1445 __ j(ZERO, &pos_ok, Assembler::kNearJump); | |
| 1446 __ Stop("pos must be Smi"); | |
| 1447 __ Bind(&pos_ok); | |
| 1448 #endif | |
| 1449 // Check that we are not trying to call 'next' when 'hasNext' is false. | |
| 1450 __ movq(RAX, FieldAddress(RAX, array_offset)); // Field _array. | |
| 1451 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); // Range check. | |
| 1452 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 1453 | |
| 1454 // RCX is Smi, i.e, times 2. | |
| 1455 ASSERT(kSmiTagShift == 1); | |
| 1456 __ movq(RDI, FieldAddress(RAX, RCX, TIMES_4, sizeof(RawArray))); // Result. | |
| 1457 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1))); | |
| 1458 __ addq(RCX, value); // _pos++. | |
| 1459 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); | |
| 1460 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver. | |
| 1461 __ StoreIntoObjectNoBarrier(RAX, | |
| 1462 FieldAddress(RAX, pos_offset), | |
| 1463 RCX); // Store _pos. | |
| 1464 __ movq(RAX, RDI); | |
| 1465 __ ret(); | |
| 1466 __ Bind(&fall_through); | |
| 1467 return false; | |
| 1468 } | |
| 1469 | |
| 1470 | |
| 1471 // Class 'FixedSizeArrayIterator': | |
| 1472 // bool get hasNext { | |
| 1473 // return _length > _pos; | |
| 1474 // } | |
| 1475 bool Intrinsifier::FixedSizeArrayIterator_getHasNext(Assembler* assembler) { | |
| 1476 Label fall_through, is_true; | |
| 1477 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1478 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 1479 const intptr_t length_offset = | |
| 1480 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length"); | |
| 1481 const intptr_t pos_offset = | |
| 1482 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos"); | |
| 1483 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver. | |
| 1484 __ movq(RCX, FieldAddress(RAX, length_offset)); // Field _length. | |
| 1485 __ movq(RAX, FieldAddress(RAX, pos_offset)); // Field _pos. | |
| 1486 __ movq(RDI, RAX); | |
| 1487 __ orq(RDI, RCX); | |
| 1488 __ testq(RDI, Immediate(kSmiTagMask)); | |
| 1489 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length/_pos. | |
| 1490 __ cmpq(RCX, RAX); // _length > _pos. | |
| 1491 __ j(GREATER, &is_true, Assembler::kNearJump); | |
| 1492 __ LoadObject(RAX, bool_false); | |
| 1493 __ ret(); | |
| 1494 __ Bind(&is_true); | |
| 1495 __ LoadObject(RAX, bool_true); | |
| 1496 __ ret(); | |
| 1497 __ Bind(&fall_through); | |
| 1498 return false; | |
| 1499 } | |
| 1500 | |
| 1501 | |
| 1502 bool Intrinsifier::String_getHashCode(Assembler* assembler) { | 1408 bool Intrinsifier::String_getHashCode(Assembler* assembler) { |
| 1503 Label fall_through; | 1409 Label fall_through; |
| 1504 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1410 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1505 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1411 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); |
| 1506 __ cmpq(RAX, Immediate(0)); | 1412 __ cmpq(RAX, Immediate(0)); |
| 1507 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1413 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 1508 __ ret(); | 1414 __ ret(); |
| 1509 __ Bind(&fall_through); | 1415 __ Bind(&fall_through); |
| 1510 // Hash not yet computed. | 1416 // Hash not yet computed. |
| 1511 return false; | 1417 return false; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 __ LoadObject(RAX, bool_true); | 1463 __ LoadObject(RAX, bool_true); |
| 1558 __ ret(); | 1464 __ ret(); |
| 1559 return true; | 1465 return true; |
| 1560 } | 1466 } |
| 1561 | 1467 |
| 1562 #undef __ | 1468 #undef __ |
| 1563 | 1469 |
| 1564 } // namespace dart | 1470 } // namespace dart |
| 1565 | 1471 |
| 1566 #endif // defined TARGET_ARCH_X64 | 1472 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |