| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1637 | 1637 |
| 1638 // Perform tail call to the entry. | 1638 // Perform tail call to the entry. |
| 1639 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); | 1639 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); |
| 1640 __ TailCallExternalReference(ref, 2, 1); | 1640 __ TailCallExternalReference(ref, 2, 1); |
| 1641 } | 1641 } |
| 1642 | 1642 |
| 1643 | 1643 |
| 1644 // One byte opcode for test eax,0xXXXXXXXX. | 1644 // One byte opcode for test eax,0xXXXXXXXX. |
| 1645 static const byte kTestEaxByte = 0xA9; | 1645 static const byte kTestEaxByte = 0xA9; |
| 1646 | 1646 |
| 1647 | |
| 1648 void LoadIC::ClearInlinedVersion(Address address) { | |
| 1649 // Reset the map check of the inlined inobject property load (if | |
| 1650 // present) to guarantee failure by holding an invalid map (the null | |
| 1651 // value). The offset can be patched to anything. | |
| 1652 PatchInlinedLoad(address, Heap::null_value(), kMaxInt); | |
| 1653 } | |
| 1654 | |
| 1655 | |
| 1656 void KeyedLoadIC::ClearInlinedVersion(Address address) { | |
| 1657 // Insert null as the map to check for to make sure the map check fails | |
| 1658 // sending control flow to the IC instead of the inlined version. | |
| 1659 PatchInlinedLoad(address, Heap::null_value()); | |
| 1660 } | |
| 1661 | |
| 1662 | |
| 1663 void KeyedStoreIC::ClearInlinedVersion(Address address) { | |
| 1664 // Insert null as the elements map to check for. This will make | |
| 1665 // sure that the elements fast-case map check fails so that control | |
| 1666 // flows to the IC instead of the inlined version. | |
| 1667 PatchInlinedStore(address, Heap::null_value()); | |
| 1668 } | |
| 1669 | |
| 1670 | |
| 1671 void KeyedStoreIC::RestoreInlinedVersion(Address address) { | |
| 1672 // Restore the fast-case elements map check so that the inlined | |
| 1673 // version can be used again. | |
| 1674 PatchInlinedStore(address, Heap::fixed_array_map()); | |
| 1675 } | |
| 1676 | |
| 1677 | |
| 1678 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1647 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1679 // The address of the instruction following the call. | 1648 // The address of the instruction following the call. |
| 1680 Address test_instruction_address = | 1649 Address test_instruction_address = |
| 1681 address + Assembler::kCallTargetAddressOffset; | 1650 address + Assembler::kCallTargetAddressOffset; |
| 1682 // If the instruction following the call is not a test eax, nothing | 1651 // If the instruction following the call is not a test eax, nothing |
| 1683 // was inlined. | 1652 // was inlined. |
| 1684 if (*test_instruction_address != kTestEaxByte) return false; | 1653 if (*test_instruction_address != kTestEaxByte) return false; |
| 1685 | 1654 |
| 1686 Address delta_address = test_instruction_address + 1; | 1655 Address delta_address = test_instruction_address + 1; |
| 1687 // The delta to the start of the map check instruction. | 1656 // The delta to the start of the map check instruction. |
| 1688 int delta = *reinterpret_cast<int*>(delta_address); | 1657 int delta = *reinterpret_cast<int*>(delta_address); |
| 1689 | 1658 |
| 1690 // The map address is the last 4 bytes of the 7-byte | 1659 // The map address is the last 4 bytes of the 7-byte |
| 1691 // operand-immediate compare instruction, so we add 3 to get the | 1660 // operand-immediate compare instruction, so we add 3 to get the |
| 1692 // offset to the last 4 bytes. | 1661 // offset to the last 4 bytes. |
| 1693 Address map_address = test_instruction_address + delta + 3; | 1662 Address map_address = test_instruction_address + delta + 3; |
| 1694 *(reinterpret_cast<Object**>(map_address)) = map; | 1663 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1695 | 1664 |
| 1696 // The offset is in the last 4 bytes of a six byte | 1665 // The offset is in the last 4 bytes of a six byte |
| 1697 // memory-to-register move instruction, so we add 2 to get the | 1666 // memory-to-register move instruction, so we add 2 to get the |
| 1698 // offset to the last 4 bytes. | 1667 // offset to the last 4 bytes. |
| 1699 Address offset_address = | 1668 Address offset_address = |
| 1700 test_instruction_address + delta + kOffsetToLoadInstruction + 2; | 1669 test_instruction_address + delta + kOffsetToLoadInstruction + 2; |
| 1701 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1670 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1702 return true; | 1671 return true; |
| 1703 } | 1672 } |
| 1704 | 1673 |
| 1705 | 1674 |
| 1675 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
| 1676 // The address of the instruction following the call. |
| 1677 Address test_instruction_address = |
| 1678 address + Assembler::kCallTargetAddressOffset; |
| 1679 |
| 1680 // If the instruction following the call is not a test eax, nothing |
| 1681 // was inlined. |
| 1682 if (*test_instruction_address != kTestEaxByte) return false; |
| 1683 |
| 1684 // Extract the encoded deltas from the test eax instruction. |
| 1685 Address encoded_offsets_address = test_instruction_address + 1; |
| 1686 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
| 1687 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
| 1688 int delta_to_record_write = encoded_offsets >> 16; |
| 1689 |
| 1690 // Patch the map to check. The map address is the last 4 bytes of |
| 1691 // the 7-byte operand-immediate compare instruction. |
| 1692 Address map_check_address = test_instruction_address + delta_to_map_check; |
| 1693 Address map_address = map_check_address + 3; |
| 1694 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1695 |
| 1696 // Patch the offset in the store instruction. The offset is in the |
| 1697 // last 4 bytes of a six byte register-to-memory move instruction. |
| 1698 Address offset_address = |
| 1699 map_check_address + StoreIC::kOffsetToStoreInstruction + 2; |
| 1700 // The offset should have initial value (kMaxInt - 1), cleared value |
| 1701 // (-1) or we should be clearing the inlined version. |
| 1702 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || |
| 1703 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1704 (offset == 0 && map == Heap::null_value())); |
| 1705 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1706 |
| 1707 // Patch the offset in the write-barrier code. The offset is the |
| 1708 // last 4 bytes of a six byte lea instruction. |
| 1709 offset_address = map_check_address + delta_to_record_write + 2; |
| 1710 // The offset should have initial value (kMaxInt), cleared value |
| 1711 // (-1) or we should be clearing the inlined version. |
| 1712 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
| 1713 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1714 (offset == 0 && map == Heap::null_value())); |
| 1715 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1716 |
| 1717 return true; |
| 1718 } |
| 1719 |
| 1720 |
| 1706 static bool PatchInlinedMapCheck(Address address, Object* map) { | 1721 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 1707 Address test_instruction_address = | 1722 Address test_instruction_address = |
| 1708 address + Assembler::kCallTargetAddressOffset; | 1723 address + Assembler::kCallTargetAddressOffset; |
| 1709 // The keyed load has a fast inlined case if the IC call instruction | 1724 // The keyed load has a fast inlined case if the IC call instruction |
| 1710 // is immediately followed by a test instruction. | 1725 // is immediately followed by a test instruction. |
| 1711 if (*test_instruction_address != kTestEaxByte) return false; | 1726 if (*test_instruction_address != kTestEaxByte) return false; |
| 1712 | 1727 |
| 1713 // Fetch the offset from the test instruction to the map cmp | 1728 // Fetch the offset from the test instruction to the map cmp |
| 1714 // instruction. This offset is stored in the last 4 bytes of the 5 | 1729 // instruction. This offset is stored in the last 4 bytes of the 5 |
| 1715 // byte test instruction. | 1730 // byte test instruction. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1807 __ push(ecx); | 1822 __ push(ecx); |
| 1808 __ push(eax); | 1823 __ push(eax); |
| 1809 __ push(ebx); | 1824 __ push(ebx); |
| 1810 | 1825 |
| 1811 // Perform tail call to the entry. | 1826 // Perform tail call to the entry. |
| 1812 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); | 1827 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); |
| 1813 __ TailCallExternalReference(ref, 3, 1); | 1828 __ TailCallExternalReference(ref, 3, 1); |
| 1814 } | 1829 } |
| 1815 | 1830 |
| 1816 | 1831 |
| 1832 // The offset from the inlined patch site to the start of the inlined |
| 1833 // store instruction. It is 7 bytes (test reg, imm) plus 6 bytes (jne |
| 1834 // slow_label). |
| 1835 const int StoreIC::kOffsetToStoreInstruction = 13; |
| 1836 |
| 1837 |
| 1817 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { | 1838 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1818 // ----------- S t a t e ------------- | 1839 // ----------- S t a t e ------------- |
| 1819 // -- eax : value | 1840 // -- eax : value |
| 1820 // -- ecx : name | 1841 // -- ecx : name |
| 1821 // -- edx : receiver | 1842 // -- edx : receiver |
| 1822 // -- esp[0] : return address | 1843 // -- esp[0] : return address |
| 1823 // ----------------------------------- | 1844 // ----------------------------------- |
| 1824 // | 1845 // |
| 1825 // This accepts as a receiver anything JSObject::SetElementsLength accepts | 1846 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1826 // (currently anything except for external and pixel arrays which means | 1847 // (currently anything except for external and pixel arrays which means |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1936 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1957 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1937 __ TailCallExternalReference(ref, 3, 1); | 1958 __ TailCallExternalReference(ref, 3, 1); |
| 1938 } | 1959 } |
| 1939 | 1960 |
| 1940 #undef __ | 1961 #undef __ |
| 1941 | 1962 |
| 1942 | 1963 |
| 1943 } } // namespace v8::internal | 1964 } } // namespace v8::internal |
| 1944 | 1965 |
| 1945 #endif // V8_TARGET_ARCH_IA32 | 1966 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |