| /* |
| * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /** |
| * JDK-8035712: Restore some of the RuntimeCallSite specializations |
| * |
| * @test |
| * @run |
| */ |
| |
| if ((typeof Assert) == "undefined") { |
| Assert = { |
| assertTrue: function(x) { if(!x) { throw "expected true" } }, |
| assertFalse: function(x) { if(x) { throw "expected false" } }, |
| }; |
| } |
| |
| function nop() {} |
| |
| function EQ(x, y) { |
| // Exercise normal evaluation |
| Assert.assertTrue (x == y); |
| Assert.assertTrue (y == x); |
| Assert.assertFalse(x != y); |
| Assert.assertFalse(y != x); |
| // Exercise the branch optimizer |
| if (x == y) { nop(); } else { Assert.fail(); } |
| if (y == x) { nop(); } else { Assert.fail(); } |
| if (x != y) { Assert.fail(); } else { nop(); } |
| if (y != x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function NE(x, y) { |
| // Exercise normal evaluation |
| Assert.assertTrue (x != y); |
| Assert.assertTrue (y != x); |
| Assert.assertFalse(x == y); |
| Assert.assertFalse(y == x); |
| // Exercise the branch optimizer |
| if (x != y) { nop(); } else { Assert.fail(); } |
| if (y != x) { nop(); } else { Assert.fail(); } |
| if (x == y) { Assert.fail(); } else { nop(); } |
| if (y == x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function STRICT_EQ(x, y) { |
| // Exercise normal evaluation |
| Assert.assertTrue (x === y); |
| Assert.assertTrue (y === x); |
| Assert.assertFalse(x !== y); |
| Assert.assertFalse(y !== x); |
| // Exercise the branch optimizer |
| if (x === y) { nop(); } else { Assert.fail(); } |
| if (y === x) { nop(); } else { Assert.fail(); } |
| if (x !== y) { Assert.fail(); } else { nop(); } |
| if (y !== x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function STRICT_NE(x, y) { |
| // Exercise normal evaluation |
| Assert.assertTrue (x !== y); |
| Assert.assertTrue (y !== x); |
| Assert.assertFalse(x === y); |
| Assert.assertFalse(y === x); |
| // Exercise the branch optimizer |
| if (x !== y) { nop(); } else { Assert.fail(); } |
| if (y !== x) { nop(); } else { Assert.fail(); } |
| if (x === y) { Assert.fail(); } else { nop(); } |
| if (y === x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function cmpToAnyNumber(cmp, value) { |
| cmp(1, value); |
| cmp(4294967296, value); |
| cmp(1.2, value); |
| cmp(Infinity, value); |
| cmp(-Infinity, value); |
| cmp(1/Infinity, value); |
| cmp(0, value); |
| cmp(-0, value); |
| cmp(true, value); |
| cmp(false, value); |
| } |
| |
| function notEqualToAnyNumber(value) { |
| cmpToAnyNumber(NE, value); |
| cmpToAnyNumber(STRICT_NE, value); |
| } |
| |
| notEqualToAnyNumber(null); |
| notEqualToAnyNumber(void 0); |
| notEqualToAnyNumber("abc"); |
| notEqualToAnyNumber({}); |
| notEqualToAnyNumber(["xyz"]); |
| |
| function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) { |
| var obj = { |
| count: 0 |
| }; |
| obj[fnName] = function() { this.count++; return "foo"; }; |
| notEqualToAnyNumber(obj); |
| // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons |
| // STRICT_NE doesn't invoke toString. |
| Assert.assertTrue(80 === obj.count); |
| } |
| objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf"); |
| objectWithPrimitiveFunctionNotEqualToAnyNumber("toString"); |
| |
| function objectEqualButNotStrictlyEqual(val, obj) { |
| EQ(val, obj); |
| STRICT_NE(val, obj); |
| } |
| |
| function numberEqualButNotStrictlyEqualToObject(num, obj) { |
| objectEqualButNotStrictlyEqual(num, obj); |
| objectEqualButNotStrictlyEqual(num, [obj]); |
| objectEqualButNotStrictlyEqual(num, [[obj]]); |
| } |
| |
| function numberEqualButNotStrictlyEqualToZeroObjects(num) { |
| numberEqualButNotStrictlyEqualToObject(num, [0]); |
| numberEqualButNotStrictlyEqualToObject(num, ""); |
| numberEqualButNotStrictlyEqualToObject(num, []); |
| numberEqualButNotStrictlyEqualToObject(num, "0"); |
| } |
| |
| numberEqualButNotStrictlyEqualToZeroObjects(0); |
| numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity); |
| numberEqualButNotStrictlyEqualToZeroObjects(false); |
| |
| function numberEqualButNotStrictlyEqualToObjectEquivalent(num) { |
| var str = String(num); |
| objectEqualButNotStrictlyEqual(num, str); |
| objectEqualButNotStrictlyEqual(num, { valueOf: function() { return str }}); |
| objectEqualButNotStrictlyEqual(num, { toString: function() { return str }}); |
| objectEqualButNotStrictlyEqual(num, { valueOf: function() { return num }}); |
| objectEqualButNotStrictlyEqual(num, { toString: function() { return num }}); |
| } |
| |
| numberEqualButNotStrictlyEqualToObjectEquivalent(1); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(1.2); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(0); |
| numberEqualButNotStrictlyEqualToObjectEquivalent(-0); |
| |
| STRICT_EQ(1, new java.lang.Integer(1)); |
| STRICT_EQ(1, new java.lang.Double(1)); |
| STRICT_EQ(1.2, new java.lang.Double(1.2)); |
| |
| function LE(x, y) { |
| // Exercise normal evaluation |
| Assert.assertTrue(x <= y); |
| Assert.assertTrue(y >= x); |
| Assert.assertFalse(x > y); |
| Assert.assertFalse(x < y); |
| // Exercise the branch optimizer |
| if (x <= y) { nop(); } else { Assert.fail(); } |
| if (y >= x) { nop(); } else { Assert.fail(); } |
| if (x > y) { Assert.fail(); } else { nop(); } |
| if (y < x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function mutuallyLessThanOrEqual(x, y) { |
| LE(x, y); |
| LE(y, x); |
| } |
| |
| mutuallyLessThanOrEqual(0, null); |
| mutuallyLessThanOrEqual(false, null); |
| mutuallyLessThanOrEqual(1/Infinity, null); |
| |
| function mutuallyLessThanEqualToObjectWithValue(num, val) { |
| mutuallyLessThanOrEqual(num, { valueOf: function() { return val } }); |
| mutuallyLessThanOrEqual(num, { toString: function() { return val } }); |
| } |
| |
| mutuallyLessThanEqualToObjectWithValue(false, 0); |
| mutuallyLessThanEqualToObjectWithValue(false, ""); |
| |
| mutuallyLessThanEqualToObjectWithValue(true, 1); |
| mutuallyLessThanEqualToObjectWithValue(true, "1"); |
| |
| function lessThanEqualToObjectEquivalent(num) { |
| var str = String(num); |
| mutuallyLessThanOrEqual(num, str); |
| mutuallyLessThanEqualToObjectWithValue(num, num); |
| mutuallyLessThanEqualToObjectWithValue(num, str); |
| } |
| |
| lessThanEqualToObjectEquivalent(1); |
| lessThanEqualToObjectEquivalent(4294967296); |
| lessThanEqualToObjectEquivalent(1.2); |
| lessThanEqualToObjectEquivalent(Infinity); |
| lessThanEqualToObjectEquivalent(-Infinity); |
| lessThanEqualToObjectEquivalent(1/Infinity); |
| lessThanEqualToObjectEquivalent(0); |
| lessThanEqualToObjectEquivalent(-0); |
| |
| function INCOMPARABLE(x, y) { |
| // Exercise normal evaluation |
| Assert.assertFalse(x < y); |
| Assert.assertFalse(x > y); |
| Assert.assertFalse(x <= y); |
| Assert.assertFalse(x >= y); |
| Assert.assertFalse(y < x); |
| Assert.assertFalse(y > x); |
| Assert.assertFalse(y <= x); |
| Assert.assertFalse(y >= x); |
| // Exercise the branch optimizer |
| if (x < y) { Assert.fail(); } else { nop(); } |
| if (x > y) { Assert.fail(); } else { nop(); } |
| if (x <= y) { Assert.fail(); } else { nop(); } |
| if (x >= y) { Assert.fail(); } else { nop(); } |
| if (y < x) { Assert.fail(); } else { nop(); } |
| if (y > x) { Assert.fail(); } else { nop(); } |
| if (y <= x) { Assert.fail(); } else { nop(); } |
| if (y >= x) { Assert.fail(); } else { nop(); } |
| } |
| |
| function isIncomparable(value) { |
| cmpToAnyNumber(INCOMPARABLE, value); |
| } |
| |
| isIncomparable(void 0); |
| isIncomparable({ valueOf: function() { return NaN }}); |
| isIncomparable({ toString: function() { return NaN }}); |
| |
| // Force ScriptRuntime.LT(Object, Object) etc. comparisons |
| function cmpObj(fn, x, y) { |
| fn({valueOf: function() { return x }}, {valueOf: function() { return y }}); |
| } |
| |
| function LT(x, y) { |
| Assert.assertTrue(x < y); |
| Assert.assertTrue(y > x); |
| Assert.assertFalse(x >= y); |
| Assert.assertFalse(y <= x); |
| } |
| |
| cmpObj(LT, 1, 2); |
| cmpObj(LT, 1, "2"); |
| cmpObj(LT, "1", 2); |
| cmpObj(LT, "a", "b"); |
| cmpObj(LT, -Infinity, 0); |
| cmpObj(LT, 0, Infinity); |
| cmpObj(LT, -Infinity, Infinity); |
| cmpObj(INCOMPARABLE, 1, NaN); |
| cmpObj(INCOMPARABLE, NaN, NaN); |
| cmpObj(INCOMPARABLE, "boo", NaN); |
| cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN |
| |
| // Test that a comparison call site can deoptimize from (int, int) to (object, object) |
| (function(){ |
| var x = [1, 2, "a"]; |
| var y = [2, "3", "b"]; |
| for(var i = 0; i < 3; ++i) { |
| Assert.assertTrue(x[i] < y[i]); |
| } |
| })(); |