Commit 5caee70b authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

Reland "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, chromium:869342, chromium:869347, chromium:869293
R=jkummerow@chromium.org, mvstanton@chromium.org

Reviewed-on: https://chromium-review.googlesource.com/1154143
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#54799}
Change-Id: I6e2f7b28c41bb9bd6255441da0f209a97bce5e8f
Reviewed-on: https://chromium-review.googlesource.com/1157142
Cr-Commit-Position: refs/heads/master@{#54830}
parent f24b575d
......@@ -756,13 +756,14 @@ void FeedbackNexus::ConfigureCloneObject(Handle<Map> source_map,
SetFeedbackExtra(*result_map);
break;
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.
SetFeedback(HeapObjectReference::Weak(*source_map));
SetFeedbackExtra(*result_map);
} else {
// Transition to POLYMORPHIC.
DCHECK_NE(*source_map, *feedback);
Handle<WeakFixedArray> array =
EnsureArrayOfSize(2 * kCloneObjectPolymorphicEntrySize);
array->Set(0, maybe_feedback);
......@@ -778,11 +779,13 @@ void FeedbackNexus::ConfigureCloneObject(Handle<Map> source_map,
Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(feedback);
int i = 0;
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;
}
DCHECK_NE(array->Get(i)->GetHeapObject(), *source_map);
}
if (i >= array->length()) {
if (i == kMaxElements) {
......
......@@ -2549,6 +2549,9 @@ RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) {
DCHECK_EQ(4, args.length());
Handle<HeapObject> source = args.at<HeapObject>(0);
int flags = args.smi_at(1);
MigrateDeprecated(source);
FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2));
Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
......
// 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
// 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.
// Flags: --expose-gc
function spread(o) { return { ...o }; }
(function setupPolymorphicFeedback() {
function C1() { this.p0 = 1; }
function C2() { this.p1 = 2; this.p2 = 3; }
assertEquals({ p0: 1 }, spread(new C1));
assertEquals({ p1: 2, p2: 3 }, spread(new C2));
})();
gc(); // Clobber cached map in feedback[0], and check that we don't crash
function C3() { this.p0 = 3; }
assertEquals({ p0: 3 }, spread(new C3));
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