8f00d61dae
This CL introduces proper Oddball and ReceiverOrOddball states for the CompareOperationFeedback, and updates the StrictEqual IC to collect this feedback as well. Previously it would not collect Oddball feedback, not even in the sense of NumberOrOddball, since that's not usable for the SpeculativeNumberEqual. The new feedback is handled via newly introduced CheckReceiverOrOddball and CheckOddball operators in TurboFan, introduced by JSTypedLowering. Just like with the Receiver feedback, it's enough to check one side and do a ReferenceEqual afterwards, since strict equal can only yield true if both sides refer to the same instance. This improves the benchmark mentioned in http://crbug.com/v8/8356 from naive: 2950 ms. tenary: 2456 ms. to around naive: 2996 ms. tenary: 2192 ms. which corresponds to a roughly 10% improvement in the case for the tenary pattern, which is currently used by dart2js. In real world scenarios this will probably help even more, since TurboFan is able to optimize across the strict equality, i.e. there's no longer a stub call forcibly spilling all registers that are live across the call. This new feedback will be used as a basis for the JSEqual support for ReceiverOrOddball, which will allow dart2js switching to the shorter a==b form, at the same peak performance. Bug: v8:8356 Change-Id: Iafbf5d64fcc9312f9e575b54c32c631ce9b572b2 Reviewed-on: https://chromium-review.googlesource.com/c/1297309 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#56925}
153 lines
3.1 KiB
JavaScript
153 lines
3.1 KiB
JavaScript
// 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
|
|
|
|
// Known receivers strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = {};
|
|
|
|
function foo() { return a === b; }
|
|
|
|
assertFalse(foo());
|
|
assertFalse(foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo());
|
|
})();
|
|
|
|
// Known receiver/null strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = null;
|
|
|
|
function foo() { return a === b; }
|
|
|
|
assertFalse(foo());
|
|
assertFalse(foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo());
|
|
})();
|
|
|
|
// Known receiver/undefined strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = undefined;
|
|
|
|
function foo() { return a === b; }
|
|
|
|
assertFalse(foo());
|
|
assertFalse(foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo());
|
|
})();
|
|
|
|
// Known receiver on one side strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = {};
|
|
|
|
function foo(a) { return a === b; }
|
|
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
})();
|
|
|
|
// Known receiver on one side strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = null;
|
|
|
|
function foo(a) { return a === b; }
|
|
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
})();
|
|
|
|
// Known receiver on one side strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = undefined;
|
|
|
|
function foo(a) { return a === b; }
|
|
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(b));
|
|
assertFalse(foo(a));
|
|
})();
|
|
|
|
// Feedback based receiver strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = {};
|
|
|
|
function foo(a, b) { return a === b; }
|
|
|
|
assertTrue(foo(b, b));
|
|
assertFalse(foo(a, b));
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
|
|
// TurboFan bakes in feedback for the left hand side.
|
|
assertFalse(foo(null, b));
|
|
assertUnoptimized(foo);
|
|
})();
|
|
|
|
// Feedback based receiver/null strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = null;
|
|
|
|
function foo(a, b) { return a === b; }
|
|
|
|
assertTrue(foo(b, b));
|
|
assertFalse(foo(a, b));
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
|
|
// TurboFan bakes in feedback for the left hand side.
|
|
assertFalse(foo(1, b));
|
|
assertUnoptimized(foo);
|
|
})();
|
|
|
|
// Feedback based receiver/undefined strict equality.
|
|
(function() {
|
|
const a = {};
|
|
const b = undefined;
|
|
|
|
function foo(a, b) { return a === b; }
|
|
|
|
assertTrue(foo(b, b));
|
|
assertFalse(foo(a, b));
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(a, a));
|
|
assertFalse(foo(b, a));
|
|
|
|
// TurboFan bakes in feedback for the left hand side.
|
|
assertFalse(foo(1, b));
|
|
assertUnoptimized(foo);
|
|
})();
|