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 |