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:
parent
fd3d44f6bb
commit
0c10dda4bd
@ -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);
|
||||
|
26
test/mjsunit/ic-migrated-map-add-when-monomorphic.js
Normal file
26
test/mjsunit/ic-migrated-map-add-when-monomorphic.js
Normal 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);
|
23
test/mjsunit/ic-migrated-map-add-when-uninitialized.js
Normal file
23
test/mjsunit/ic-migrated-map-add-when-uninitialized.js
Normal 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);
|
27
test/mjsunit/ic-migrated-map-update-when-deprecated.js
Normal file
27
test/mjsunit/ic-migrated-map-update-when-deprecated.js
Normal 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);
|
Loading…
Reference in New Issue
Block a user