d4da17c6e3
The Object.is builtin provides an entry point to the abstract operation SameValue, which properly distinguishes -0 and 0, and also identifies NaNs. Most of the time you don't need these, but rather just regular strict equality, but when you do, Object.is(o, -0) is the most readable way to check for minus zero. This is for example used in Node.js by formatNumber to properly print -0 for negative zero. However since the builtin thus far implemented as C++ builtin and TurboFan didn't know anything about it, Node.js considering to go with a more performant, less readable version (which also makes assumptions about the input value) in https://github.com/nodejs/node/pull/15726 until the performance of Object.is will be on par (so hopefully we can go back to Object.is in Node 9). This CL ports the baseline implementation of Object.is to CSA, which is pretty straight-forward since SameValue is already available in CodeStubAssembler, and inlines a few interesting cases into TurboFan, i.e. comparing same SSA node, and checking for -0 and NaN explicitly. On the micro-benchmarks we go from testNumberIsMinusZero: 1000 ms. testObjectIsMinusZero: 929 ms. testObjectIsNaN: 954 ms. testObjectIsSame: 793 ms. testStrictEqualSame: 104 ms. to testNumberIsMinusZero: 89 ms. testObjectIsMinusZero: 88 ms. testObjectIsNaN: 88 ms. testObjectIsSame: 86 ms. testStrictEqualSame: 105 ms. which is a nice 10x to 11x improvement and brings Object.is on par with strict equality for most cases. Drive-by-fix: Also refactor and optimize the SameValue check in the CodeStubAssembler to avoid code bloat (by not inlining StrictEqual into every user of SameValue, and also avoiding useless checks). Bug: v8:6882 Change-Id: Ibffd8c36511f219fcce0d89ed4e1073f5d6c6344 Reviewed-on: https://chromium-review.googlesource.com/700254 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#48275}
144 lines
3.3 KiB
JavaScript
144 lines
3.3 KiB
JavaScript
// 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
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(o, -0); }
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(-0, o); }
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(+o, -0); }
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(-0, +o); }
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertFalse(foo(NaN));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(o, NaN); }
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(NaN, o); }
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertFalse(foo(''));
|
|
assertFalse(foo([]));
|
|
assertFalse(foo({}));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(+o, NaN); }
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(NaN, +o); }
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo(-0));
|
|
assertFalse(foo(0));
|
|
assertTrue(foo(NaN));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(`${o}`, "foo"); }
|
|
assertFalse(foo("bar"));
|
|
assertTrue(foo("foo"));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertFalse(foo("bar"));
|
|
assertTrue(foo("foo"));
|
|
})();
|
|
|
|
(function() {
|
|
function foo(o) { return Object.is(o, o); }
|
|
assertTrue(foo(-0));
|
|
assertTrue(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertTrue(foo(''));
|
|
assertTrue(foo([]));
|
|
assertTrue(foo({}));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertTrue(foo(-0));
|
|
assertTrue(foo(0));
|
|
assertTrue(foo(NaN));
|
|
assertTrue(foo(''));
|
|
assertTrue(foo([]));
|
|
assertTrue(foo({}));
|
|
})();
|