| 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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 Smi::FromInt(PropertyDetails::TypeField::mask())); | 372 Smi::FromInt(PropertyDetails::TypeField::mask())); |
| 373 __ j(not_zero, miss); | 373 __ j(not_zero, miss); |
| 374 | 374 |
| 375 // Get the value at the masked, scaled index. | 375 // Get the value at the masked, scaled index. |
| 376 const int kValueOffset = | 376 const int kValueOffset = |
| 377 NumberDictionary::kElementsStartOffset + kPointerSize; | 377 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 378 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 378 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
| 379 } | 379 } |
| 380 | 380 |
| 381 | 381 |
| 382 // One byte opcode for test eax,0xXXXXXXXX. | 382 // One byte opcode for test rax,0xXXXXXXXX. |
| 383 static const byte kTestEaxByte = 0xA9; | 383 static const byte kTestEaxByte = 0xA9; |
| 384 | 384 |
| 385 | 385 |
| 386 static bool PatchInlinedMapCheck(Address address, Object* map) { | 386 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 387 // Arguments are address of start of call sequence that called | 387 // Arguments are address of start of call sequence that called |
| 388 // the IC, | 388 // the IC, |
| 389 Address test_instruction_address = | 389 Address test_instruction_address = |
| 390 address + Assembler::kCallTargetAddressOffset; | 390 address + Assembler::kCallTargetAddressOffset; |
| 391 // The keyed load has a fast inlined case if the IC call instruction | 391 // The keyed load has a fast inlined case if the IC call instruction |
| 392 // is immediately followed by a test instruction. | 392 // is immediately followed by a test instruction. |
| (...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load); | 1513 masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load); |
| 1514 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); | 1514 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); |
| 1515 | 1515 |
| 1516 __ bind(&do_call); | 1516 __ bind(&do_call); |
| 1517 // receiver in rdx is not used after this point. | 1517 // receiver in rdx is not used after this point. |
| 1518 // rcx: key | 1518 // rcx: key |
| 1519 // rdi: function | 1519 // rdi: function |
| 1520 GenerateFunctionTailCall(masm, argc, &slow_call); | 1520 GenerateFunctionTailCall(masm, argc, &slow_call); |
| 1521 | 1521 |
| 1522 __ bind(&check_number_dictionary); | 1522 __ bind(&check_number_dictionary); |
| 1523 // eax: elements | 1523 // rax: elements |
| 1524 // ecx: smi key | 1524 // rcx: smi key |
| 1525 // Check whether the elements is a number dictionary. | 1525 // Check whether the elements is a number dictionary. |
| 1526 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 1526 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
| 1527 Heap::kHashTableMapRootIndex); | 1527 Heap::kHashTableMapRootIndex); |
| 1528 __ j(not_equal, &slow_load); | 1528 __ j(not_equal, &slow_load); |
| 1529 __ SmiToInteger32(rbx, rcx); | 1529 __ SmiToInteger32(rbx, rcx); |
| 1530 // ebx: untagged index | 1530 // ebx: untagged index |
| 1531 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi); | 1531 GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi); |
| 1532 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); | 1532 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); |
| 1533 __ jmp(&do_call); | 1533 __ jmp(&do_call); |
| 1534 | 1534 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1596 // ... | 1596 // ... |
| 1597 // rsp[argc * 8] : argument 1 | 1597 // rsp[argc * 8] : argument 1 |
| 1598 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1598 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1599 // ----------------------------------- | 1599 // ----------------------------------- |
| 1600 | 1600 |
| 1601 GenerateCallNormal(masm, argc); | 1601 GenerateCallNormal(masm, argc); |
| 1602 GenerateMiss(masm, argc); | 1602 GenerateMiss(masm, argc); |
| 1603 } | 1603 } |
| 1604 | 1604 |
| 1605 | 1605 |
| 1606 // The offset from the inlined patch site to the start of the | 1606 // The offset from the inlined patch site to the start of the inlined |
| 1607 // inlined load instruction. | 1607 // load instruction. |
| 1608 const int LoadIC::kOffsetToLoadInstruction = 20; | 1608 const int LoadIC::kOffsetToLoadInstruction = 20; |
| 1609 | 1609 |
| 1610 | 1610 |
| 1611 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 1611 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1612 // ----------- S t a t e ------------- | 1612 // ----------- S t a t e ------------- |
| 1613 // -- rax : receiver | 1613 // -- rax : receiver |
| 1614 // -- rcx : name | 1614 // -- rcx : name |
| 1615 // -- rsp[0] : return address | 1615 // -- rsp[0] : return address |
| 1616 // ----------------------------------- | 1616 // ----------------------------------- |
| 1617 | 1617 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1706 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); | 1706 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); |
| 1707 __ bind(&miss); | 1707 __ bind(&miss); |
| 1708 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1708 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 1709 } | 1709 } |
| 1710 | 1710 |
| 1711 | 1711 |
| 1712 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1712 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1713 // The address of the instruction following the call. | 1713 // The address of the instruction following the call. |
| 1714 Address test_instruction_address = | 1714 Address test_instruction_address = |
| 1715 address + Assembler::kCallTargetAddressOffset; | 1715 address + Assembler::kCallTargetAddressOffset; |
| 1716 // If the instruction following the call is not a test eax, nothing | 1716 // If the instruction following the call is not a test rax, nothing |
| 1717 // was inlined. | 1717 // was inlined. |
| 1718 if (*test_instruction_address != kTestEaxByte) return false; | 1718 if (*test_instruction_address != kTestEaxByte) return false; |
| 1719 | 1719 |
| 1720 Address delta_address = test_instruction_address + 1; | 1720 Address delta_address = test_instruction_address + 1; |
| 1721 // The delta to the start of the map check instruction. | 1721 // The delta to the start of the map check instruction. |
| 1722 int delta = *reinterpret_cast<int*>(delta_address); | 1722 int delta = *reinterpret_cast<int*>(delta_address); |
| 1723 | 1723 |
| 1724 // The map address is the last 8 bytes of the 10-byte | 1724 // The map address is the last 8 bytes of the 10-byte |
| 1725 // immediate move instruction, so we add 2 to get the | 1725 // immediate move instruction, so we add 2 to get the |
| 1726 // offset to the last 8 bytes. | 1726 // offset to the last 8 bytes. |
| 1727 Address map_address = test_instruction_address + delta + 2; | 1727 Address map_address = test_instruction_address + delta + 2; |
| 1728 *(reinterpret_cast<Object**>(map_address)) = map; | 1728 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1729 | 1729 |
| 1730 // The offset is in the 32-bit displacement of a seven byte | 1730 // The offset is in the 32-bit displacement of a seven byte |
| 1731 // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), | 1731 // memory-to-register move instruction (REX.W 0x88 ModR/M disp32), |
| 1732 // so we add 3 to get the offset of the displacement. | 1732 // so we add 3 to get the offset of the displacement. |
| 1733 Address offset_address = | 1733 Address offset_address = |
| 1734 test_instruction_address + delta + kOffsetToLoadInstruction + 3; | 1734 test_instruction_address + delta + kOffsetToLoadInstruction + 3; |
| 1735 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1735 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1736 return true; | 1736 return true; |
| 1737 } | 1737 } |
| 1738 | 1738 |
| 1739 | 1739 |
| 1740 // The offset from the inlined patch site to the start of the inlined |
| 1741 // store instruction. |
| 1742 const int StoreIC::kOffsetToStoreInstruction = 20; |
| 1743 |
| 1744 |
| 1740 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | 1745 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
| 1741 // TODO(787): Implement inline stores on x64. | 1746 // The address of the instruction following the call. |
| 1742 return false; | 1747 Address test_instruction_address = |
| 1748 address + Assembler::kCallTargetAddressOffset; |
| 1749 |
| 1750 // If the instruction following the call is not a test rax, nothing |
| 1751 // was inlined. |
| 1752 if (*test_instruction_address != kTestEaxByte) return false; |
| 1753 |
| 1754 // Extract the encoded deltas from the test rax instruction. |
| 1755 Address encoded_offsets_address = test_instruction_address + 1; |
| 1756 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
| 1757 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
| 1758 int delta_to_record_write = encoded_offsets >> 16; |
| 1759 |
| 1760 // Patch the map to check. The map address is the last 8 bytes of |
| 1761 // the 10-byte immediate move instruction. |
| 1762 Address map_check_address = test_instruction_address + delta_to_map_check; |
| 1763 Address map_address = map_check_address + 2; |
| 1764 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1765 |
| 1766 // Patch the offset in the store instruction. The offset is in the |
| 1767 // last 4 bytes of a 7 byte register-to-memory move instruction. |
| 1768 Address offset_address = |
| 1769 map_check_address + StoreIC::kOffsetToStoreInstruction + 3; |
| 1770 // The offset should have initial value (kMaxInt - 1), cleared value |
| 1771 // (-1) or we should be clearing the inlined version. |
| 1772 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt - 1 || |
| 1773 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1774 (offset == 0 && map == Heap::null_value())); |
| 1775 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1776 |
| 1777 // Patch the offset in the write-barrier code. The offset is the |
| 1778 // last 4 bytes of a 7 byte lea instruction. |
| 1779 offset_address = map_check_address + delta_to_record_write + 3; |
| 1780 // The offset should have initial value (kMaxInt), cleared value |
| 1781 // (-1) or we should be clearing the inlined version. |
| 1782 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
| 1783 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1784 (offset == 0 && map == Heap::null_value())); |
| 1785 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1786 |
| 1787 return true; |
| 1743 } | 1788 } |
| 1744 | 1789 |
| 1745 | 1790 |
| 1746 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1791 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1747 // ----------- S t a t e ------------- | 1792 // ----------- S t a t e ------------- |
| 1748 // -- rax : value | 1793 // -- rax : value |
| 1749 // -- rcx : name | 1794 // -- rcx : name |
| 1750 // -- rdx : receiver | 1795 // -- rdx : receiver |
| 1751 // -- rsp[0] : return address | 1796 // -- rsp[0] : return address |
| 1752 // ----------------------------------- | 1797 // ----------------------------------- |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1853 GenerateMiss(masm); | 1898 GenerateMiss(masm); |
| 1854 } | 1899 } |
| 1855 | 1900 |
| 1856 | 1901 |
| 1857 #undef __ | 1902 #undef __ |
| 1858 | 1903 |
| 1859 | 1904 |
| 1860 } } // namespace v8::internal | 1905 } } // namespace v8::internal |
| 1861 | 1906 |
| 1862 #endif // V8_TARGET_ARCH_X64 | 1907 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |