| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 1538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 __ Ret(); | 1549 __ Ret(); |
| 1550 __ Bind(&is_true); | 1550 __ Bind(&is_true); |
| 1551 __ LoadObject(V0, Bool::True()); | 1551 __ LoadObject(V0, Bool::True()); |
| 1552 __ Ret(); | 1552 __ Ret(); |
| 1553 return true; | 1553 return true; |
| 1554 } | 1554 } |
| 1555 | 1555 |
| 1556 | 1556 |
| 1557 bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { | 1557 bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { |
| 1558 Label no_hash; | 1558 Label no_hash; |
| 1559 __ Untested("Intrinsifier::OneByteString_getHashCode"); | 1559 |
| 1560 __ lw(T1, Address(SP, 0 * kWordSize)); | 1560 __ lw(T1, Address(SP, 0 * kWordSize)); |
| 1561 __ lw(T0, FieldAddress(T1, String::hash_offset())); | 1561 __ lw(V0, FieldAddress(T1, String::hash_offset())); |
| 1562 __ beq(T0, ZR, &no_hash); | 1562 __ beq(V0, ZR, &no_hash); |
| 1563 __ Ret(); // Return if already computed. | 1563 __ Ret(); // Return if already computed. |
| 1564 __ Bind(&no_hash); | 1564 __ Bind(&no_hash); |
| 1565 | 1565 |
| 1566 __ lw(T2, FieldAddress(T1, String::length_offset())); | 1566 __ lw(T2, FieldAddress(T1, String::length_offset())); |
| 1567 | 1567 |
| 1568 Label done; | 1568 Label done; |
| 1569 // If the string is empty, set the hash to 1, and return. | 1569 // If the string is empty, set the hash to 1, and return. |
| 1570 __ BranchEqual(T2, Smi::RawValue(0), &done); | 1570 __ BranchEqual(T2, Smi::RawValue(0), &done); |
| 1571 __ delay_slot()->mov(T0, ZR); | 1571 __ delay_slot()->mov(V0, ZR); |
| 1572 | 1572 |
| 1573 __ SmiUntag(T2); | 1573 __ SmiUntag(T2); |
| 1574 __ AddImmediate(T3, T1, OneByteString::data_offset() - kHeapObjectTag); | 1574 __ AddImmediate(T3, T1, OneByteString::data_offset() - kHeapObjectTag); |
| 1575 __ addu(T4, T3, T2); | 1575 __ addu(T4, T3, T2); |
| 1576 // T0: Hash code, untagged integer. | 1576 // V0: Hash code, untagged integer. |
| 1577 // T1: Instance of OneByteString. | 1577 // T1: Instance of OneByteString. |
| 1578 // T2: String length, untagged integer. | 1578 // T2: String length, untagged integer. |
| 1579 // T3: String data start. | 1579 // T3: String data start. |
| 1580 // T4: String data end. | 1580 // T4: String data end. |
| 1581 | 1581 |
| 1582 Label loop; | 1582 Label loop; |
| 1583 // Add to hash code: (hash_ is uint32) | 1583 // Add to hash code: (hash_ is uint32) |
| 1584 // hash_ += ch; | 1584 // hash_ += ch; |
| 1585 // hash_ += hash_ << 10; | 1585 // hash_ += hash_ << 10; |
| 1586 // hash_ ^= hash_ >> 6; | 1586 // hash_ ^= hash_ >> 6; |
| 1587 // Get one characters (ch). | 1587 // Get one characters (ch). |
| 1588 __ Bind(&loop); | 1588 __ Bind(&loop); |
| 1589 __ lw(T5, Address(T3)); | 1589 __ lbu(T5, Address(T3)); |
| 1590 // T5: ch. | 1590 // T5: ch. |
| 1591 __ addiu(T3, T3, Immediate(1)); | 1591 __ addiu(T3, T3, Immediate(1)); |
| 1592 __ addu(T0, T0, T5); | 1592 __ addu(V0, V0, T5); |
| 1593 __ sll(TMP, T0, 10); | 1593 __ sll(TMP, V0, 10); |
| 1594 __ addu(T0, T0, TMP); | 1594 __ addu(V0, V0, TMP); |
| 1595 __ srl(TMP, T0, 6); | 1595 __ srl(TMP, V0, 6); |
| 1596 __ BranchUnsignedLess(T3, T4, &loop); | 1596 __ bne(T3, T4, &loop); |
| 1597 __ delay_slot()->xor_(T0, T0, TMP); | 1597 __ delay_slot()->xor_(V0, V0, TMP); |
| 1598 | 1598 |
| 1599 // Finalize. | 1599 // Finalize. |
| 1600 // hash_ += hash_ << 3; | 1600 // hash_ += hash_ << 3; |
| 1601 // hash_ ^= hash_ >> 11; | 1601 // hash_ ^= hash_ >> 11; |
| 1602 // hash_ += hash_ << 15; | 1602 // hash_ += hash_ << 15; |
| 1603 __ sll(TMP, T0, 3); | 1603 __ sll(TMP, V0, 3); |
| 1604 __ addu(T0, T0, TMP); | 1604 __ addu(V0, V0, TMP); |
| 1605 __ srl(TMP, T0, 11); | 1605 __ srl(TMP, V0, 11); |
| 1606 __ xor_(T0, T0, TMP); | 1606 __ xor_(V0, V0, TMP); |
| 1607 __ sll(TMP, T0, 15); | 1607 __ sll(TMP, V0, 15); |
| 1608 __ addu(T0, T0, TMP); | 1608 __ addu(V0, V0, TMP); |
| 1609 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); | 1609 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); |
| 1610 __ LoadImmediate(TMP, (static_cast<intptr_t>(1) << String::kHashBits) - 1); | 1610 __ LoadImmediate(TMP, (static_cast<intptr_t>(1) << String::kHashBits) - 1); |
| 1611 __ and_(T0, T0, TMP); | 1611 __ and_(V0, V0, TMP); |
| 1612 __ Bind(&done); | 1612 __ Bind(&done); |
| 1613 | 1613 |
| 1614 __ LoadImmediate(T2, 1); | 1614 __ LoadImmediate(T2, 1); |
| 1615 __ movz(T0, T2, T0); // If T0 is 0, set to 1. | 1615 __ movz(V0, T2, V0); // If V0 is 0, set to 1. |
| 1616 __ SmiTag(T0); | 1616 __ SmiTag(V0); |
| 1617 |
| 1617 __ Ret(); | 1618 __ Ret(); |
| 1618 __ delay_slot()->sw(T0, FieldAddress(T1, String::hash_offset())); | 1619 __ delay_slot()->sw(V0, FieldAddress(T1, String::hash_offset())); |
| 1619 return false; | 1620 return true; |
| 1620 } | 1621 } |
| 1621 | 1622 |
| 1622 | 1623 |
| 1623 // Allocates one-byte string of length 'end - start'. The content is not | 1624 // Allocates one-byte string of length 'end - start'. The content is not |
| 1624 // initialized. | 1625 // initialized. |
| 1625 // 'length-reg' (T2) contains tagged length. | 1626 // 'length-reg' (T2) contains tagged length. |
| 1626 // Returns new string as tagged pointer in V0. | 1627 // Returns new string as tagged pointer in V0. |
| 1627 static void TryAllocateOnebyteString(Assembler* assembler, | 1628 static void TryAllocateOnebyteString(Assembler* assembler, |
| 1628 Label* ok, | 1629 Label* ok, |
| 1629 Label* failure) { | 1630 Label* failure) { |
| 1630 const Register length_reg = T2; | 1631 const Register length_reg = T2; |
| 1631 Label fail; | |
| 1632 | 1632 |
| 1633 __ mov(T6, length_reg); // Save the length register. | 1633 __ mov(T6, length_reg); // Save the length register. |
| 1634 __ SmiUntag(length_reg); | 1634 __ SmiUntag(length_reg); |
| 1635 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1635 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
| 1636 __ AddImmediate(length_reg, fixed_size); | 1636 __ AddImmediate(length_reg, fixed_size); |
| 1637 __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); | 1637 __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); |
| 1638 __ and_(length_reg, length_reg, TMP); | 1638 __ and_(length_reg, length_reg, TMP); |
| 1639 | 1639 |
| 1640 Isolate* isolate = Isolate::Current(); | 1640 Isolate* isolate = Isolate::Current(); |
| 1641 Heap* heap = isolate->heap(); | 1641 Heap* heap = isolate->heap(); |
| 1642 | 1642 |
| 1643 __ LoadImmediate(T3, heap->TopAddress()); | 1643 __ LoadImmediate(T3, heap->TopAddress()); |
| 1644 __ lw(V0, Address(T3, 0)); | 1644 __ lw(V0, Address(T3, 0)); |
| 1645 | 1645 |
| 1646 // length_reg: allocation size. | 1646 // length_reg: allocation size. |
| 1647 __ AdduDetectOverflow(T1, V0, length_reg, CMPRES); | 1647 __ AdduDetectOverflow(T1, V0, length_reg, CMPRES); |
| 1648 __ bltz(CMPRES, &fail); // Fail on overflow. | 1648 __ bltz(CMPRES, failure); // Fail on overflow. |
| 1649 | 1649 |
| 1650 // Check if the allocation fits into the remaining space. | 1650 // Check if the allocation fits into the remaining space. |
| 1651 // V0: potential new object start. | 1651 // V0: potential new object start. |
| 1652 // T1: potential next object start. | 1652 // T1: potential next object start. |
| 1653 // T2: allocation size. | 1653 // T2: allocation size. |
| 1654 // T3: heap->TopAddress(). | 1654 // T3: heap->TopAddress(). |
| 1655 __ LoadImmediate(T4, heap->EndAddress()); | 1655 __ LoadImmediate(T4, heap->EndAddress()); |
| 1656 __ lw(T4, Address(T4, 0)); | 1656 __ lw(T4, Address(T4, 0)); |
| 1657 __ BranchUnsignedGreaterEqual(T1, T4, &fail); | 1657 __ BranchUnsignedGreaterEqual(T1, T4, failure); |
| 1658 | 1658 |
| 1659 // Successfully allocated the object(s), now update top to point to | 1659 // Successfully allocated the object(s), now update top to point to |
| 1660 // next object start and initialize the object. | 1660 // next object start and initialize the object. |
| 1661 __ sw(T1, Address(T3, 0)); | 1661 __ sw(T1, Address(T3, 0)); |
| 1662 __ AddImmediate(V0, kHeapObjectTag); | 1662 __ AddImmediate(V0, kHeapObjectTag); |
| 1663 | 1663 |
| 1664 // Initialize the tags. | 1664 // Initialize the tags. |
| 1665 // V0: new object start as a tagged pointer. | 1665 // V0: new object start as a tagged pointer. |
| 1666 // T1: new object end address. | 1666 // T1: new object end address. |
| 1667 // T2: allocation size. | 1667 // T2: allocation size. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1685 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags. | 1685 __ sw(T2, FieldAddress(V0, String::tags_offset())); // Store tags. |
| 1686 } | 1686 } |
| 1687 | 1687 |
| 1688 // Set the length field using the saved length (T6). | 1688 // Set the length field using the saved length (T6). |
| 1689 __ StoreIntoObjectNoBarrier(V0, | 1689 __ StoreIntoObjectNoBarrier(V0, |
| 1690 FieldAddress(V0, String::length_offset()), | 1690 FieldAddress(V0, String::length_offset()), |
| 1691 T6); | 1691 T6); |
| 1692 // Clear hash. | 1692 // Clear hash. |
| 1693 __ b(ok); | 1693 __ b(ok); |
| 1694 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); | 1694 __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); |
| 1695 | |
| 1696 __ Bind(&fail); | |
| 1697 __ b(failure); | |
| 1698 } | 1695 } |
| 1699 | 1696 |
| 1700 | 1697 |
| 1701 // Arg0: Onebyte String | 1698 // Arg0: Onebyte String |
| 1702 // Arg1: Start index as Smi. | 1699 // Arg1: Start index as Smi. |
| 1703 // Arg2: End index as Smi. | 1700 // Arg2: End index as Smi. |
| 1704 // The indexes must be valid. | 1701 // The indexes must be valid. |
| 1705 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { | 1702 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { |
| 1706 const intptr_t kStringOffset = 2 * kWordSize; | 1703 const intptr_t kStringOffset = 2 * kWordSize; |
| 1707 const intptr_t kStartIndexOffset = 1 * kWordSize; | 1704 const intptr_t kStartIndexOffset = 1 * kWordSize; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 __ Bind(&ok); | 1772 __ Bind(&ok); |
| 1776 __ Ret(); | 1773 __ Ret(); |
| 1777 | 1774 |
| 1778 __ Bind(&fall_through); | 1775 __ Bind(&fall_through); |
| 1779 return false; | 1776 return false; |
| 1780 } | 1777 } |
| 1781 | 1778 |
| 1782 } // namespace dart | 1779 } // namespace dart |
| 1783 | 1780 |
| 1784 #endif // defined TARGET_ARCH_MIPS | 1781 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |