Commit 32ea5662 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[ic] Improve COW array support in KeyedStoreIC transition handler.

See the referenced issue for details.

Bug: v8:7559
Change-Id: I16b5d22b484407d277fa55868429f5f11078b56d
Reviewed-on: https://chromium-review.googlesource.com/970361
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52173}
parent c8e9cd65
......@@ -1679,13 +1679,14 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
}
void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
KeyedAccessStoreMode store_mode) {
KeyedAccessStoreMode store_mode,
bool receiver_was_cow) {
MapHandles target_receiver_maps;
TargetMaps(&target_receiver_maps);
if (target_receiver_maps.empty()) {
Handle<Map> monomorphic_map =
ComputeTransitionedMap(receiver_map, store_mode);
store_mode = GetNonTransitioningStoreMode(store_mode);
store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
}
......@@ -1718,7 +1719,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> 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);
store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
Handle<Object> handler =
StoreElementHandler(transitioned_receiver_map, store_mode);
ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
......@@ -1762,7 +1763,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
// Make sure all polymorphic handlers have the same store mode, otherwise the
// megamorphic stub must be used.
store_mode = GetNonTransitioningStoreMode(store_mode);
store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
if (old_store_mode != STANDARD_STORE) {
if (store_mode == STANDARD_STORE) {
store_mode = old_store_mode;
......@@ -1977,12 +1978,8 @@ static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
receiver->map()->has_fixed_typed_array_elements() && oob_access) {
return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
}
Heap* heap = receiver->GetHeap();
if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
return STORE_NO_TRANSITION_HANDLE_COW;
} else {
return STANDARD_STORE;
}
return receiver->elements()->IsCowArray() ? STORE_NO_TRANSITION_HANDLE_COW
: STANDARD_STORE;
}
}
......@@ -2066,6 +2063,9 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
}
DCHECK(store_handle.is_null());
bool receiver_was_cow =
object->IsJSArray() &&
Handle<JSArray>::cast(object)->elements()->IsCowArray();
ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
Runtime::SetObjectProperty(isolate(), object, key,
value, language_mode()),
......@@ -2084,7 +2084,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
// 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);
UpdateStoreElement(old_receiver_map, store_mode, receiver_was_cow);
} else {
set_slow_stub_reason("dictionary or proxy prototype");
}
......@@ -2140,11 +2140,12 @@ void StoreInArrayLiteralIC::Store(Handle<JSArray> array, Handle<Object> index,
}
Handle<Map> old_array_map(array->map(), isolate());
bool array_was_cow = array->elements()->IsCowArray();
StoreOwnElement(array, index, value);
if (index->IsSmi()) {
DCHECK(!old_array_map->is_abandoned_prototype_map());
UpdateStoreElement(old_array_map, store_mode);
UpdateStoreElement(old_array_map, store_mode, array_was_cow);
} else {
set_slow_stub_reason("index out of Smi range");
}
......
......@@ -371,7 +371,8 @@ class KeyedStoreIC : public StoreIC {
protected:
void UpdateStoreElement(Handle<Map> receiver_map,
KeyedAccessStoreMode store_mode);
KeyedAccessStoreMode store_mode,
bool receiver_was_cow);
Handle<Code> slow_stub() const override {
return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
......
......@@ -216,14 +216,26 @@ static inline bool IsCOWHandlingStoreMode(KeyedAccessStoreMode store_mode) {
}
static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
KeyedAccessStoreMode store_mode) {
if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
return store_mode;
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;
}
if (store_mode >= STORE_AND_GROW_NO_TRANSITION_HANDLE_COW) {
return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
}
return STANDARD_STORE;
DCHECK(!IsTransitionStoreMode(store_mode));
DCHECK_IMPLIES(receiver_was_cow, IsCOWHandlingStoreMode(store_mode));
return store_mode;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment