d2fdc74755
Reviewed-by: jlaskey, hannesw, mhaupt
283 lines
9.1 KiB
JavaScript
283 lines
9.1 KiB
JavaScript
/*
|
|
* 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]);
|
|
}
|
|
})();
|