[turboprop] Only optimize prototype const fields in turboprop
This patch has the following improvement on v8.browsing_mobile: - total-main-thread:duration improved by 1.7% - js:duration improved by 1.3% Change-Id: I1cdf2c181bfd991b67f31c5c2f32e3c2f909c67e Bug: v8:9684, v8:10431 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2149433 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#67405}
This commit is contained in:
parent
6ffb8e1886
commit
79e9a97df7
@ -390,6 +390,10 @@ PropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
|
||||
PropertyConstness constness;
|
||||
if (details.IsReadOnly() && !details.IsConfigurable()) {
|
||||
constness = PropertyConstness::kConst;
|
||||
} else if (FLAG_turboprop && !map->is_prototype_map()) {
|
||||
// The constness feedback is too unstable for the aggresive compilation
|
||||
// of turboprop.
|
||||
constness = PropertyConstness::kMutable;
|
||||
} else {
|
||||
map_ref.SerializeOwnDescriptor(descriptor);
|
||||
constness = dependencies()->DependOnFieldConstness(map_ref, descriptor);
|
||||
|
225
test/mjsunit/const-field-tracking-2.js
Normal file
225
test/mjsunit/const-field-tracking-2.js
Normal file
@ -0,0 +1,225 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// TODO(gsathya): This test will probably break when v8 tiers up to turbofan
|
||||
// from turboprop.
|
||||
//
|
||||
// Flags: --allow-natives-syntax --opt --no-always-opt --turboprop
|
||||
|
||||
var global = this;
|
||||
var unique_id = 0;
|
||||
// Creates a function with unique SharedFunctionInfo to ensure the feedback
|
||||
// vector is unique for each test case.
|
||||
function MakeFunctionWithUniqueSFI(...args) {
|
||||
assertTrue(args.length > 0);
|
||||
var body = `/* Unique comment: ${unique_id++} */ ` + args.pop();
|
||||
return new Function(...args, body);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Load constant field from constant object directly.
|
||||
//
|
||||
function TestLoadFromConstantFieldOfAConstantObject(the_value, other_value) {
|
||||
function A(v) { this.v = v; }
|
||||
function O() { this.a = new A(the_value); }
|
||||
var the_object = new O();
|
||||
|
||||
// Ensure that {the_object.a}'s map is not stable to complicate compiler's
|
||||
// life.
|
||||
new A(the_value).blah = 0;
|
||||
|
||||
// Ensure that constant tracking is enabled for {contant_object}.
|
||||
delete global.constant_object;
|
||||
global.constant_object = the_object;
|
||||
assertEquals(the_object, constant_object);
|
||||
|
||||
assertTrue(%HasFastProperties(the_object));
|
||||
|
||||
// {constant_object} is known to the compiler via global property cell
|
||||
// tracking.
|
||||
var load = MakeFunctionWithUniqueSFI("return constant_object.a.v;");
|
||||
%PrepareFunctionForOptimization(load);
|
||||
load();
|
||||
load();
|
||||
%OptimizeFunctionOnNextCall(load);
|
||||
assertEquals(the_value, load());
|
||||
assertOptimized(load);
|
||||
var a = new A(other_value);
|
||||
assertTrue(%HaveSameMap(a, the_object.a));
|
||||
// Make constant field mutable by assigning another value
|
||||
// to some other instance of A.
|
||||
new A(the_value).v = other_value;
|
||||
assertTrue(%HaveSameMap(a, new A(the_value)));
|
||||
assertTrue(%HaveSameMap(a, the_object.a));
|
||||
assertOptimized(load);
|
||||
assertEquals(the_value, load());
|
||||
assertOptimized(load);
|
||||
assertEquals(the_value, load());
|
||||
}
|
||||
|
||||
//Test constant tracking with Smi value.
|
||||
(function() {
|
||||
var the_value = 42;
|
||||
var other_value = 153;
|
||||
TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with double value.
|
||||
(function() {
|
||||
var the_value = 0.9;
|
||||
var other_value = 0.42;
|
||||
TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with function value.
|
||||
(function() {
|
||||
var the_value = function V() {};
|
||||
var other_value = function W() {};
|
||||
TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with heap object value.
|
||||
(function() {
|
||||
function V() {}
|
||||
var the_value = new V();
|
||||
var other_value = new V();
|
||||
TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
|
||||
//
|
||||
// Load constant field from a prototype.
|
||||
//
|
||||
function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
|
||||
function Proto() { this.v = the_value; }
|
||||
var the_prototype = new Proto();
|
||||
|
||||
function O() {}
|
||||
O.prototype = the_prototype;
|
||||
var the_object = new O();
|
||||
|
||||
// Ensure O.prototype is in fast mode by loading from its field.
|
||||
function warmup() { return new O().v; }
|
||||
%EnsureFeedbackVectorForFunction(warmup);
|
||||
warmup(); warmup(); warmup();
|
||||
assertTrue(%HasFastProperties(O.prototype));
|
||||
|
||||
// The parameter object is not constant but all the values have the same
|
||||
// map and therefore the compiler knows the prototype object and can
|
||||
// optimize load of "v".
|
||||
var load = MakeFunctionWithUniqueSFI("o", "return o.v;");
|
||||
%PrepareFunctionForOptimization(load);
|
||||
load(new O());
|
||||
load(new O());
|
||||
%OptimizeFunctionOnNextCall(load);
|
||||
assertEquals(the_value, load(new O()));
|
||||
assertOptimized(load);
|
||||
// Invalidation of mutability should trigger deoptimization with a
|
||||
// "field-owner" reason.
|
||||
the_prototype.v = other_value;
|
||||
assertUnoptimized(load);
|
||||
}
|
||||
|
||||
// Test constant tracking with Smi value.
|
||||
(function() {
|
||||
var the_value = 42;
|
||||
var other_value = 153;
|
||||
TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with double value.
|
||||
(function() {
|
||||
var the_value = 0.9;
|
||||
var other_value = 0.42;
|
||||
TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with function value.
|
||||
(function() {
|
||||
var the_value = function V() {};
|
||||
var other_value = function W() {};
|
||||
TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with heap object value.
|
||||
(function() {
|
||||
function V() {}
|
||||
var the_value = new V();
|
||||
var other_value = new V();
|
||||
TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
|
||||
})();
|
||||
|
||||
|
||||
//
|
||||
// Store to constant field of a constant object.
|
||||
//
|
||||
function TestStoreToConstantFieldOfConstantObject(the_value, other_value) {
|
||||
function A(v) { this.v = v; }
|
||||
function O() { this.a = new A(the_value); }
|
||||
var the_object = new O();
|
||||
|
||||
// Ensure that {the_object.a}'s map is not stable to complicate compiler's
|
||||
// life.
|
||||
new A(the_value).blah = 0;
|
||||
|
||||
// Ensure that constant tracking is enabled for {contant_object}.
|
||||
delete global.constant_object;
|
||||
global.constant_object = the_object;
|
||||
assertEquals(the_object, constant_object);
|
||||
|
||||
assertTrue(%HasFastProperties(the_object));
|
||||
|
||||
// {constant_object} is known to the compiler via global property cell
|
||||
// tracking.
|
||||
var store = MakeFunctionWithUniqueSFI("v", "constant_object.a.v = v;");
|
||||
%PrepareFunctionForOptimization(store);
|
||||
store(the_value);
|
||||
store(the_value);
|
||||
%OptimizeFunctionOnNextCall(store);
|
||||
store(the_value);
|
||||
assertEquals(the_value, constant_object.a.v);
|
||||
assertOptimized(store);
|
||||
// Storing of the same value does not deoptimize.
|
||||
store(the_value);
|
||||
assertEquals(the_value, constant_object.a.v);
|
||||
assertOptimized(store);
|
||||
|
||||
var a = new A(other_value);
|
||||
|
||||
assertOptimized(store);
|
||||
// Storing other value deoptimizes because of failed value check.
|
||||
store(other_value);
|
||||
assertOptimized(store);
|
||||
assertEquals(other_value, constant_object.a.v);
|
||||
}
|
||||
|
||||
// Test constant tracking with Smi values.
|
||||
(function() {
|
||||
var the_value = 42;
|
||||
var other_value = 153;
|
||||
TestStoreToConstantFieldOfConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with double values.
|
||||
(function() {
|
||||
var the_value = 0.9;
|
||||
var other_value = 0.42
|
||||
TestStoreToConstantFieldOfConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with function values.
|
||||
(function() {
|
||||
var the_value = function V() {};
|
||||
var other_value = function W() {};
|
||||
TestStoreToConstantFieldOfConstantObject(the_value, other_value);
|
||||
})();
|
||||
|
||||
// Test constant tracking with heap object values.
|
||||
(function() {
|
||||
function V() {}
|
||||
var the_value = new V();
|
||||
var other_value = new V();
|
||||
TestStoreToConstantFieldOfConstantObject(the_value, other_value);
|
||||
})();
|
@ -1157,6 +1157,9 @@
|
||||
'deopt-recursive-soft-once': [SKIP],
|
||||
'regress/regress-3709': [SKIP],
|
||||
'regress/regress-5790': [SKIP],
|
||||
|
||||
# const field tracking is disabled in turboprop
|
||||
'const-field-tracking': [SKIP],
|
||||
}], # variant == turboprop
|
||||
|
||||
##############################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user