Chromium Code Reviews| 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 1470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1481 __ incq(RAX); | 1481 __ incq(RAX); |
| 1482 __ Bind(&set_hash_code); | 1482 __ Bind(&set_hash_code); |
| 1483 __ SmiTag(RAX); | 1483 __ SmiTag(RAX); |
| 1484 __ movq(FieldAddress(RBX, String::hash_offset()), RAX); | 1484 __ movq(FieldAddress(RBX, String::hash_offset()), RAX); |
| 1485 __ ret(); | 1485 __ ret(); |
| 1486 return true; | 1486 return true; |
| 1487 } | 1487 } |
| 1488 | 1488 |
| 1489 | 1489 |
| 1490 // Allocates one-byte string of length 'end - start'. The content is not | 1490 // Allocates one-byte string of length 'end - start'. The content is not |
| 1491 // initialized. | 1491 // initialized. 'length-reg' contains tagged length. |
| 1492 // Returns new string as tagged pointer in EAX. | |
| 1492 static void TryAllocateOnebyteString(Assembler* assembler, | 1493 static void TryAllocateOnebyteString(Assembler* assembler, |
| 1494 Label* ok, | |
| 1493 Label* failure, | 1495 Label* failure, |
| 1494 intptr_t start_index_offset, | 1496 Register length_reg) { |
| 1495 intptr_t end_index_offset) { | 1497 if (length_reg != RDI) { |
| 1496 __ movq(RDI, Address(RSP, + end_index_offset)); | 1498 __ movl(RDI, length_reg); |
|
siva
2013/05/03 23:05:01
movq instead of movl.
srdjan
2013/05/03 23:36:37
Done.
| |
| 1497 __ subq(RDI, Address(RSP, + start_index_offset)); | 1499 } |
| 1500 Label pop_and_fail; | |
| 1501 __ pushq(RDI); // Preserve length. | |
| 1502 __ SmiUntag(RDI); | |
| 1498 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1503 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
| 1499 __ SmiUntag(RDI); | |
| 1500 __ leaq(RDI, Address(RDI, TIMES_1, fixed_size)); // RDI is a Smi. | 1504 __ leaq(RDI, Address(RDI, TIMES_1, fixed_size)); // RDI is a Smi. |
| 1501 __ andq(RDI, Immediate(-kObjectAlignment)); | 1505 __ andq(RDI, Immediate(-kObjectAlignment)); |
| 1502 | 1506 |
| 1503 Isolate* isolate = Isolate::Current(); | 1507 Isolate* isolate = Isolate::Current(); |
| 1504 Heap* heap = isolate->heap(); | 1508 Heap* heap = isolate->heap(); |
| 1505 | 1509 |
| 1506 __ movq(RAX, Immediate(heap->TopAddress())); | 1510 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1507 __ movq(RAX, Address(RAX, 0)); | 1511 __ movq(RAX, Address(RAX, 0)); |
| 1508 | 1512 |
| 1509 // RDI: allocation size. | 1513 // RDI: allocation size. |
| 1510 __ movq(RCX, RAX); | 1514 __ movq(RCX, RAX); |
| 1511 __ addq(RCX, RDI); | 1515 __ addq(RCX, RDI); |
| 1512 __ j(CARRY, failure); | 1516 __ j(CARRY, &pop_and_fail); |
| 1513 | 1517 |
| 1514 // Check if the allocation fits into the remaining space. | 1518 // Check if the allocation fits into the remaining space. |
| 1515 // RAX: potential new object start. | 1519 // RAX: potential new object start. |
| 1516 // RCX: potential next object start. | 1520 // RCX: potential next object start. |
| 1517 // RDI: allocation size. | 1521 // RDI: allocation size. |
| 1518 __ movq(R13, Immediate(heap->EndAddress())); | 1522 __ movq(R13, Immediate(heap->EndAddress())); |
| 1519 __ cmpq(RCX, Address(R13, 0)); | 1523 __ cmpq(RCX, Address(R13, 0)); |
| 1520 __ j(ABOVE_EQUAL, failure); | 1524 __ j(ABOVE_EQUAL, &pop_and_fail); |
| 1521 | 1525 |
| 1522 // Successfully allocated the object(s), now update top to point to | 1526 // Successfully allocated the object(s), now update top to point to |
| 1523 // next object start and initialize the object. | 1527 // next object start and initialize the object. |
| 1524 __ movq(R13, Immediate(heap->TopAddress())); | 1528 __ movq(R13, Immediate(heap->TopAddress())); |
| 1525 __ movq(Address(R13, 0), RCX); | 1529 __ movq(Address(R13, 0), RCX); |
| 1526 __ addq(RAX, Immediate(kHeapObjectTag)); | 1530 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 1527 | 1531 |
| 1528 // Initialize the tags. | 1532 // Initialize the tags. |
| 1529 // RAX: new object start as a tagged pointer. | 1533 // RAX: new object start as a tagged pointer. |
| 1530 // RDI: allocation size. | 1534 // RDI: allocation size. |
| 1531 { | 1535 { |
| 1532 Label size_tag_overflow, done; | 1536 Label size_tag_overflow, done; |
| 1533 __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 1537 __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1534 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 1538 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1535 __ shlq(RDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 1539 __ shlq(RDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| 1536 __ jmp(&done, Assembler::kNearJump); | 1540 __ jmp(&done, Assembler::kNearJump); |
| 1537 | 1541 |
| 1538 __ Bind(&size_tag_overflow); | 1542 __ Bind(&size_tag_overflow); |
| 1539 __ xorq(RDI, RDI); | 1543 __ xorq(RDI, RDI); |
| 1540 __ Bind(&done); | 1544 __ Bind(&done); |
| 1541 | 1545 |
| 1542 // Get the class index and insert it into the tags. | 1546 // Get the class index and insert it into the tags. |
| 1543 const Class& cls = | 1547 const Class& cls = |
| 1544 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1548 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 1545 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cls.id()))); | 1549 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cls.id()))); |
| 1546 __ movq(FieldAddress(RAX, String::tags_offset()), RDI); // Tags. | 1550 __ movq(FieldAddress(RAX, String::tags_offset()), RDI); // Tags. |
| 1547 } | 1551 } |
| 1548 | 1552 |
| 1549 // Set the length field. | 1553 // Set the length field. |
| 1550 __ movq(RDI, Address(RSP, + end_index_offset)); | 1554 __ popq(RDI); |
| 1551 __ subq(RDI, Address(RSP, + start_index_offset)); // Length. | |
| 1552 __ StoreIntoObjectNoBarrier(RAX, | 1555 __ StoreIntoObjectNoBarrier(RAX, |
| 1553 FieldAddress(RAX, String::length_offset()), | 1556 FieldAddress(RAX, String::length_offset()), |
| 1554 RDI); | 1557 RDI); |
| 1555 // Clear hash. | 1558 // Clear hash. |
| 1556 __ movq(FieldAddress(RAX, String::hash_offset()), Immediate(0)); | 1559 __ movq(FieldAddress(RAX, String::hash_offset()), Immediate(0)); |
| 1560 __ jmp(ok, Assembler::kNearJump); | |
| 1561 | |
| 1562 __ Bind(&pop_and_fail); | |
| 1563 __ popq(RDI); | |
| 1564 __ jmp(failure); | |
| 1557 } | 1565 } |
| 1558 | 1566 |
| 1559 | 1567 |
| 1560 // Arg0: Onebyte String | 1568 // Arg0: Onebyte String |
| 1561 // Arg1: Start index as Smi. | 1569 // Arg1: Start index as Smi. |
| 1562 // Arg2: End index as Smi. | 1570 // Arg2: End index as Smi. |
| 1563 // The indexes must be valid. | 1571 // The indexes must be valid. |
| 1564 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { | 1572 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { |
| 1565 const intptr_t kStringOffset = 3 * kWordSize; | 1573 const intptr_t kStringOffset = 3 * kWordSize; |
| 1566 const intptr_t kStartIndexOffset = 2 * kWordSize; | 1574 const intptr_t kStartIndexOffset = 2 * kWordSize; |
| 1567 const intptr_t kEndIndexOffset = 1 * kWordSize; | 1575 const intptr_t kEndIndexOffset = 1 * kWordSize; |
| 1568 Label fall_through; | 1576 Label fall_through, ok; |
| 1569 TryAllocateOnebyteString( | 1577 __ movq(RDI, Address(RSP, + kEndIndexOffset)); |
| 1570 assembler, &fall_through, kStartIndexOffset, kEndIndexOffset); | 1578 __ subq(RDI, Address(RSP, + kStartIndexOffset)); |
| 1579 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI); | |
| 1580 __ Bind(&ok); | |
| 1571 // RAX: new string as tagged pointer. | 1581 // RAX: new string as tagged pointer. |
| 1572 // Copy string. | 1582 // Copy string. |
| 1573 __ movq(RSI, Address(RSP, + kStringOffset)); | 1583 __ movq(RSI, Address(RSP, + kStringOffset)); |
| 1574 __ movq(RBX, Address(RSP, + kStartIndexOffset)); | 1584 __ movq(RBX, Address(RSP, + kStartIndexOffset)); |
| 1575 __ SmiUntag(RBX); | 1585 __ SmiUntag(RBX); |
| 1576 __ leaq(RSI, FieldAddress(RSI, RBX, TIMES_1, OneByteString::data_offset())); | 1586 __ leaq(RSI, FieldAddress(RSI, RBX, TIMES_1, OneByteString::data_offset())); |
| 1577 // RSI: Start address to copy from (untagged). | 1587 // RSI: Start address to copy from (untagged). |
| 1578 // RBX: Untagged start index. | 1588 // RBX: Untagged start index. |
| 1579 __ movq(RCX, Address(RSP, + kEndIndexOffset)); | 1589 __ movq(RCX, Address(RSP, + kEndIndexOffset)); |
| 1580 __ SmiUntag(RCX); | 1590 __ SmiUntag(RCX); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1593 __ incq(RDX); | 1603 __ incq(RDX); |
| 1594 __ Bind(&check); | 1604 __ Bind(&check); |
| 1595 __ cmpq(RDX, RCX); | 1605 __ cmpq(RDX, RCX); |
| 1596 __ j(LESS, &loop, Assembler::kNearJump); | 1606 __ j(LESS, &loop, Assembler::kNearJump); |
| 1597 __ ret(); | 1607 __ ret(); |
| 1598 __ Bind(&fall_through); | 1608 __ Bind(&fall_through); |
| 1599 return false; | 1609 return false; |
| 1600 } | 1610 } |
| 1601 | 1611 |
| 1602 | 1612 |
| 1613 bool Intrinsifier::OneByteString_setAt(Assembler* assembler) { | |
| 1614 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Value. | |
| 1615 __ movq(RBX, Address(RSP, + 2 * kWordSize)); // Index. | |
| 1616 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // OneByteString. | |
| 1617 __ SmiUntag(RBX); | |
| 1618 __ SmiUntag(RCX); | |
| 1619 __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX); | |
| 1620 __ ret(); | |
| 1621 return true; | |
| 1622 } | |
| 1623 | |
| 1624 | |
| 1625 bool Intrinsifier::OneByteString_allocate(Assembler* assembler) { | |
| 1626 __ movq(RDI, Address(RSP, + 1 * kWordSize)); // Length.v= | |
| 1627 Label fall_through, ok; | |
| 1628 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI); | |
| 1629 // EDI: Start address to copy from (untagged). | |
| 1630 | |
| 1631 __ Bind(&ok); | |
| 1632 __ ret(); | |
| 1633 | |
| 1634 __ Bind(&fall_through); | |
| 1635 return false; | |
| 1636 } | |
| 1637 | |
| 1638 | |
| 1603 #undef __ | 1639 #undef __ |
| 1604 | 1640 |
| 1605 } // namespace dart | 1641 } // namespace dart |
| 1606 | 1642 |
| 1607 #endif // defined TARGET_ARCH_X64 | 1643 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |