| 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 |
| (...skipping 1554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 __ incl(EAX); | 1565 __ incl(EAX); |
| 1566 __ Bind(&set_hash_code); | 1566 __ Bind(&set_hash_code); |
| 1567 __ SmiTag(EAX); | 1567 __ SmiTag(EAX); |
| 1568 __ movl(FieldAddress(EBX, String::hash_offset()), EAX); | 1568 __ movl(FieldAddress(EBX, String::hash_offset()), EAX); |
| 1569 __ ret(); | 1569 __ ret(); |
| 1570 return true; | 1570 return true; |
| 1571 } | 1571 } |
| 1572 | 1572 |
| 1573 | 1573 |
| 1574 // Allocates one-byte string of length 'end - start'. The content is not | 1574 // Allocates one-byte string of length 'end - start'. The content is not |
| 1575 // initialized. | 1575 // initialized. 'length-reg' contains tagged length. |
| 1576 // Returns new string as tagged pointer in EAX. |
| 1576 static void TryAllocateOnebyteString(Assembler* assembler, | 1577 static void TryAllocateOnebyteString(Assembler* assembler, |
| 1578 Label* ok, |
| 1577 Label* failure, | 1579 Label* failure, |
| 1578 intptr_t start_index_offset, | 1580 Register length_reg) { |
| 1579 intptr_t end_index_offset) { | 1581 if (length_reg != EDI) { |
| 1580 __ movl(EDI, Address(ESP, + end_index_offset)); | 1582 __ movl(EDI, length_reg); |
| 1581 __ subl(EDI, Address(ESP, + start_index_offset)); | 1583 } |
| 1584 Label pop_and_fail; |
| 1585 __ pushl(EDI); // Preserve length. |
| 1586 __ SmiUntag(EDI); |
| 1582 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1587 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
| 1583 __ SmiUntag(EDI); | |
| 1584 __ leal(EDI, Address(EDI, TIMES_1, fixed_size)); // EDI is a Smi. | 1588 __ leal(EDI, Address(EDI, TIMES_1, fixed_size)); // EDI is a Smi. |
| 1585 __ andl(EDI, Immediate(-kObjectAlignment)); | 1589 __ andl(EDI, Immediate(-kObjectAlignment)); |
| 1586 | 1590 |
| 1587 Isolate* isolate = Isolate::Current(); | 1591 Isolate* isolate = Isolate::Current(); |
| 1588 Heap* heap = isolate->heap(); | 1592 Heap* heap = isolate->heap(); |
| 1589 | 1593 |
| 1590 __ movl(EAX, Address::Absolute(heap->TopAddress())); | 1594 __ movl(EAX, Address::Absolute(heap->TopAddress())); |
| 1591 __ movl(EBX, EAX); | 1595 __ movl(EBX, EAX); |
| 1592 | 1596 |
| 1593 // EDI: allocation size. | 1597 // EDI: allocation size. |
| 1594 __ addl(EBX, EDI); | 1598 __ addl(EBX, EDI); |
| 1595 __ j(CARRY, failure); | 1599 __ j(CARRY, &pop_and_fail, Assembler::kNearJump); |
| 1596 | 1600 |
| 1597 // Check if the allocation fits into the remaining space. | 1601 // Check if the allocation fits into the remaining space. |
| 1598 // EAX: potential new object start. | 1602 // EAX: potential new object start. |
| 1599 // EBX: potential next object start. | 1603 // EBX: potential next object start. |
| 1600 // EDI: allocation size. | 1604 // EDI: allocation size. |
| 1601 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); | 1605 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); |
| 1602 __ j(ABOVE_EQUAL, failure); | 1606 __ j(ABOVE_EQUAL, &pop_and_fail, Assembler::kNearJump); |
| 1603 | 1607 |
| 1604 // Successfully allocated the object(s), now update top to point to | 1608 // Successfully allocated the object(s), now update top to point to |
| 1605 // next object start and initialize the object. | 1609 // next object start and initialize the object. |
| 1606 __ movl(Address::Absolute(heap->TopAddress()), EBX); | 1610 __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| 1607 __ addl(EAX, Immediate(kHeapObjectTag)); | 1611 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 1608 | 1612 |
| 1609 // Initialize the tags. | 1613 // Initialize the tags. |
| 1610 // EAX: new object start as a tagged pointer. | 1614 // EAX: new object start as a tagged pointer. |
| 1611 // EBX: new object end address. | 1615 // EBX: new object end address. |
| 1612 // EDI: allocation size. | 1616 // EDI: allocation size. |
| 1613 { | 1617 { |
| 1614 Label size_tag_overflow, done; | 1618 Label size_tag_overflow, done; |
| 1615 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 1619 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1616 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 1620 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1617 __ shll(EDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 1621 __ shll(EDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| 1618 __ jmp(&done, Assembler::kNearJump); | 1622 __ jmp(&done, Assembler::kNearJump); |
| 1619 | 1623 |
| 1620 __ Bind(&size_tag_overflow); | 1624 __ Bind(&size_tag_overflow); |
| 1621 __ xorl(EDI, EDI); | 1625 __ xorl(EDI, EDI); |
| 1622 __ Bind(&done); | 1626 __ Bind(&done); |
| 1623 | 1627 |
| 1624 // Get the class index and insert it into the tags. | 1628 // Get the class index and insert it into the tags. |
| 1625 const Class& cls = | 1629 const Class& cls = |
| 1626 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1630 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 1627 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cls.id()))); | 1631 __ orl(EDI, Immediate(RawObject::ClassIdTag::encode(cls.id()))); |
| 1628 __ movl(FieldAddress(EAX, String::tags_offset()), EDI); // Tags. | 1632 __ movl(FieldAddress(EAX, String::tags_offset()), EDI); // Tags. |
| 1629 } | 1633 } |
| 1630 | 1634 |
| 1631 // Set the length field. | 1635 // Set the length field. |
| 1632 __ movl(EDI, Address(ESP, + end_index_offset)); | 1636 __ popl(EDI); |
| 1633 __ subl(EDI, Address(ESP, + start_index_offset)); // Length. | |
| 1634 __ StoreIntoObjectNoBarrier(EAX, | 1637 __ StoreIntoObjectNoBarrier(EAX, |
| 1635 FieldAddress(EAX, String::length_offset()), | 1638 FieldAddress(EAX, String::length_offset()), |
| 1636 EDI); | 1639 EDI); |
| 1637 // Clear hash. | 1640 // Clear hash. |
| 1638 __ movl(FieldAddress(EAX, String::hash_offset()), Immediate(0)); | 1641 __ movl(FieldAddress(EAX, String::hash_offset()), Immediate(0)); |
| 1642 __ jmp(ok, Assembler::kNearJump); |
| 1643 |
| 1644 __ Bind(&pop_and_fail); |
| 1645 __ popl(EDI); |
| 1646 __ jmp(failure); |
| 1639 } | 1647 } |
| 1640 | 1648 |
| 1641 | 1649 |
| 1642 // Arg0: Onebyte String | 1650 // Arg0: Onebyte String |
| 1643 // Arg1: Start index as Smi. | 1651 // Arg1: Start index as Smi. |
| 1644 // Arg2: End index as Smi. | 1652 // Arg2: End index as Smi. |
| 1645 // The indexes must be valid. | 1653 // The indexes must be valid. |
| 1646 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { | 1654 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { |
| 1647 const intptr_t kStringOffset = 3 * kWordSize; | 1655 const intptr_t kStringOffset = 3 * kWordSize; |
| 1648 const intptr_t kStartIndexOffset = 2 * kWordSize; | 1656 const intptr_t kStartIndexOffset = 2 * kWordSize; |
| 1649 const intptr_t kEndIndexOffset = 1 * kWordSize; | 1657 const intptr_t kEndIndexOffset = 1 * kWordSize; |
| 1650 Label fall_through; | 1658 Label fall_through, ok; |
| 1651 TryAllocateOnebyteString( | 1659 __ movl(EDI, Address(ESP, + kEndIndexOffset)); |
| 1652 assembler, &fall_through, kStartIndexOffset, kEndIndexOffset); | 1660 __ subl(EDI, Address(ESP, + kStartIndexOffset)); |
| 1661 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI); |
| 1662 __ Bind(&ok); |
| 1653 // EAX: new string as tagged pointer. | 1663 // EAX: new string as tagged pointer. |
| 1654 // Copy string. | 1664 // Copy string. |
| 1655 __ movl(EDI, Address(ESP, + kStringOffset)); | 1665 __ movl(EDI, Address(ESP, + kStringOffset)); |
| 1656 __ movl(EBX, Address(ESP, + kStartIndexOffset)); | 1666 __ movl(EBX, Address(ESP, + kStartIndexOffset)); |
| 1657 __ SmiUntag(EBX); | 1667 __ SmiUntag(EBX); |
| 1658 __ leal(EDI, FieldAddress(EDI, EBX, TIMES_1, OneByteString::data_offset())); | 1668 __ leal(EDI, FieldAddress(EDI, EBX, TIMES_1, OneByteString::data_offset())); |
| 1659 // EDI: Start address to copy from (untagged). | 1669 // EDI: Start address to copy from (untagged). |
| 1660 // EBX: Untagged start index. | 1670 // EBX: Untagged start index. |
| 1661 __ movl(ECX, Address(ESP, + kEndIndexOffset)); | 1671 __ movl(ECX, Address(ESP, + kEndIndexOffset)); |
| 1662 __ SmiUntag(ECX); | 1672 __ SmiUntag(ECX); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1674 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL); | 1684 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL); |
| 1675 __ incl(EDX); | 1685 __ incl(EDX); |
| 1676 __ Bind(&check); | 1686 __ Bind(&check); |
| 1677 __ cmpl(EDX, ECX); | 1687 __ cmpl(EDX, ECX); |
| 1678 __ j(LESS, &loop, Assembler::kNearJump); | 1688 __ j(LESS, &loop, Assembler::kNearJump); |
| 1679 __ ret(); | 1689 __ ret(); |
| 1680 __ Bind(&fall_through); | 1690 __ Bind(&fall_through); |
| 1681 return false; | 1691 return false; |
| 1682 } | 1692 } |
| 1683 | 1693 |
| 1694 |
| 1695 bool Intrinsifier::OneByteString_setAt(Assembler* assembler) { |
| 1696 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. |
| 1697 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. |
| 1698 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // OneByteString. |
| 1699 __ SmiUntag(EBX); |
| 1700 __ SmiUntag(ECX); |
| 1701 __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL); |
| 1702 __ ret(); |
| 1703 return true; |
| 1704 } |
| 1705 |
| 1706 |
| 1707 bool Intrinsifier::OneByteString_allocate(Assembler* assembler) { |
| 1708 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Length. |
| 1709 Label fall_through, ok; |
| 1710 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI); |
| 1711 // EDI: Start address to copy from (untagged). |
| 1712 |
| 1713 __ Bind(&ok); |
| 1714 __ ret(); |
| 1715 |
| 1716 __ Bind(&fall_through); |
| 1717 return false; |
| 1718 } |
| 1719 |
| 1684 #undef __ | 1720 #undef __ |
| 1685 } // namespace dart | 1721 } // namespace dart |
| 1686 | 1722 |
| 1687 #endif // defined TARGET_ARCH_IA32 | 1723 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |