| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1612 DCHECK(kind() == Code::KEYED_STORE_IC); | 1612 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 1613 if (strict_mode() == STRICT) { | 1613 if (strict_mode() == STRICT) { |
| 1614 return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); | 1614 return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); |
| 1615 } else { | 1615 } else { |
| 1616 return isolate()->builtins()->KeyedStoreIC_Megamorphic(); | 1616 return isolate()->builtins()->KeyedStoreIC_Megamorphic(); |
| 1617 } | 1617 } |
| 1618 } | 1618 } |
| 1619 } | 1619 } |
| 1620 | 1620 |
| 1621 | 1621 |
| 1622 Handle<Code> StoreIC::generic_stub() const { | |
| 1623 if (kind() == Code::STORE_IC) { | |
| 1624 return PropertyICCompiler::ComputeStore(isolate(), GENERIC, | |
| 1625 extra_ic_state()); | |
| 1626 } else { | |
| 1627 DCHECK(kind() == Code::KEYED_STORE_IC); | |
| 1628 if (strict_mode() == STRICT) { | |
| 1629 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); | |
| 1630 } else { | |
| 1631 return isolate()->builtins()->KeyedStoreIC_Generic(); | |
| 1632 } | |
| 1633 } | |
| 1634 } | |
| 1635 | |
| 1636 | |
| 1637 Handle<Code> StoreIC::slow_stub() const { | 1622 Handle<Code> StoreIC::slow_stub() const { |
| 1638 if (kind() == Code::STORE_IC) { | 1623 if (kind() == Code::STORE_IC) { |
| 1639 return isolate()->builtins()->StoreIC_Slow(); | 1624 return isolate()->builtins()->StoreIC_Slow(); |
| 1640 } else { | 1625 } else { |
| 1641 DCHECK(kind() == Code::KEYED_STORE_IC); | 1626 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 1642 return isolate()->builtins()->KeyedStoreIC_Slow(); | 1627 return isolate()->builtins()->KeyedStoreIC_Slow(); |
| 1643 } | 1628 } |
| 1644 } | 1629 } |
| 1645 | 1630 |
| 1646 | 1631 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1794 | 1779 |
| 1795 | 1780 |
| 1796 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1781 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
| 1797 KeyedAccessStoreMode store_mode) { | 1782 KeyedAccessStoreMode store_mode) { |
| 1798 // Don't handle megamorphic property accesses for INTERCEPTORS or | 1783 // Don't handle megamorphic property accesses for INTERCEPTORS or |
| 1799 // ACCESSOR_CONSTANT | 1784 // ACCESSOR_CONSTANT |
| 1800 // via megamorphic stubs, since they don't have a map in their relocation info | 1785 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1801 // and so the stubs can't be harvested for the object needed for a map check. | 1786 // and so the stubs can't be harvested for the object needed for a map check. |
| 1802 if (target()->type() != Code::NORMAL) { | 1787 if (target()->type() != Code::NORMAL) { |
| 1803 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); | 1788 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); |
| 1804 return generic_stub(); | 1789 return megamorphic_stub(); |
| 1805 } | 1790 } |
| 1806 | 1791 |
| 1807 Handle<Map> receiver_map(receiver->map(), isolate()); | 1792 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1808 MapHandleList target_receiver_maps; | 1793 MapHandleList target_receiver_maps; |
| 1809 TargetMaps(&target_receiver_maps); | 1794 TargetMaps(&target_receiver_maps); |
| 1810 if (target_receiver_maps.length() == 0) { | 1795 if (target_receiver_maps.length() == 0) { |
| 1811 Handle<Map> monomorphic_map = | 1796 Handle<Map> monomorphic_map = |
| 1812 ComputeTransitionedMap(receiver_map, store_mode); | 1797 ComputeTransitionedMap(receiver_map, store_mode); |
| 1813 store_mode = GetNonTransitioningStoreMode(store_mode); | 1798 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1814 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1799 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 | 1843 |
| 1859 if (IsTransitionStoreMode(store_mode)) { | 1844 if (IsTransitionStoreMode(store_mode)) { |
| 1860 Handle<Map> transitioned_receiver_map = | 1845 Handle<Map> transitioned_receiver_map = |
| 1861 ComputeTransitionedMap(receiver_map, store_mode); | 1846 ComputeTransitionedMap(receiver_map, store_mode); |
| 1862 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1847 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
| 1863 transitioned_receiver_map); | 1848 transitioned_receiver_map); |
| 1864 } | 1849 } |
| 1865 | 1850 |
| 1866 if (!map_added) { | 1851 if (!map_added) { |
| 1867 // If the miss wasn't due to an unseen map, a polymorphic stub | 1852 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1868 // won't help. In theory we should use the generic stub, but in | 1853 // won't help, use the megamorphic stub which can handle everything. |
| 1869 // practice there are a number of hard-to-avoid reasons why this | |
| 1870 // can happen occasionally, and where the additional logic in the | |
| 1871 // megamorphic stub is beneficial because it can handle most cases | |
| 1872 // without calling into the runtime. | |
| 1873 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice"); | 1854 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice"); |
| 1874 return megamorphic_stub(); | 1855 return megamorphic_stub(); |
| 1875 } | 1856 } |
| 1876 | 1857 |
| 1877 // If the maximum number of receiver maps has been exceeded, use the | 1858 // If the maximum number of receiver maps has been exceeded, use the |
| 1878 // megamorphic version of the IC. | 1859 // megamorphic version of the IC. |
| 1879 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1860 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1880 return megamorphic_stub(); | 1861 return megamorphic_stub(); |
| 1881 } | 1862 } |
| 1882 | 1863 |
| 1883 // Make sure all polymorphic handlers have the same store mode, otherwise the | 1864 // Make sure all polymorphic handlers have the same store mode, otherwise the |
| 1884 // generic stub must be used. | 1865 // megamorphic stub must be used. |
| 1885 store_mode = GetNonTransitioningStoreMode(store_mode); | 1866 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1886 if (old_store_mode != STANDARD_STORE) { | 1867 if (old_store_mode != STANDARD_STORE) { |
| 1887 if (store_mode == STANDARD_STORE) { | 1868 if (store_mode == STANDARD_STORE) { |
| 1888 store_mode = old_store_mode; | 1869 store_mode = old_store_mode; |
| 1889 } else if (store_mode != old_store_mode) { | 1870 } else if (store_mode != old_store_mode) { |
| 1890 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch"); | 1871 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch"); |
| 1891 return generic_stub(); | 1872 return megamorphic_stub(); |
| 1892 } | 1873 } |
| 1893 } | 1874 } |
| 1894 | 1875 |
| 1895 // If the store mode isn't the standard mode, make sure that all polymorphic | 1876 // If the store mode isn't the standard mode, make sure that all polymorphic |
| 1896 // receivers are either external arrays, or all "normal" arrays. Otherwise, | 1877 // receivers are either external arrays, or all "normal" arrays. Otherwise, |
| 1897 // use the generic stub. | 1878 // use the megamorphic stub. |
| 1898 if (store_mode != STANDARD_STORE) { | 1879 if (store_mode != STANDARD_STORE) { |
| 1899 int external_arrays = 0; | 1880 int external_arrays = 0; |
| 1900 for (int i = 0; i < target_receiver_maps.length(); ++i) { | 1881 for (int i = 0; i < target_receiver_maps.length(); ++i) { |
| 1901 if (target_receiver_maps[i]->has_external_array_elements() || | 1882 if (target_receiver_maps[i]->has_external_array_elements() || |
| 1902 target_receiver_maps[i]->has_fixed_typed_array_elements()) { | 1883 target_receiver_maps[i]->has_fixed_typed_array_elements()) { |
| 1903 external_arrays++; | 1884 external_arrays++; |
| 1904 } | 1885 } |
| 1905 } | 1886 } |
| 1906 if (external_arrays != 0 && | 1887 if (external_arrays != 0 && |
| 1907 external_arrays != target_receiver_maps.length()) { | 1888 external_arrays != target_receiver_maps.length()) { |
| 1908 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 1889 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 1909 "unsupported combination of external and normal arrays"); | 1890 "unsupported combination of external and normal arrays"); |
| 1910 return generic_stub(); | 1891 return megamorphic_stub(); |
| 1911 } | 1892 } |
| 1912 } | 1893 } |
| 1913 | 1894 |
| 1914 return PropertyICCompiler::ComputeKeyedStorePolymorphic( | 1895 return PropertyICCompiler::ComputeKeyedStorePolymorphic( |
| 1915 &target_receiver_maps, store_mode, strict_mode()); | 1896 &target_receiver_maps, store_mode, strict_mode()); |
| 1916 } | 1897 } |
| 1917 | 1898 |
| 1918 | 1899 |
| 1919 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 1900 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
| 1920 Handle<Map> map, KeyedAccessStoreMode store_mode) { | 1901 Handle<Map> map, KeyedAccessStoreMode store_mode) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2045 value, strict_mode()), | 2026 value, strict_mode()), |
| 2046 Object); | 2027 Object); |
| 2047 return result; | 2028 return result; |
| 2048 } | 2029 } |
| 2049 | 2030 |
| 2050 // Check for non-string values that can be converted into an | 2031 // Check for non-string values that can be converted into an |
| 2051 // internalized string directly or is representable as a smi. | 2032 // internalized string directly or is representable as a smi. |
| 2052 key = TryConvertKey(key, isolate()); | 2033 key = TryConvertKey(key, isolate()); |
| 2053 | 2034 |
| 2054 Handle<Object> store_handle; | 2035 Handle<Object> store_handle; |
| 2055 Handle<Code> stub = generic_stub(); | 2036 Handle<Code> stub = megamorphic_stub(); |
| 2056 | 2037 |
| 2057 if (key->IsInternalizedString()) { | 2038 if (key->IsInternalizedString()) { |
| 2058 ASSIGN_RETURN_ON_EXCEPTION( | 2039 ASSIGN_RETURN_ON_EXCEPTION( |
| 2059 isolate(), store_handle, | 2040 isolate(), store_handle, |
| 2060 StoreIC::Store(object, Handle<String>::cast(key), value, | 2041 StoreIC::Store(object, Handle<String>::cast(key), value, |
| 2061 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 2042 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
| 2062 Object); | 2043 Object); |
| 2063 if (!is_target_set()) { | 2044 if (!is_target_set()) { |
| 2064 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2045 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2065 "unhandled internalized string key"); | 2046 "unhandled internalized string key"); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 | 2100 |
| 2120 if (store_handle.is_null()) { | 2101 if (store_handle.is_null()) { |
| 2121 ASSIGN_RETURN_ON_EXCEPTION( | 2102 ASSIGN_RETURN_ON_EXCEPTION( |
| 2122 isolate(), store_handle, | 2103 isolate(), store_handle, |
| 2123 Runtime::SetObjectProperty(isolate(), object, key, value, | 2104 Runtime::SetObjectProperty(isolate(), object, key, value, |
| 2124 strict_mode()), | 2105 strict_mode()), |
| 2125 Object); | 2106 Object); |
| 2126 } | 2107 } |
| 2127 | 2108 |
| 2128 DCHECK(!is_target_set()); | 2109 DCHECK(!is_target_set()); |
| 2129 Code* generic = *generic_stub(); | 2110 Code* megamorphic = *megamorphic_stub(); |
| 2130 if (*stub == generic) { | 2111 if (*stub == megamorphic) { |
| 2131 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 2112 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
| 2132 } | 2113 } |
| 2133 if (*stub == *slow_stub()) { | 2114 if (*stub == *slow_stub()) { |
| 2134 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); | 2115 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
| 2135 } | 2116 } |
| 2136 DCHECK(!stub.is_null()); | 2117 DCHECK(!stub.is_null()); |
| 2137 set_target(*stub); | 2118 set_target(*stub); |
| 2138 TRACE_IC("StoreIC", key); | 2119 TRACE_IC("StoreIC", key); |
| 2139 | 2120 |
| 2140 return store_handle; | 2121 return store_handle; |
| 2141 } | 2122 } |
| 2142 | 2123 |
| 2143 | 2124 |
| 2144 // static | |
| 2145 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | |
| 2146 StrictMode strict_mode) { | |
| 2147 PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); | |
| 2148 } | |
| 2149 | |
| 2150 | |
| 2151 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, | 2125 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, |
| 2152 const CallICState& callic_state) { | 2126 const CallICState& callic_state) { |
| 2153 DCHECK(FLAG_use_ic && function->IsJSFunction()); | 2127 DCHECK(FLAG_use_ic && function->IsJSFunction()); |
| 2154 | 2128 |
| 2155 // Are we the array function? | 2129 // Are we the array function? |
| 2156 Handle<JSFunction> array_function = | 2130 Handle<JSFunction> array_function = |
| 2157 Handle<JSFunction>(isolate()->native_context()->array_function()); | 2131 Handle<JSFunction>(isolate()->native_context()->array_function()); |
| 2158 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { | 2132 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { |
| 2159 // Alter the slot. | 2133 // Alter the slot. |
| 2160 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2134 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
| (...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2995 static const Address IC_utilities[] = { | 2969 static const Address IC_utilities[] = { |
| 2996 #define ADDR(name) FUNCTION_ADDR(name), | 2970 #define ADDR(name) FUNCTION_ADDR(name), |
| 2997 IC_UTIL_LIST(ADDR) NULL | 2971 IC_UTIL_LIST(ADDR) NULL |
| 2998 #undef ADDR | 2972 #undef ADDR |
| 2999 }; | 2973 }; |
| 3000 | 2974 |
| 3001 | 2975 |
| 3002 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2976 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3003 } | 2977 } |
| 3004 } // namespace v8::internal | 2978 } // namespace v8::internal |
| OLD | NEW |