[turbofan] Optimize JSResolvePromise with unreliable resolution maps.
When InferReceiverMaps doesn't provide us with reliable maps for the resolution, we can still utilize the information if all the maps that are found are stable - aka leaf - maps. But in that case we need to make sure that we add proper dependencies on the stability of these maps. Bug: v8:7253 Change-Id: I6f5825583acc3f2575e83a244d55609ac64d04d3 Reviewed-on: https://chromium-review.googlesource.com/c/1288633 Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#56789}
This commit is contained in:
parent
2e70a9f7ee
commit
39e68c5e40
@ -689,9 +689,17 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
|
||||
NodeProperties::InferReceiverMapsResult result =
|
||||
NodeProperties::InferReceiverMaps(broker(), resolution, effect,
|
||||
&resolution_maps);
|
||||
if (result != NodeProperties::kReliableReceiverMaps) return NoChange();
|
||||
if (result == NodeProperties::kNoReceiverMaps) return NoChange();
|
||||
DCHECK_NE(0, resolution_maps.size());
|
||||
|
||||
// When the {resolution_maps} information is unreliable, we can
|
||||
// still optimize if all individual {resolution_maps} are stable.
|
||||
if (result == NodeProperties::kUnreliableReceiverMaps) {
|
||||
for (Handle<Map> resolution_map : resolution_maps) {
|
||||
if (!resolution_map->is_stable()) return NoChange();
|
||||
}
|
||||
}
|
||||
|
||||
// Compute property access info for "then" on {resolution}.
|
||||
PropertyAccessInfo access_info;
|
||||
AccessInfoFactory access_info_factory(
|
||||
@ -714,6 +722,13 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
|
||||
broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
|
||||
}
|
||||
|
||||
// Add stability dependencies on the {resolution_maps}.
|
||||
if (result == NodeProperties::kUnreliableReceiverMaps) {
|
||||
for (Handle<Map> resolution_map : resolution_maps) {
|
||||
dependencies()->DependOnStableMap(MapRef(broker(), resolution_map));
|
||||
}
|
||||
}
|
||||
|
||||
// Simply fulfill the {promise} with the {resolution}.
|
||||
Node* value = effect =
|
||||
graph()->NewNode(javascript()->FulfillPromise(), promise, resolution,
|
||||
|
61
test/mjsunit/compiler/promise-resolve-stable-maps.js
Normal file
61
test/mjsunit/compiler/promise-resolve-stable-maps.js
Normal file
@ -0,0 +1,61 @@
|
||||
// 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: --allow-natives-syntax --opt --noalways-opt
|
||||
|
||||
// Test that JSResolvePromise takes a proper stability dependency
|
||||
// on the resolutions map if the infer receiver maps are unreliable
|
||||
// (as is the case for HeapConstants).
|
||||
(function() {
|
||||
// We need an object literal which gets a stable map initially.
|
||||
function makeObjectWithStableMap() {
|
||||
return {a:1, b:1, c:1};
|
||||
}
|
||||
const a = makeObjectWithStableMap();
|
||||
|
||||
function foo() {
|
||||
return Promise.resolve(a);
|
||||
}
|
||||
|
||||
assertInstanceof(foo(), Promise);
|
||||
assertInstanceof(foo(), Promise);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
assertInstanceof(foo(), Promise);
|
||||
assertOptimized(foo);
|
||||
|
||||
// Now invalidate the stability of a's map.
|
||||
const b = makeObjectWithStableMap();
|
||||
b.d = 1;
|
||||
|
||||
// This should deoptimize foo.
|
||||
assertUnoptimized(foo);
|
||||
})();
|
||||
|
||||
// Same test with async functions.
|
||||
(function() {
|
||||
// We need an object literal which gets a stable map initially,
|
||||
// it needs to be different from the above, otherwise the map
|
||||
// is already not stable when we get here.
|
||||
function makeObjectWithStableMap() {
|
||||
return {x:1, y:1};
|
||||
}
|
||||
const a = makeObjectWithStableMap();
|
||||
|
||||
async function foo() {
|
||||
return a;
|
||||
}
|
||||
|
||||
assertInstanceof(foo(), Promise);
|
||||
assertInstanceof(foo(), Promise);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
assertInstanceof(foo(), Promise);
|
||||
assertOptimized(foo);
|
||||
|
||||
// Now invalidate the stability of a's map.
|
||||
const b = makeObjectWithStableMap();
|
||||
b.z = 1;
|
||||
|
||||
// This should deoptimize foo.
|
||||
assertUnoptimized(foo);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user