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 |