Update inline cache after migrating deprecated map

Previously, when the Load IC saw a deprecated map, it would migrate to
the new map but not update the feedback vector. This would lead to a
deopt the next time the same object was seen.

With this CL, the feedback vector will be updated to the target of the
deprecated map. In order to do this, we need to mark the IC for
recomputation. Without that call, the map and handler would look the
same to IC::UpdatePolymorphicIC amd would decline to update, causing
the IC to go megamorphic instead.

Bug: v8:10816
Change-Id: I0dcf97fb278bc0b167df6ce24d5db179f599f535
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3032983
Reviewed-by: Mythri Alle <mythria@chromium.org>
Commit-Queue: Kevin Babbitt <kbabbitt@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#76042}
This commit is contained in:
Kevin Babbitt 2021-07-22 16:13:10 -07:00 committed by V8 LUCI CQ
parent fd3d44f6bb
commit 0c10dda4bd
4 changed files with 83 additions and 1 deletions

View File

@ -427,7 +427,13 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name,
}
}
if (MigrateDeprecated(isolate(), object)) use_ic = false;
// If we encounter an object with a deprecated map, we want to update the
// feedback vector with the migrated map.
// Mark ourselves as RECOMPUTE_HANDLER so that we don't turn megamorphic due
// to seeing the same map and handler.
if (MigrateDeprecated(isolate(), object)) {
UpdateState(object, name);
}
JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
update_lookup_start_object_map(object);

View File

@ -0,0 +1,26 @@
// Copyright 2021 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: --allow-natives-syntax --opt
// https://bugs.chromium.org/p/v8/issues/detail?id=10816
// When V8 sees a deprecated map, update the IC with its target.
function A() { this.x = 1 }
function B() { this.x = 1 }
function load(o) { return o.x }
%PrepareFunctionForOptimization(load);
// Initialize the load IC with a map that will not be deprecated.
load(new A());
const oldB = new B();
(new B()).x = 1.5; // deprecates map
// Should add the target of the deprecated map to the load IC.
load(oldB);
%OptimizeFunctionOnNextCall(load);
load(oldB);
assertOptimized(load);

View File

@ -0,0 +1,23 @@
// Copyright 2021 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: --allow-natives-syntax --opt
// https://bugs.chromium.org/p/v8/issues/detail?id=10816
// When V8 sees a deprecated map, update the IC with its target.
function A() { this.x = 1 }
function B() { this.x = 1 }
function load(o) { return o.x }
%PrepareFunctionForOptimization(load);
const oldB = new B();
(new B()).x = 1.5; // deprecates map
// Should add the target of the deprecated map to the load IC.
load(oldB);
%OptimizeFunctionOnNextCall(load);
load(oldB);
assertOptimized(load);

View File

@ -0,0 +1,27 @@
// Copyright 2021 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: --allow-natives-syntax --opt
// https://bugs.chromium.org/p/v8/issues/detail?id=10816
// When V8 sees a deprecated map, update the IC with its target.
function A() { this.x = 1 }
function B() { this.x = 1 }
function load(o) { return o.x }
%PrepareFunctionForOptimization(load);
// Initialize the load IC with the map of A before we deprecate it.
load(new A());
const oldB = new B();
(new A()).x = 1.5; // deprecates map already in FV
(new B()).x = 1.5; // deprecates map for oldB
// Should update the load IC with the target of the deprecated map.
load(oldB);
%OptimizeFunctionOnNextCall(load);
load(oldB);
assertOptimized(load);