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 |