diff --git a/src/builtins/builtins-handler-gen.cc b/src/builtins/builtins-handler-gen.cc index 6f13c0b3ad..e7b947c483 100644 --- a/src/builtins/builtins-handler-gen.cc +++ b/src/builtins/builtins-handler-gen.cc @@ -243,17 +243,17 @@ TF_BUILTIN(ElementsTransitionAndStore_Standard, HandlerBuiltinsAssembler) { TF_BUILTIN(ElementsTransitionAndStore_GrowNoTransitionHandleCOW, HandlerBuiltinsAssembler) { - Generate_ElementsTransitionAndStore(STORE_AND_GROW_NO_TRANSITION_HANDLE_COW); + Generate_ElementsTransitionAndStore(STORE_AND_GROW_HANDLE_COW); } TF_BUILTIN(ElementsTransitionAndStore_NoTransitionIgnoreOOB, HandlerBuiltinsAssembler) { - Generate_ElementsTransitionAndStore(STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS); + Generate_ElementsTransitionAndStore(STORE_IGNORE_OUT_OF_BOUNDS); } TF_BUILTIN(ElementsTransitionAndStore_NoTransitionHandleCOW, HandlerBuiltinsAssembler) { - Generate_ElementsTransitionAndStore(STORE_NO_TRANSITION_HANDLE_COW); + Generate_ElementsTransitionAndStore(STORE_HANDLE_COW); } // All elements kinds handled by EmitElementStore. Specifically, this includes @@ -353,15 +353,15 @@ TF_BUILTIN(StoreFastElementIC_Standard, HandlerBuiltinsAssembler) { TF_BUILTIN(StoreFastElementIC_GrowNoTransitionHandleCOW, HandlerBuiltinsAssembler) { - Generate_StoreFastElementIC(STORE_AND_GROW_NO_TRANSITION_HANDLE_COW); + Generate_StoreFastElementIC(STORE_AND_GROW_HANDLE_COW); } TF_BUILTIN(StoreFastElementIC_NoTransitionIgnoreOOB, HandlerBuiltinsAssembler) { - Generate_StoreFastElementIC(STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS); + Generate_StoreFastElementIC(STORE_IGNORE_OUT_OF_BOUNDS); } TF_BUILTIN(StoreFastElementIC_NoTransitionHandleCOW, HandlerBuiltinsAssembler) { - Generate_StoreFastElementIC(STORE_NO_TRANSITION_HANDLE_COW); + Generate_StoreFastElementIC(STORE_HANDLE_COW); } TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) { diff --git a/src/codegen/code-factory.cc b/src/codegen/code-factory.cc index bda410464b..d48cc9933c 100644 --- a/src/codegen/code-factory.cc +++ b/src/codegen/code-factory.cc @@ -104,15 +104,15 @@ Callable CodeFactory::KeyedStoreIC_SloppyArguments(Isolate* isolate, case STANDARD_STORE: builtin_index = Builtins::kKeyedStoreIC_SloppyArguments_Standard; break; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: builtin_index = Builtins::kKeyedStoreIC_SloppyArguments_GrowNoTransitionHandleCOW; break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: builtin_index = Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB; break; - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: builtin_index = Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW; break; @@ -129,13 +129,13 @@ Callable CodeFactory::KeyedStoreIC_Slow(Isolate* isolate, case STANDARD_STORE: builtin_index = Builtins::kKeyedStoreIC_Slow_Standard; break; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: builtin_index = Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW; break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: builtin_index = Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB; break; - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: builtin_index = Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW; break; default: @@ -151,15 +151,15 @@ Callable CodeFactory::StoreInArrayLiteralIC_Slow(Isolate* isolate, case STANDARD_STORE: builtin_index = Builtins::kStoreInArrayLiteralIC_Slow_Standard; break; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: builtin_index = Builtins::kStoreInArrayLiteralIC_Slow_GrowNoTransitionHandleCOW; break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: builtin_index = Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB; break; - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: builtin_index = Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW; break; @@ -176,15 +176,15 @@ Callable CodeFactory::ElementsTransitionAndStore(Isolate* isolate, case STANDARD_STORE: builtin_index = Builtins::kElementsTransitionAndStore_Standard; break; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: builtin_index = Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW; break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: builtin_index = Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB; break; - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: builtin_index = Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW; break; @@ -201,13 +201,13 @@ Callable CodeFactory::StoreFastElementIC(Isolate* isolate, case STANDARD_STORE: builtin_index = Builtins::kStoreFastElementIC_Standard; break; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: builtin_index = Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW; break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: builtin_index = Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB; break; - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: builtin_index = Builtins::kStoreFastElementIC_NoTransitionHandleCOW; break; default: diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc index 8ac6a5929f..f924b38772 100644 --- a/src/codegen/code-stub-assembler.cc +++ b/src/codegen/code-stub-assembler.cc @@ -10609,7 +10609,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, // Bounds check. TNode length = LoadJSTypedArrayLength(CAST(object)); - if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { + if (store_mode == STORE_IGNORE_OUT_OF_BOUNDS) { // Skip the store if we write beyond the length or // to a property with a negative integer index. GotoIfNot(UintPtrLessThan(intptr_key, length), &done); diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc index da7060e69c..30f1386200 100644 --- a/src/compiler/js-native-context-specialization.cc +++ b/src/compiler/js-native-context-specialization.cc @@ -2618,7 +2618,7 @@ JSNativeContextSpecialization::BuildElementAccess( } if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS || - store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { + store_mode == STORE_IGNORE_OUT_OF_BOUNDS) { // Only check that the {index} is in SignedSmall range. We do the actual // bounds check below and just skip the property access if it's out of // bounds for the {receiver}. @@ -2702,7 +2702,7 @@ JSNativeContextSpecialization::BuildElementAccess( } // Check if we can skip the out-of-bounds store. - if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { + if (store_mode == STORE_IGNORE_OUT_OF_BOUNDS) { Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, length); Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), @@ -2995,7 +2995,7 @@ JSNativeContextSpecialization::BuildElementAccess( // Ensure that copy-on-write backing store is writable. if (IsSmiOrObjectElementsKind(elements_kind) && - store_mode == STORE_NO_TRANSITION_HANDLE_COW) { + store_mode == STORE_HANDLE_COW) { elements = effect = graph()->NewNode(simplified()->EnsureWritableFastElements(), receiver, elements, effect, control); @@ -3037,7 +3037,7 @@ JSNativeContextSpecialization::BuildElementAccess( // If we didn't grow {elements}, it might still be COW, in which case we // copy it now. if (IsSmiOrObjectElementsKind(elements_kind) && - store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW) { + store_mode == STORE_AND_GROW_HANDLE_COW) { elements = effect = graph()->NewNode(simplified()->EnsureWritableFastElements(), receiver, elements, effect, control); diff --git a/src/feedback-vector.cc b/src/feedback-vector.cc index dd2210c285..09910b680f 100644 --- a/src/feedback-vector.cc +++ b/src/feedback-vector.cc @@ -1153,19 +1153,19 @@ KeyedAccessStoreMode KeyedAccessStoreModeForBuiltin(int builtin_index) { case Builtins::kKeyedStoreIC_Slow_GrowNoTransitionHandleCOW: case Builtins::kStoreFastElementIC_GrowNoTransitionHandleCOW: case Builtins::kElementsTransitionAndStore_GrowNoTransitionHandleCOW: - return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW; + return STORE_AND_GROW_HANDLE_COW; case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionIgnoreOOB: case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionIgnoreOOB: case Builtins::kKeyedStoreIC_Slow_NoTransitionIgnoreOOB: case Builtins::kStoreFastElementIC_NoTransitionIgnoreOOB: case Builtins::kElementsTransitionAndStore_NoTransitionIgnoreOOB: - return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS; + return STORE_IGNORE_OUT_OF_BOUNDS; case Builtins::kKeyedStoreIC_SloppyArguments_NoTransitionHandleCOW: case Builtins::kStoreInArrayLiteralIC_Slow_NoTransitionHandleCOW: case Builtins::kKeyedStoreIC_Slow_NoTransitionHandleCOW: case Builtins::kStoreFastElementIC_NoTransitionHandleCOW: case Builtins::kElementsTransitionAndStore_NoTransitionHandleCOW: - return STORE_NO_TRANSITION_HANDLE_COW; + return STORE_HANDLE_COW; default: UNREACHABLE(); } diff --git a/src/globals.h b/src/globals.h index 21915b73d5..c5a1525404 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1504,55 +1504,20 @@ enum KeyedAccessLoadMode { enum KeyedAccessStoreMode { STANDARD_STORE, - STORE_TRANSITION_TO_OBJECT, - STORE_TRANSITION_TO_DOUBLE, - STORE_AND_GROW_NO_TRANSITION_HANDLE_COW, - STORE_AND_GROW_TRANSITION_TO_OBJECT, - STORE_AND_GROW_TRANSITION_TO_DOUBLE, - STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS, - STORE_NO_TRANSITION_HANDLE_COW + STORE_AND_GROW_HANDLE_COW, + STORE_IGNORE_OUT_OF_BOUNDS, + STORE_HANDLE_COW }; enum MutableMode { MUTABLE, IMMUTABLE }; -static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) { - return store_mode == STORE_TRANSITION_TO_OBJECT || - store_mode == STORE_TRANSITION_TO_DOUBLE || - store_mode == STORE_AND_GROW_TRANSITION_TO_OBJECT || - store_mode == STORE_AND_GROW_TRANSITION_TO_DOUBLE; -} - static inline bool IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode) { - return store_mode == STORE_NO_TRANSITION_HANDLE_COW || - store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW; -} - -static inline KeyedAccessStoreMode GetNonTransitioningStoreMode( - KeyedAccessStoreMode store_mode, bool receiver_was_cow) { - switch (store_mode) { - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: - case STORE_AND_GROW_TRANSITION_TO_OBJECT: - case STORE_AND_GROW_TRANSITION_TO_DOUBLE: - store_mode = STORE_AND_GROW_NO_TRANSITION_HANDLE_COW; - break; - case STANDARD_STORE: - case STORE_TRANSITION_TO_OBJECT: - case STORE_TRANSITION_TO_DOUBLE: - store_mode = - receiver_was_cow ? STORE_NO_TRANSITION_HANDLE_COW : STANDARD_STORE; - break; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: - case STORE_NO_TRANSITION_HANDLE_COW: - break; - } - DCHECK(!IsTransitionStoreMode(store_mode)); - DCHECK_IMPLIES(receiver_was_cow, IsCOWHandlingStoreMode(store_mode)); - return store_mode; + return store_mode == STORE_HANDLE_COW || + store_mode == STORE_AND_GROW_HANDLE_COW; } static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) { - return store_mode >= STORE_AND_GROW_NO_TRANSITION_HANDLE_COW && - store_mode <= STORE_AND_GROW_TRANSITION_TO_DOUBLE; + return store_mode == STORE_AND_GROW_HANDLE_COW; } enum IcCheckType { ELEMENT, PROPERTY }; diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 24d6754188..c536ecd55a 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -73,17 +73,16 @@ const char* GetModifier(KeyedAccessLoadMode mode) { const char* GetModifier(KeyedAccessStoreMode mode) { switch (mode) { - case STORE_NO_TRANSITION_HANDLE_COW: + case STORE_HANDLE_COW: return ".COW"; - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case STORE_AND_GROW_HANDLE_COW: return ".STORE+COW"; - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: + case STORE_IGNORE_OUT_OF_BOUNDS: return ".IGNORE_OOB"; - default: - break; + case STANDARD_STORE: + return ""; } - DCHECK(!IsCOWHandlingStoreMode(mode)); - return IsGrowStoreMode(mode) ? ".GROW" : ""; + UNREACHABLE(); } } // namespace @@ -1767,13 +1766,12 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) { void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, KeyedAccessStoreMode store_mode, - bool receiver_was_cow) { + TransitionMode transition_mode) { MapHandles target_receiver_maps; TargetMaps(&target_receiver_maps); if (target_receiver_maps.empty()) { Handle monomorphic_map = - ComputeTransitionedMap(receiver_map, store_mode); - store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow); + ComputeTransitionedMap(receiver_map, transition_mode); Handle handler = StoreElementHandler(monomorphic_map, store_mode); return ConfigureVectorState(Handle(), monomorphic_map, handler); } @@ -1787,26 +1785,21 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, } // There are several special cases where an IC that is MONOMORPHIC can still - // transition to a different GetNonTransitioningStoreMode IC that handles a - // superset of the original IC. Handle those here if the receiver map hasn't - // changed or it has transitioned to a more general kind. - KeyedAccessStoreMode old_store_mode; - old_store_mode = GetKeyedAccessStoreMode(); + // transition to a different IC that handles a superset of the original IC. + // Handle those here if the receiver map hasn't changed or it has transitioned + // to a more general kind. + KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); Handle previous_receiver_map = target_receiver_maps.at(0); if (state() == MONOMORPHIC) { - Handle transitioned_receiver_map = receiver_map; - if (IsTransitionStoreMode(store_mode)) { - transitioned_receiver_map = - ComputeTransitionedMap(receiver_map, store_mode); - } + Handle transitioned_receiver_map = + ComputeTransitionedMap(receiver_map, transition_mode); if ((receiver_map.is_identical_to(previous_receiver_map) && - IsTransitionStoreMode(store_mode)) || + transition_mode != TransitionMode::kNoTransition) || IsTransitionOfMonomorphicTarget(*previous_receiver_map, *transitioned_receiver_map)) { // If the "old" and "new" maps are in the same elements map family, or // if they at least come from the same origin for a transitioning store, // stay MONOMORPHIC and use the map for the most generic ElementsKind. - store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow); Handle handler = StoreElementHandler(transitioned_receiver_map, store_mode); ConfigureVectorState(Handle(), transitioned_receiver_map, handler); @@ -1814,9 +1807,8 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, } if (receiver_map.is_identical_to(previous_receiver_map) && old_store_mode == STANDARD_STORE && - (store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW || - store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || - store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { + transition_mode == TransitionMode::kNoTransition && + store_mode != STANDARD_STORE) { // A "normal" IC that handles stores can switch to a version that can // grow at the end of the array, handle OOB accesses or copy COW arrays // and still stay MONOMORPHIC. @@ -1830,9 +1822,9 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, bool map_added = AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); - if (IsTransitionStoreMode(store_mode)) { + if (transition_mode != TransitionMode::kNoTransition) { Handle transitioned_receiver_map = - ComputeTransitionedMap(receiver_map, store_mode); + ComputeTransitionedMap(receiver_map, transition_mode); map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, transitioned_receiver_map); } @@ -1850,7 +1842,6 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, // Make sure all polymorphic handlers have the same store mode, otherwise the // megamorphic stub must be used. - store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow); if (old_store_mode != STANDARD_STORE) { if (store_mode == STANDARD_STORE) { store_mode = old_store_mode; @@ -1896,28 +1887,21 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, } Handle KeyedStoreIC::ComputeTransitionedMap( - Handle map, KeyedAccessStoreMode store_mode) { - switch (store_mode) { - case STORE_TRANSITION_TO_OBJECT: - case STORE_AND_GROW_TRANSITION_TO_OBJECT: { + Handle map, TransitionMode transition_mode) { + switch (transition_mode) { + case TransitionMode::kTransitionToObject: { ElementsKind kind = IsHoleyElementsKind(map->elements_kind()) ? HOLEY_ELEMENTS : PACKED_ELEMENTS; return Map::TransitionElementsTo(isolate(), map, kind); } - case STORE_TRANSITION_TO_DOUBLE: - case STORE_AND_GROW_TRANSITION_TO_DOUBLE: { + case TransitionMode::kTransitionToDouble: { ElementsKind kind = IsHoleyElementsKind(map->elements_kind()) ? HOLEY_DOUBLE_ELEMENTS : PACKED_DOUBLE_ELEMENTS; return Map::TransitionElementsTo(isolate(), map, kind); } - case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: - DCHECK(map->has_fixed_typed_array_elements()); - V8_FALLTHROUGH; - case STORE_NO_TRANSITION_HANDLE_COW: - case STANDARD_STORE: - case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW: + case TransitionMode::kNoTransition: return map; } UNREACHABLE(); @@ -1925,10 +1909,6 @@ Handle KeyedStoreIC::ComputeTransitionedMap( Handle KeyedStoreIC::StoreElementHandler( Handle receiver_map, KeyedAccessStoreMode store_mode) { - DCHECK(store_mode == STANDARD_STORE || - store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW || - store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || - store_mode == STORE_NO_TRANSITION_HANDLE_COW); DCHECK_IMPLIES( receiver_map->DictionaryElementsInPrototypeChainOnly(isolate()), IsStoreInArrayLiteralICKind(kind())); @@ -1980,11 +1960,6 @@ Handle KeyedStoreIC::StoreElementHandler( void KeyedStoreIC::StoreElementPolymorphicHandlers( MapHandles* receiver_maps, MaybeObjectHandles* handlers, KeyedAccessStoreMode store_mode) { - DCHECK(store_mode == STANDARD_STORE || - store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW || - store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || - store_mode == STORE_NO_TRANSITION_HANDLE_COW); - // Filter out deprecated maps to ensure their instances get migrated. receiver_maps->erase( std::remove_if( @@ -2046,8 +2021,7 @@ bool MayHaveTypedArrayInPrototypeChain(Handle object) { return false; } -KeyedAccessStoreMode GetStoreMode(Handle receiver, uint32_t index, - Handle value) { +KeyedAccessStoreMode GetStoreMode(Handle receiver, uint32_t index) { bool oob_access = IsOutOfBoundsAccess(receiver, index); // Don't consider this a growing store if the store would send the receiver to // dictionary mode. Also make sure we don't consider this a growing store if @@ -2058,40 +2032,32 @@ KeyedAccessStoreMode GetStoreMode(Handle receiver, uint32_t index, !receiver->WouldConvertToSlowElements(index) && !MayHaveTypedArrayInPrototypeChain(receiver); if (allow_growth) { - // Handle growing array in stub if necessary. - if (receiver->HasSmiElements()) { - if (value->IsHeapNumber()) { - return STORE_AND_GROW_TRANSITION_TO_DOUBLE; - } - if (value->IsHeapObject()) { - return STORE_AND_GROW_TRANSITION_TO_OBJECT; - } - } else if (receiver->HasDoubleElements()) { - if (!value->IsSmi() && !value->IsHeapNumber()) { - return STORE_AND_GROW_TRANSITION_TO_OBJECT; - } - } - return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW; - } else { - // Handle only in-bounds elements accesses. - if (receiver->HasSmiElements()) { - if (value->IsHeapNumber()) { - return STORE_TRANSITION_TO_DOUBLE; - } else if (value->IsHeapObject()) { - return STORE_TRANSITION_TO_OBJECT; - } - } else if (receiver->HasDoubleElements()) { - if (!value->IsSmi() && !value->IsHeapNumber()) { - return STORE_TRANSITION_TO_OBJECT; - } - } - if (!FLAG_trace_external_array_abuse && - receiver->map()->has_fixed_typed_array_elements() && oob_access) { - return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS; - } - return receiver->elements()->IsCowArray() ? STORE_NO_TRANSITION_HANDLE_COW - : STANDARD_STORE; + return STORE_AND_GROW_HANDLE_COW; } + if (!FLAG_trace_external_array_abuse && + receiver->map()->has_fixed_typed_array_elements() && oob_access) { + return STORE_IGNORE_OUT_OF_BOUNDS; + } + return receiver->elements()->IsCowArray() ? STORE_HANDLE_COW : STANDARD_STORE; +} + +TransitionMode GetTransitionMode(Handle receiver, + Handle value) { + // TODO(mythria): Also consider index and the current length and handle + // transitions to HOLEY. + if (receiver->HasSmiElements()) { + if (value->IsHeapNumber()) { + return TransitionMode::kTransitionToDouble; + } + if (value->IsHeapObject()) { + return TransitionMode::kTransitionToObject; + } + } else if (receiver->HasDoubleElements()) { + if (!value->IsSmi() && !value->IsHeapNumber()) { + return TransitionMode::kTransitionToObject; + } + } + return TransitionMode::kNoTransition; } } // namespace @@ -2154,6 +2120,7 @@ MaybeHandle KeyedStoreIC::Store(Handle object, bool is_arguments = false; bool key_is_valid_index = false; KeyedAccessStoreMode store_mode = STANDARD_STORE; + TransitionMode transition_mode = TransitionMode::kNoTransition; if (use_ic && object->IsJSReceiver()) { Handle receiver = Handle::cast(object); old_receiver_map = handle(receiver->map(), isolate()); @@ -2170,15 +2137,13 @@ MaybeHandle KeyedStoreIC::Store(Handle object, if (key_is_valid_index) { uint32_t index = static_cast(Smi::ToInt(*key)); Handle receiver_object = Handle::cast(object); - store_mode = GetStoreMode(receiver_object, index, value); + store_mode = GetStoreMode(receiver_object, index); + transition_mode = GetTransitionMode(receiver_object, value); } } } DCHECK(store_handle.is_null()); - bool receiver_was_cow = - object->IsJSArray() && - Handle::cast(object)->elements()->IsCowArray(); ASSIGN_RETURN_ON_EXCEPTION( isolate(), store_handle, Runtime::SetObjectProperty(isolate(), object, key, value, @@ -2203,14 +2168,13 @@ MaybeHandle KeyedStoreIC::Store(Handle object, // (Runtime::SetObjectProperty). if (old_receiver_map->elements_kind() == Handle::cast(object)->map()->elements_kind()) { - store_mode = - GetNonTransitioningStoreMode(store_mode, receiver_was_cow); + transition_mode = TransitionMode::kNoTransition; } // We should go generic if receiver isn't a dictionary, but our // prototype chain does have dictionary elements. This ensures that // other non-dictionary receivers in the polymorphic case benefit // from fast path keyed stores. - UpdateStoreElement(old_receiver_map, store_mode, receiver_was_cow); + UpdateStoreElement(old_receiver_map, store_mode, transition_mode); } else { set_slow_stub_reason("dictionary or proxy prototype"); } @@ -2259,19 +2223,20 @@ void StoreInArrayLiteralIC::Store(Handle array, Handle index, // TODO(neis): Convert HeapNumber to Smi if possible? KeyedAccessStoreMode store_mode = STANDARD_STORE; + TransitionMode transition_mode = TransitionMode::kNoTransition; if (index->IsSmi()) { DCHECK_GE(Smi::ToInt(*index), 0); uint32_t index32 = static_cast(Smi::ToInt(*index)); - store_mode = GetStoreMode(array, index32, value); + store_mode = GetStoreMode(array, index32); + transition_mode = GetTransitionMode(array, value); } Handle old_array_map(array->map(), isolate()); - bool array_was_cow = array->elements()->IsCowArray(); StoreOwnElement(isolate(), array, index, value); if (index->IsSmi()) { DCHECK(!old_array_map->is_abandoned_prototype_map()); - UpdateStoreElement(old_array_map, store_mode, array_was_cow); + UpdateStoreElement(old_array_map, store_mode, transition_mode); } else { set_slow_stub_reason("index out of Smi range"); } diff --git a/src/ic/ic.h b/src/ic/ic.h index 9de63124ec..e72e71d240 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -334,6 +334,12 @@ enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap }; enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength }; +enum class TransitionMode { + kNoTransition, + kTransitionToDouble, + kTransitionToObject +}; + class KeyedStoreIC : public StoreIC { public: KeyedAccessStoreMode GetKeyedAccessStoreMode() { @@ -351,7 +357,7 @@ class KeyedStoreIC : public StoreIC { protected: void UpdateStoreElement(Handle receiver_map, KeyedAccessStoreMode store_mode, - bool receiver_was_cow); + TransitionMode transition_mode); Handle slow_stub() const override { return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow); @@ -359,7 +365,7 @@ class KeyedStoreIC : public StoreIC { private: Handle ComputeTransitionedMap(Handle map, - KeyedAccessStoreMode store_mode); + TransitionMode transition_mode); Handle StoreElementHandler(Handle receiver_map, KeyedAccessStoreMode store_mode);