v8/test/mjsunit/const-field-tracking.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

236 lines
7.1 KiB
JavaScript
Raw Normal View History

// Copyright 2017 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 --turbofan --no-always-turbofan
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));
assertUnoptimized(load);
assertEquals(the_value, load());
assertUnoptimized(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();
if (!%IsDictPropertyConstTrackingEnabled())
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);
})();
Revert "[ic] Remove SameValue optimisation for constant fields" This reverts commit e7f6d34cfe32fcb64841a20c16fe3375f04af6a9. Reason for revert: Regressions and clusterfuzz bugs Original change's description: > [ic] Remove SameValue optimisation for constant fields > > We would previously try to preserve field constness if field assignment > was assigning the same value. It's unexpected that real-life code would > be assigning the same value multiple times to an intentionally constant > field, so this was additional bookkeeping with unclear value. > > Replace this with not doing it, and considering any write to a constant > field to convert it to mutable. In particular, this means that stores to > existing constant fields in TurboFan become unconditional deopts, rather > than emitting additional code to check whether the value is the same. > > Locally, this deopt doesn't fire on our peak-performance benchmarks. > > Bug: v8:5495 > Change-Id: I12216c5f10a00f42be32c64ca3afe7cf59b4e7f3 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3976516 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Tobias Tebbi <tebbi@chromium.org> > Reviewed-by: Igor Sheludko <ishell@chromium.org> > Cr-Commit-Position: refs/heads/main@{#83955} Bug: v8:5495 Change-Id: Ifeeceb773af04e9dd5e069821cd128a1cdbedcf5 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3990683 Auto-Submit: Leszek Swirski <leszeks@chromium.org> Owners-Override: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Cr-Commit-Position: refs/heads/main@{#83970}
2022-10-28 08:21:17 +00:00
//
// 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);
if (typeof the_value == "function" || typeof the_value == "object") {
// For heap object fields "field-owner" dependency is installed for
// any access of the field, therefore making constant field mutable by
// assigning other value to some other instance of A should already
// trigger deoptimization.
assertTrue(%HaveSameMap(a, the_object.a));
new A(the_value).v = other_value;
assertTrue(%HaveSameMap(a, new A(the_value)));
assertTrue(%HaveSameMap(a, the_object.a));
assertUnoptimized(store);
} else {
assertOptimized(store);
}
// Storing other value deoptimizes because of failed value check.
store(other_value);
assertUnoptimized(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);
})();