nashorn/test/script/basic/JDK-8035712.js
changeset 29283 fb47e4d25a9f
child 31925 85c87bc2f1f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035712.js	Thu Mar 05 15:43:43 2015 +0100
@@ -0,0 +1,282 @@
+/*
+ * 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]);
+    }
+})();