| 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 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1395 // internalized string directly or is representable as a smi. | 1395 // internalized string directly or is representable as a smi. |
| 1396 key = TryConvertKey(key, isolate()); | 1396 key = TryConvertKey(key, isolate()); |
| 1397 | 1397 |
| 1398 if (key->IsInternalizedString() || key->IsSymbol()) { | 1398 if (key->IsInternalizedString() || key->IsSymbol()) { |
| 1399 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, | 1399 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, |
| 1400 LoadIC::Load(object, Handle<Name>::cast(key)), | 1400 LoadIC::Load(object, Handle<Name>::cast(key)), |
| 1401 Object); | 1401 Object); |
| 1402 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1402 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1403 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1403 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
| 1404 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1404 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1405 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1405 if (object->IsString() || key->IsSmi()) stub = LoadElementStub(receiver); |
| 1406 stub = LoadElementStub(receiver); | |
| 1407 } | |
| 1408 } | 1406 } |
| 1409 } | 1407 } |
| 1410 | 1408 |
| 1411 DCHECK(UseVector()); | 1409 DCHECK(UseVector()); |
| 1412 if (!is_vector_set() || stub.is_null()) { | 1410 if (!is_vector_set() || stub.is_null()) { |
| 1413 Code* generic = *megamorphic_stub(); | 1411 Code* generic = *megamorphic_stub(); |
| 1414 if (!stub.is_null() && *stub == generic) { | 1412 if (!stub.is_null() && *stub == generic) { |
| 1415 ConfigureVectorState(MEGAMORPHIC); | 1413 ConfigureVectorState(MEGAMORPHIC); |
| 1416 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1414 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1417 } | 1415 } |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1987 case STORE_NO_TRANSITION_HANDLE_COW: | 1985 case STORE_NO_TRANSITION_HANDLE_COW: |
| 1988 case STANDARD_STORE: | 1986 case STANDARD_STORE: |
| 1989 case STORE_AND_GROW_NO_TRANSITION: | 1987 case STORE_AND_GROW_NO_TRANSITION: |
| 1990 return map; | 1988 return map; |
| 1991 } | 1989 } |
| 1992 UNREACHABLE(); | 1990 UNREACHABLE(); |
| 1993 return MaybeHandle<Map>().ToHandleChecked(); | 1991 return MaybeHandle<Map>().ToHandleChecked(); |
| 1994 } | 1992 } |
| 1995 | 1993 |
| 1996 | 1994 |
| 1997 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, int index) { | 1995 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) { |
| 1996 uint32_t length = 0; |
| 1998 if (receiver->IsJSArray()) { | 1997 if (receiver->IsJSArray()) { |
| 1999 return JSArray::cast(*receiver)->length()->IsSmi() && | 1998 JSArray::cast(*receiver)->length()->ToArrayLength(&length); |
| 2000 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); | 1999 } else { |
| 2000 length = static_cast<uint32_t>(receiver->elements()->length()); |
| 2001 } | 2001 } |
| 2002 return index >= receiver->elements()->length(); | 2002 return index >= length; |
| 2003 } | 2003 } |
| 2004 | 2004 |
| 2005 | 2005 |
| 2006 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, | 2006 static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, |
| 2007 Handle<Object> key, | 2007 uint32_t index, Handle<Object> value) { |
| 2008 Handle<Object> value) { | |
| 2009 Handle<Smi> smi_key = Object::ToSmi(isolate(), key).ToHandleChecked(); | |
| 2010 int index = smi_key->value(); | |
| 2011 bool oob_access = IsOutOfBoundsAccess(receiver, index); | 2008 bool oob_access = IsOutOfBoundsAccess(receiver, index); |
| 2012 // Don't consider this a growing store if the store would send the receiver to | 2009 // Don't consider this a growing store if the store would send the receiver to |
| 2013 // dictionary mode. | 2010 // dictionary mode. |
| 2014 bool allow_growth = receiver->IsJSArray() && oob_access && | 2011 bool allow_growth = receiver->IsJSArray() && oob_access && |
| 2015 !receiver->WouldConvertToSlowElements(key); | 2012 !receiver->WouldConvertToSlowElements(index); |
| 2016 if (allow_growth) { | 2013 if (allow_growth) { |
| 2017 // Handle growing array in stub if necessary. | 2014 // Handle growing array in stub if necessary. |
| 2018 if (receiver->HasFastSmiElements()) { | 2015 if (receiver->HasFastSmiElements()) { |
| 2019 if (value->IsHeapNumber()) { | 2016 if (value->IsHeapNumber()) { |
| 2020 if (receiver->HasFastHoleyElements()) { | 2017 if (receiver->HasFastHoleyElements()) { |
| 2021 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; | 2018 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; |
| 2022 } else { | 2019 } else { |
| 2023 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; | 2020 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; |
| 2024 } | 2021 } |
| 2025 } | 2022 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2138 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 2135 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 2139 if (heap_object->map()->IsMapInArrayPrototypeChain()) { | 2136 if (heap_object->map()->IsMapInArrayPrototypeChain()) { |
| 2140 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); | 2137 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype"); |
| 2141 use_ic = false; | 2138 use_ic = false; |
| 2142 } | 2139 } |
| 2143 } | 2140 } |
| 2144 | 2141 |
| 2145 if (use_ic) { | 2142 if (use_ic) { |
| 2146 if (object->IsJSObject()) { | 2143 if (object->IsJSObject()) { |
| 2147 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2144 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 2148 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); | |
| 2149 if (receiver->elements()->map() == | 2145 if (receiver->elements()->map() == |
| 2150 isolate()->heap()->sloppy_arguments_elements_map() && | 2146 isolate()->heap()->sloppy_arguments_elements_map() && |
| 2151 !is_sloppy(language_mode())) { | 2147 !is_sloppy(language_mode())) { |
| 2152 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); | 2148 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
| 2153 } else if (key_is_smi_like) { | 2149 } else if (key->IsSmi() && Smi::cast(*key)->value() >= 0) { |
| 2150 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value()); |
| 2154 // We should go generic if receiver isn't a dictionary, but our | 2151 // We should go generic if receiver isn't a dictionary, but our |
| 2155 // prototype chain does have dictionary elements. This ensures that | 2152 // prototype chain does have dictionary elements. This ensures that |
| 2156 // other non-dictionary receivers in the polymorphic case benefit | 2153 // other non-dictionary receivers in the polymorphic case benefit |
| 2157 // from fast path keyed stores. | 2154 // from fast path keyed stores. |
| 2158 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 2155 if (!receiver->map()->DictionaryElementsInPrototypeChainOnly()) { |
| 2159 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2156 KeyedAccessStoreMode store_mode = |
| 2157 GetStoreMode(receiver, index, value); |
| 2160 stub = StoreElementStub(receiver, store_mode); | 2158 stub = StoreElementStub(receiver, store_mode); |
| 2161 } else { | 2159 } else { |
| 2162 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); | 2160 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); |
| 2163 } | 2161 } |
| 2164 } else { | 2162 } else { |
| 2165 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); | 2163 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
| 2166 } | 2164 } |
| 2167 } else { | 2165 } else { |
| 2168 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); | 2166 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
| 2169 } | 2167 } |
| (...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3090 static const Address IC_utilities[] = { | 3088 static const Address IC_utilities[] = { |
| 3091 #define ADDR(name) FUNCTION_ADDR(name), | 3089 #define ADDR(name) FUNCTION_ADDR(name), |
| 3092 IC_UTIL_LIST(ADDR) NULL | 3090 IC_UTIL_LIST(ADDR) NULL |
| 3093 #undef ADDR | 3091 #undef ADDR |
| 3094 }; | 3092 }; |
| 3095 | 3093 |
| 3096 | 3094 |
| 3097 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3095 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3098 } // namespace internal | 3096 } // namespace internal |
| 3099 } // namespace v8 | 3097 } // namespace v8 |
| OLD | NEW |