| 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 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 scratch1, | 703 scratch1, |
| 704 scratch2, | 704 scratch2, |
| 705 result, | 705 result, |
| 706 &miss, // When not a string. | 706 &miss, // When not a string. |
| 707 &miss, // When not a number. | 707 &miss, // When not a number. |
| 708 &miss, // When index out of range. | 708 &miss, // When index out of range. |
| 709 STRING_INDEX_IS_ARRAY_INDEX); | 709 STRING_INDEX_IS_ARRAY_INDEX); |
| 710 char_at_generator.GenerateFast(masm); | 710 char_at_generator.GenerateFast(masm); |
| 711 __ ret(0); | 711 __ ret(0); |
| 712 | 712 |
| 713 ICRuntimeCallHelper call_helper; | 713 StubRuntimeCallHelper call_helper; |
| 714 char_at_generator.GenerateSlow(masm, call_helper); | 714 char_at_generator.GenerateSlow(masm, call_helper); |
| 715 | 715 |
| 716 __ bind(&miss); | 716 __ bind(&miss); |
| 717 GenerateMiss(masm); | 717 GenerateMiss(masm); |
| 718 } | 718 } |
| 719 | 719 |
| 720 | 720 |
| 721 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, | 721 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, |
| 722 ExternalArrayType array_type) { | 722 ExternalArrayType array_type) { |
| 723 // ----------- S t a t e ------------- | 723 // ----------- S t a t e ------------- |
| (...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 __ push(eax); // receiver | 1625 __ push(eax); // receiver |
| 1626 __ push(ecx); // name | 1626 __ push(ecx); // name |
| 1627 __ push(ebx); // return address | 1627 __ push(ebx); // return address |
| 1628 | 1628 |
| 1629 // Perform tail call to the entry. | 1629 // Perform tail call to the entry. |
| 1630 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); | 1630 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); |
| 1631 __ TailCallExternalReference(ref, 2, 1); | 1631 __ TailCallExternalReference(ref, 2, 1); |
| 1632 } | 1632 } |
| 1633 | 1633 |
| 1634 | 1634 |
| 1635 // One byte opcode for test eax,0xXXXXXXXX. | 1635 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1636 static const byte kTestEaxByte = 0xA9; | 1636 if (V8::UseCrankshaft()) return false; |
| 1637 | 1637 |
| 1638 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | |
| 1639 // The address of the instruction following the call. | 1638 // The address of the instruction following the call. |
| 1640 Address test_instruction_address = | 1639 Address test_instruction_address = |
| 1641 address + Assembler::kCallTargetAddressOffset; | 1640 address + Assembler::kCallTargetAddressOffset; |
| 1642 // If the instruction following the call is not a test eax, nothing | 1641 // If the instruction following the call is not a test eax, nothing |
| 1643 // was inlined. | 1642 // was inlined. |
| 1644 if (*test_instruction_address != kTestEaxByte) return false; | 1643 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1645 | 1644 |
| 1646 Address delta_address = test_instruction_address + 1; | 1645 Address delta_address = test_instruction_address + 1; |
| 1647 // The delta to the start of the map check instruction. | 1646 // The delta to the start of the map check instruction. |
| 1648 int delta = *reinterpret_cast<int*>(delta_address); | 1647 int delta = *reinterpret_cast<int*>(delta_address); |
| 1649 | 1648 |
| 1650 // The map address is the last 4 bytes of the 7-byte | 1649 // The map address is the last 4 bytes of the 7-byte |
| 1651 // operand-immediate compare instruction, so we add 3 to get the | 1650 // operand-immediate compare instruction, so we add 3 to get the |
| 1652 // offset to the last 4 bytes. | 1651 // offset to the last 4 bytes. |
| 1653 Address map_address = test_instruction_address + delta + 3; | 1652 Address map_address = test_instruction_address + delta + 3; |
| 1654 *(reinterpret_cast<Object**>(map_address)) = map; | 1653 *(reinterpret_cast<Object**>(map_address)) = map; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1678 // cells. Generated code doesn't have the hole check: | 1677 // cells. Generated code doesn't have the hole check: |
| 1679 // mov reg, <cell> | 1678 // mov reg, <cell> |
| 1680 // mov reg, (<cell>, value offset) | 1679 // mov reg, (<cell>, value offset) |
| 1681 // ;; use reg | 1680 // ;; use reg |
| 1682 static const byte kMovEdxByte = 0xBA; | 1681 static const byte kMovEdxByte = 0xBA; |
| 1683 | 1682 |
| 1684 bool LoadIC::PatchInlinedContextualLoad(Address address, | 1683 bool LoadIC::PatchInlinedContextualLoad(Address address, |
| 1685 Object* map, | 1684 Object* map, |
| 1686 Object* cell, | 1685 Object* cell, |
| 1687 bool is_dont_delete) { | 1686 bool is_dont_delete) { |
| 1687 if (V8::UseCrankshaft()) return false; |
| 1688 |
| 1688 // The address of the instruction following the call. | 1689 // The address of the instruction following the call. |
| 1689 Address mov_instruction_address = | 1690 Address mov_instruction_address = |
| 1690 address + Assembler::kCallTargetAddressOffset; | 1691 address + Assembler::kCallTargetAddressOffset; |
| 1691 // If the instruction following the call is not a mov ecx/edx, | 1692 // If the instruction following the call is not a mov ecx/edx, |
| 1692 // nothing was inlined. | 1693 // nothing was inlined. |
| 1693 byte b = *mov_instruction_address; | 1694 byte b = *mov_instruction_address; |
| 1694 if (b != kMovEcxByte && b != kMovEdxByte) return false; | 1695 if (b != kMovEcxByte && b != kMovEdxByte) return false; |
| 1695 // If we don't have the hole check generated, we can only support | 1696 // If we don't have the hole check generated, we can only support |
| 1696 // "don't delete" cells. | 1697 // "don't delete" cells. |
| 1697 if (b == kMovEdxByte && !is_dont_delete) return false; | 1698 if (b == kMovEdxByte && !is_dont_delete) return false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1709 // The cell is in the last 4 bytes of a five byte mov reg, imm32 | 1710 // The cell is in the last 4 bytes of a five byte mov reg, imm32 |
| 1710 // instruction, so we add 1 to get the offset to the last 4 bytes. | 1711 // instruction, so we add 1 to get the offset to the last 4 bytes. |
| 1711 Address offset_address = | 1712 Address offset_address = |
| 1712 mov_instruction_address + delta + kOffsetToLoadInstruction + 1; | 1713 mov_instruction_address + delta + kOffsetToLoadInstruction + 1; |
| 1713 *reinterpret_cast<Object**>(offset_address) = cell; | 1714 *reinterpret_cast<Object**>(offset_address) = cell; |
| 1714 return true; | 1715 return true; |
| 1715 } | 1716 } |
| 1716 | 1717 |
| 1717 | 1718 |
| 1718 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | 1719 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
| 1720 if (V8::UseCrankshaft()) return false; |
| 1721 |
| 1719 // The address of the instruction following the call. | 1722 // The address of the instruction following the call. |
| 1720 Address test_instruction_address = | 1723 Address test_instruction_address = |
| 1721 address + Assembler::kCallTargetAddressOffset; | 1724 address + Assembler::kCallTargetAddressOffset; |
| 1722 | 1725 |
| 1723 // If the instruction following the call is not a test eax, nothing | 1726 // If the instruction following the call is not a test eax, nothing |
| 1724 // was inlined. | 1727 // was inlined. |
| 1725 if (*test_instruction_address != kTestEaxByte) return false; | 1728 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1726 | 1729 |
| 1727 // Extract the encoded deltas from the test eax instruction. | 1730 // Extract the encoded deltas from the test eax instruction. |
| 1728 Address encoded_offsets_address = test_instruction_address + 1; | 1731 Address encoded_offsets_address = test_instruction_address + 1; |
| 1729 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); | 1732 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
| 1730 int delta_to_map_check = -(encoded_offsets & 0xFFFF); | 1733 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
| 1731 int delta_to_record_write = encoded_offsets >> 16; | 1734 int delta_to_record_write = encoded_offsets >> 16; |
| 1732 | 1735 |
| 1733 // Patch the map to check. The map address is the last 4 bytes of | 1736 // Patch the map to check. The map address is the last 4 bytes of |
| 1734 // the 7-byte operand-immediate compare instruction. | 1737 // the 7-byte operand-immediate compare instruction. |
| 1735 Address map_check_address = test_instruction_address + delta_to_map_check; | 1738 Address map_check_address = test_instruction_address + delta_to_map_check; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1755 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || | 1758 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
| 1756 *reinterpret_cast<int*>(offset_address) == -1 || | 1759 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1757 (offset == 0 && map == HEAP->null_value())); | 1760 (offset == 0 && map == HEAP->null_value())); |
| 1758 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1761 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1759 | 1762 |
| 1760 return true; | 1763 return true; |
| 1761 } | 1764 } |
| 1762 | 1765 |
| 1763 | 1766 |
| 1764 static bool PatchInlinedMapCheck(Address address, Object* map) { | 1767 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 1768 if (V8::UseCrankshaft()) return false; |
| 1769 |
| 1765 Address test_instruction_address = | 1770 Address test_instruction_address = |
| 1766 address + Assembler::kCallTargetAddressOffset; | 1771 address + Assembler::kCallTargetAddressOffset; |
| 1767 // The keyed load has a fast inlined case if the IC call instruction | 1772 // The keyed load has a fast inlined case if the IC call instruction |
| 1768 // is immediately followed by a test instruction. | 1773 // is immediately followed by a test instruction. |
| 1769 if (*test_instruction_address != kTestEaxByte) return false; | 1774 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1770 | 1775 |
| 1771 // Fetch the offset from the test instruction to the map cmp | 1776 // Fetch the offset from the test instruction to the map cmp |
| 1772 // instruction. This offset is stored in the last 4 bytes of the 5 | 1777 // instruction. This offset is stored in the last 4 bytes of the 5 |
| 1773 // byte test instruction. | 1778 // byte test instruction. |
| 1774 Address delta_address = test_instruction_address + 1; | 1779 Address delta_address = test_instruction_address + 1; |
| 1775 int delta = *reinterpret_cast<int*>(delta_address); | 1780 int delta = *reinterpret_cast<int*>(delta_address); |
| 1776 // Compute the map address. The map address is in the last 4 bytes | 1781 // Compute the map address. The map address is in the last 4 bytes |
| 1777 // of the 7-byte operand-immediate compare instruction, so we add 3 | 1782 // of the 7-byte operand-immediate compare instruction, so we add 3 |
| 1778 // to the offset to get the map address. | 1783 // to the offset to get the map address. |
| 1779 Address map_address = test_instruction_address + delta + 3; | 1784 Address map_address = test_instruction_address + delta + 3; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 | 1961 |
| 1957 __ bind(&restore_miss); | 1962 __ bind(&restore_miss); |
| 1958 __ pop(edx); | 1963 __ pop(edx); |
| 1959 | 1964 |
| 1960 __ bind(&miss); | 1965 __ bind(&miss); |
| 1961 __ IncrementCounter(COUNTERS->store_normal_miss(), 1); | 1966 __ IncrementCounter(COUNTERS->store_normal_miss(), 1); |
| 1962 GenerateMiss(masm); | 1967 GenerateMiss(masm); |
| 1963 } | 1968 } |
| 1964 | 1969 |
| 1965 | 1970 |
| 1971 void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) { |
| 1972 // ----------- S t a t e ------------- |
| 1973 // -- eax : value |
| 1974 // -- ecx : name |
| 1975 // -- edx : receiver |
| 1976 // -- esp[0] : return address |
| 1977 // ----------------------------------- |
| 1978 __ pop(ebx); |
| 1979 __ push(edx); |
| 1980 __ push(ecx); |
| 1981 __ push(eax); |
| 1982 __ push(ebx); |
| 1983 |
| 1984 // Do tail-call to runtime routine. |
| 1985 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1986 } |
| 1987 |
| 1988 |
| 1966 // Defined in ic.cc. | 1989 // Defined in ic.cc. |
| 1967 Object* KeyedStoreIC_Miss(Arguments args); | 1990 Object* KeyedStoreIC_Miss(Arguments args); |
| 1968 | 1991 |
| 1969 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1992 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1970 // ----------- S t a t e ------------- | 1993 // ----------- S t a t e ------------- |
| 1971 // -- eax : value | 1994 // -- eax : value |
| 1972 // -- ecx : key | 1995 // -- ecx : key |
| 1973 // -- edx : receiver | 1996 // -- edx : receiver |
| 1974 // -- esp[0] : return address | 1997 // -- esp[0] : return address |
| 1975 // ----------------------------------- | 1998 // ----------------------------------- |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1997 __ push(edx); | 2020 __ push(edx); |
| 1998 __ push(ecx); | 2021 __ push(ecx); |
| 1999 __ push(eax); | 2022 __ push(eax); |
| 2000 __ push(ebx); | 2023 __ push(ebx); |
| 2001 | 2024 |
| 2002 // Do tail-call to runtime routine. | 2025 // Do tail-call to runtime routine. |
| 2003 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 2026 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 2004 __ TailCallExternalReference(ref, 3, 1); | 2027 __ TailCallExternalReference(ref, 3, 1); |
| 2005 } | 2028 } |
| 2006 | 2029 |
| 2030 |
| 2007 #undef __ | 2031 #undef __ |
| 2008 | 2032 |
| 2009 | 2033 |
| 2034 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 2035 switch (op) { |
| 2036 case Token::EQ_STRICT: |
| 2037 case Token::EQ: |
| 2038 return equal; |
| 2039 case Token::LT: |
| 2040 return less; |
| 2041 case Token::GT: |
| 2042 // Reverse left and right operands to obtain ECMA-262 conversion order. |
| 2043 return less; |
| 2044 case Token::LTE: |
| 2045 // Reverse left and right operands to obtain ECMA-262 conversion order. |
| 2046 return greater_equal; |
| 2047 case Token::GTE: |
| 2048 return greater_equal; |
| 2049 default: |
| 2050 UNREACHABLE(); |
| 2051 return no_condition; |
| 2052 } |
| 2053 } |
| 2054 |
| 2055 |
| 2056 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { |
| 2057 HandleScope scope; |
| 2058 Handle<Code> rewritten; |
| 2059 #ifdef DEBUG |
| 2060 State previous_state = GetState(); |
| 2061 #endif |
| 2062 State state = TargetState(x, y); |
| 2063 if (state == GENERIC) { |
| 2064 CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS); |
| 2065 rewritten = stub.GetCode(); |
| 2066 } else { |
| 2067 ICCompareStub stub(op_, state); |
| 2068 rewritten = stub.GetCode(); |
| 2069 } |
| 2070 set_target(*rewritten); |
| 2071 |
| 2072 #ifdef DEBUG |
| 2073 if (FLAG_trace_ic) { |
| 2074 PrintF("[CompareIC (%s->%s)#%s]\n", |
| 2075 GetStateName(previous_state), |
| 2076 GetStateName(state), |
| 2077 Token::Name(op_)); |
| 2078 } |
| 2079 #endif |
| 2080 } |
| 2081 |
| 2082 |
| 2010 } } // namespace v8::internal | 2083 } } // namespace v8::internal |
| 2011 | 2084 |
| 2012 #endif // V8_TARGET_ARCH_IA32 | 2085 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |