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 |