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/ic/ic.h" | 5 #include "src/ic/ic.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 1833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1844 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 1844 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
1845 case LookupIterator::ACCESS_CHECK: | 1845 case LookupIterator::ACCESS_CHECK: |
1846 case LookupIterator::JSPROXY: | 1846 case LookupIterator::JSPROXY: |
1847 case LookupIterator::NOT_FOUND: | 1847 case LookupIterator::NOT_FOUND: |
1848 UNREACHABLE(); | 1848 UNREACHABLE(); |
1849 } | 1849 } |
1850 return slow_stub(); | 1850 return slow_stub(); |
1851 } | 1851 } |
1852 | 1852 |
1853 | 1853 |
1854 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1854 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map, |
1855 KeyedAccessStoreMode store_mode) { | 1855 KeyedAccessStoreMode store_mode) { |
1856 // Don't handle megamorphic property accesses for INTERCEPTORS or | 1856 // Don't handle megamorphic property accesses for INTERCEPTORS or |
1857 // ACCESSOR_CONSTANT | 1857 // ACCESSOR_CONSTANT |
1858 // via megamorphic stubs, since they don't have a map in their relocation info | 1858 // via megamorphic stubs, since they don't have a map in their relocation info |
1859 // and so the stubs can't be harvested for the object needed for a map check. | 1859 // and so the stubs can't be harvested for the object needed for a map check. |
1860 if (target()->type() != Code::NORMAL) { | 1860 if (target()->type() != Code::NORMAL) { |
1861 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); | 1861 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); |
1862 return megamorphic_stub(); | 1862 return megamorphic_stub(); |
1863 } | 1863 } |
1864 | 1864 |
1865 Handle<Map> receiver_map(receiver->map(), isolate()); | |
1866 MapHandleList target_receiver_maps; | 1865 MapHandleList target_receiver_maps; |
1867 TargetMaps(&target_receiver_maps); | 1866 TargetMaps(&target_receiver_maps); |
1868 if (target_receiver_maps.length() == 0) { | 1867 if (target_receiver_maps.length() == 0) { |
1869 Handle<Map> monomorphic_map = | 1868 Handle<Map> monomorphic_map = |
1870 ComputeTransitionedMap(receiver_map, store_mode); | 1869 ComputeTransitionedMap(receiver_map, store_mode); |
1871 store_mode = GetNonTransitioningStoreMode(store_mode); | 1870 store_mode = GetNonTransitioningStoreMode(store_mode); |
1872 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1871 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1873 monomorphic_map, language_mode(), store_mode); | 1872 monomorphic_map, language_mode(), store_mode); |
1874 } | 1873 } |
1875 | 1874 |
(...skipping 13 matching lines...) Expand all Loading... |
1889 if ((receiver_map.is_identical_to(previous_receiver_map) && | 1888 if ((receiver_map.is_identical_to(previous_receiver_map) && |
1890 IsTransitionStoreMode(store_mode)) || | 1889 IsTransitionStoreMode(store_mode)) || |
1891 IsTransitionOfMonomorphicTarget(*previous_receiver_map, | 1890 IsTransitionOfMonomorphicTarget(*previous_receiver_map, |
1892 *transitioned_receiver_map)) { | 1891 *transitioned_receiver_map)) { |
1893 // If the "old" and "new" maps are in the same elements map family, or | 1892 // If the "old" and "new" maps are in the same elements map family, or |
1894 // if they at least come from the same origin for a transitioning store, | 1893 // if they at least come from the same origin for a transitioning store, |
1895 // stay MONOMORPHIC and use the map for the most generic ElementsKind. | 1894 // stay MONOMORPHIC and use the map for the most generic ElementsKind. |
1896 store_mode = GetNonTransitioningStoreMode(store_mode); | 1895 store_mode = GetNonTransitioningStoreMode(store_mode); |
1897 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1896 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1898 transitioned_receiver_map, language_mode(), store_mode); | 1897 transitioned_receiver_map, language_mode(), store_mode); |
1899 } else if (*previous_receiver_map == receiver->map() && | 1898 } else if (receiver_map.is_identical_to(previous_receiver_map) && |
1900 old_store_mode == STANDARD_STORE && | 1899 old_store_mode == STANDARD_STORE && |
1901 (store_mode == STORE_AND_GROW_NO_TRANSITION || | 1900 (store_mode == STORE_AND_GROW_NO_TRANSITION || |
1902 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1901 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1903 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1902 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1904 // A "normal" IC that handles stores can switch to a version that can | 1903 // A "normal" IC that handles stores can switch to a version that can |
1905 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1904 // grow at the end of the array, handle OOB accesses or copy COW arrays |
1906 // and still stay MONOMORPHIC. | 1905 // and still stay MONOMORPHIC. |
1907 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1906 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1908 receiver_map, language_mode(), store_mode); | 1907 receiver_map, language_mode(), store_mode); |
1909 } | 1908 } |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 // Don't use ICs for maps of the objects in Array's prototype chain. We | 2152 // Don't use ICs for maps of the objects in Array's prototype chain. We |
2154 // expect to be able to trap element sets to objects with those maps in | 2153 // expect to be able to trap element sets to objects with those maps in |
2155 // the runtime to enable optimization of element hole access. | 2154 // the runtime to enable optimization of element hole access. |
2156 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 2155 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
2157 if (heap_object->map()->IsMapInArrayPrototypeChain()) { | 2156 if (heap_object->map()->IsMapInArrayPrototypeChain()) { |
2158 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); | 2157 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); |
2159 use_ic = false; | 2158 use_ic = false; |
2160 } | 2159 } |
2161 } | 2160 } |
2162 | 2161 |
| 2162 Handle<Map> old_receiver_map; |
| 2163 bool sloppy_arguments_elements = false; |
| 2164 bool key_is_valid_index = false; |
| 2165 KeyedAccessStoreMode store_mode = STANDARD_STORE; |
| 2166 if (use_ic && object->IsJSObject()) { |
| 2167 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 2168 old_receiver_map = handle(receiver->map(), isolate()); |
| 2169 sloppy_arguments_elements = |
| 2170 !is_sloppy(language_mode()) && |
| 2171 receiver->elements()->map() == |
| 2172 isolate()->heap()->sloppy_arguments_elements_map(); |
| 2173 if (!sloppy_arguments_elements) { |
| 2174 key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0; |
| 2175 if (key_is_valid_index) { |
| 2176 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
| 2177 store_mode = GetStoreMode(receiver, index, value); |
| 2178 } |
| 2179 } |
| 2180 } |
| 2181 |
| 2182 DCHECK(store_handle.is_null()); |
| 2183 ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle, |
| 2184 Runtime::SetObjectProperty(isolate(), object, key, |
| 2185 value, language_mode()), |
| 2186 Object); |
| 2187 |
2163 if (use_ic) { | 2188 if (use_ic) { |
2164 if (object->IsJSObject()) { | 2189 if (!old_receiver_map.is_null()) { |
2165 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2190 if (sloppy_arguments_elements) { |
2166 if (receiver->elements()->map() == | |
2167 isolate()->heap()->sloppy_arguments_elements_map() && | |
2168 !is_sloppy(language_mode())) { | |
2169 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); | 2191 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
2170 } else if (key->IsSmi() && Smi::cast(*key)->value() >= 0) { | 2192 } else if (key_is_valid_index) { |
2171 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); | |
2172 // We should go generic if receiver isn't a dictionary, but our | 2193 // We should go generic if receiver isn't a dictionary, but our |
2173 // prototype chain does have dictionary elements. This ensures that | 2194 // prototype chain does have dictionary elements. This ensures that |
2174 // other non-dictionary receivers in the polymorphic case benefit | 2195 // other non-dictionary receivers in the polymorphic case benefit |
2175 // from fast path keyed stores. | 2196 // from fast path keyed stores. |
2176 if (!receiver->map()->DictionaryElementsInPrototypeChainOnly()) { | 2197 if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) { |
2177 KeyedAccessStoreMode store_mode = | 2198 stub = StoreElementStub(old_receiver_map, store_mode); |
2178 GetStoreMode(receiver, index, value); | |
2179 stub = StoreElementStub(receiver, store_mode); | |
2180 | 2199 |
2181 // Validate that the store_mode in the stub can also be derived | 2200 // Validate that the store_mode in the stub can also be derived |
2182 // from peeking in the code bits of the handlers. | 2201 // from peeking in the code bits of the handlers. |
2183 ValidateStoreMode(stub); | 2202 ValidateStoreMode(stub); |
2184 } else { | 2203 } else { |
2185 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); | 2204 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); |
2186 } | 2205 } |
2187 } else { | 2206 } else { |
2188 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); | 2207 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
2189 } | 2208 } |
2190 } else { | 2209 } else { |
2191 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); | 2210 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
2192 } | 2211 } |
2193 } | 2212 } |
2194 | 2213 |
2195 if (store_handle.is_null()) { | |
2196 ASSIGN_RETURN_ON_EXCEPTION( | |
2197 isolate(), store_handle, | |
2198 Runtime::SetObjectProperty(isolate(), object, key, value, | |
2199 language_mode()), | |
2200 Object); | |
2201 } | |
2202 | |
2203 if (FLAG_vector_stores) { | 2214 if (FLAG_vector_stores) { |
2204 if (!is_vector_set() || stub.is_null()) { | 2215 if (!is_vector_set() || stub.is_null()) { |
2205 Code* megamorphic = *megamorphic_stub(); | 2216 Code* megamorphic = *megamorphic_stub(); |
2206 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { | 2217 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { |
2207 ConfigureVectorState(MEGAMORPHIC); | 2218 ConfigureVectorState(MEGAMORPHIC); |
2208 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2219 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
2209 *stub == megamorphic ? "set generic" : "slow stub"); | 2220 *stub == megamorphic ? "set generic" : "slow stub"); |
2210 } | 2221 } |
2211 } | 2222 } |
2212 } else { | 2223 } else { |
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3120 KeyedLoadICNexus nexus(vector, vector_slot); | 3131 KeyedLoadICNexus nexus(vector, vector_slot); |
3121 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 3132 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
3122 ic.UpdateState(receiver, key); | 3133 ic.UpdateState(receiver, key); |
3123 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 3134 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
3124 } | 3135 } |
3125 | 3136 |
3126 return *result; | 3137 return *result; |
3127 } | 3138 } |
3128 } // namespace internal | 3139 } // namespace internal |
3129 } // namespace v8 | 3140 } // namespace v8 |
OLD | NEW |