Reland [CloneObjectIC] overwrite monomorphic/polymorphic feedback if deprecated
An object with a deprecated Map which has already been cached in CloneObjectIC feedback is still a valid Map for fast cloning --- but to be consistent with other ICs, deprecated maps are ignored, and are expected to be transitioned away from. If the source object has a deprecated map, the instance is migrated. BUG=v8:7611, chromium:867958, chromium:868586 R=jkummerow@chromium.org, mvstanton@chromium.org Change-Id: I477aec6c8d0ae1e1648a70e85d2fd46146521d1c Reviewed-on: https://chromium-review.googlesource.com/1154143 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#54799}
This commit is contained in:
parent
3d4524f672
commit
d9f6c685f0
@ -756,13 +756,14 @@ void FeedbackNexus::ConfigureCloneObject(Handle<Map> source_map,
|
|||||||
SetFeedbackExtra(*result_map);
|
SetFeedbackExtra(*result_map);
|
||||||
break;
|
break;
|
||||||
case MONOMORPHIC:
|
case MONOMORPHIC:
|
||||||
if (maybe_feedback->IsClearedWeakHeapObject()) {
|
if (maybe_feedback->IsClearedWeakHeapObject() ||
|
||||||
|
feedback.is_identical_to(source_map) ||
|
||||||
|
Map::cast(*feedback)->is_deprecated()) {
|
||||||
// Remain in MONOMORPHIC state if previous feedback has been collected.
|
// Remain in MONOMORPHIC state if previous feedback has been collected.
|
||||||
SetFeedback(HeapObjectReference::Weak(*source_map));
|
SetFeedback(HeapObjectReference::Weak(*source_map));
|
||||||
SetFeedbackExtra(*result_map);
|
SetFeedbackExtra(*result_map);
|
||||||
} else {
|
} else {
|
||||||
// Transition to POLYMORPHIC.
|
// Transition to POLYMORPHIC.
|
||||||
DCHECK_NE(*source_map, *feedback);
|
|
||||||
Handle<WeakFixedArray> array =
|
Handle<WeakFixedArray> array =
|
||||||
EnsureArrayOfSize(2 * kCloneObjectPolymorphicEntrySize);
|
EnsureArrayOfSize(2 * kCloneObjectPolymorphicEntrySize);
|
||||||
array->Set(0, maybe_feedback);
|
array->Set(0, maybe_feedback);
|
||||||
@ -778,10 +779,12 @@ void FeedbackNexus::ConfigureCloneObject(Handle<Map> source_map,
|
|||||||
Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(feedback);
|
Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(feedback);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < array->length(); i += kCloneObjectPolymorphicEntrySize) {
|
for (; i < array->length(); i += kCloneObjectPolymorphicEntrySize) {
|
||||||
if (array->Get(i)->IsClearedWeakHeapObject()) {
|
MaybeObject* feedback = array->Get(i);
|
||||||
|
if (!feedback->IsClearedWeakHeapObject()) break;
|
||||||
|
Handle<Map> cached_map(Map::cast(feedback->GetHeapObject()), isolate);
|
||||||
|
if (cached_map.is_identical_to(source_map) ||
|
||||||
|
cached_map->is_deprecated())
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
DCHECK_NE(array->Get(i)->GetHeapObject(), *source_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= array->length()) {
|
if (i >= array->length()) {
|
||||||
|
@ -2549,6 +2549,9 @@ RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) {
|
|||||||
DCHECK_EQ(4, args.length());
|
DCHECK_EQ(4, args.length());
|
||||||
Handle<HeapObject> source = args.at<HeapObject>(0);
|
Handle<HeapObject> source = args.at<HeapObject>(0);
|
||||||
int flags = args.smi_at(1);
|
int flags = args.smi_at(1);
|
||||||
|
|
||||||
|
MigrateDeprecated(source);
|
||||||
|
|
||||||
FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2));
|
FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2));
|
||||||
Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
|
Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
|
||||||
|
|
||||||
|
13
test/mjsunit/es9/regress/regress-867958.js
Normal file
13
test/mjsunit/es9/regress/regress-867958.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Check that encountering deprecated Maps does not cause CloneObjectIC to
|
||||||
|
// crash.
|
||||||
|
var obj1 = { x: 1 };
|
||||||
|
var obj2 = { x: 2 }; // same map
|
||||||
|
obj2.x = null; // deprecate map
|
||||||
|
|
||||||
|
function f() { return { ...obj1 } };
|
||||||
|
assertEquals({ x: 1 }, f()); // missed, object migrated to cached new map
|
||||||
|
assertEquals({ x: 1 }, f()); // monomorphic cache-hit
|
Loading…
Reference in New Issue
Block a user