1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * JDK-8035712: Restore some of the RuntimeCallSite specializations 26 * 27 * @test 28 * @run 29 */ 30 31 if ((typeof Assert) == "undefined") { 32 Assert = { 33 assertTrue: function(x) { if(!x) { throw "expected true" } }, 34 assertFalse: function(x) { if(x) { throw "expected false" } }, 35 }; 36 } 37 38 function nop() {} 39 40 function EQ(x, y) { 41 // Exercise normal evaluation 42 Assert.assertTrue (x == y); 43 Assert.assertTrue (y == x); 44 Assert.assertFalse(x != y); 45 Assert.assertFalse(y != x); 46 // Exercise the branch optimizer 47 if (x == y) { nop(); } else { Assert.fail(); } 48 if (y == x) { nop(); } else { Assert.fail(); } 49 if (x != y) { Assert.fail(); } else { nop(); } 50 if (y != x) { Assert.fail(); } else { nop(); } 51 } 52 53 function NE(x, y) { 54 // Exercise normal evaluation 55 Assert.assertTrue (x != y); 56 Assert.assertTrue (y != x); 57 Assert.assertFalse(x == y); 58 Assert.assertFalse(y == x); 59 // Exercise the branch optimizer 60 if (x != y) { nop(); } else { Assert.fail(); } 61 if (y != x) { nop(); } else { Assert.fail(); } 62 if (x == y) { Assert.fail(); } else { nop(); } 63 if (y == x) { Assert.fail(); } else { nop(); } 64 } 65 66 function STRICT_EQ(x, y) { 67 // Exercise normal evaluation 68 Assert.assertTrue (x === y); 69 Assert.assertTrue (y === x); 70 Assert.assertFalse(x !== y); 71 Assert.assertFalse(y !== x); 72 // Exercise the branch optimizer 73 if (x === y) { nop(); } else { Assert.fail(); } 74 if (y === x) { nop(); } else { Assert.fail(); } 75 if (x !== y) { Assert.fail(); } else { nop(); } 76 if (y !== x) { Assert.fail(); } else { nop(); } 77 } 78 79 function STRICT_NE(x, y) { 80 // Exercise normal evaluation 81 Assert.assertTrue (x !== y); 82 Assert.assertTrue (y !== x); 83 Assert.assertFalse(x === y); 84 Assert.assertFalse(y === x); 85 // Exercise the branch optimizer 86 if (x !== y) { nop(); } else { Assert.fail(); } 87 if (y !== x) { nop(); } else { Assert.fail(); } 88 if (x === y) { Assert.fail(); } else { nop(); } 89 if (y === x) { Assert.fail(); } else { nop(); } 90 } 91 92 function cmpToAnyNumber(cmp, value) { 93 cmp(1, value); 94 cmp(4294967296, value); 95 cmp(1.2, value); 96 cmp(Infinity, value); 97 cmp(-Infinity, value); 98 cmp(1/Infinity, value); 99 cmp(0, value); 100 cmp(-0, value); 101 cmp(true, value); 102 cmp(false, value); 103 } 104 105 function notEqualToAnyNumber(value) { 106 cmpToAnyNumber(NE, value); 107 cmpToAnyNumber(STRICT_NE, value); 108 } 109 110 notEqualToAnyNumber(null); 111 notEqualToAnyNumber(void 0); 112 notEqualToAnyNumber("abc"); 113 notEqualToAnyNumber({}); 114 notEqualToAnyNumber(["xyz"]); 115 116 function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) { 117 var obj = { 118 count: 0 119 }; 120 obj[fnName] = function() { this.count++; return "foo"; }; 121 notEqualToAnyNumber(obj); 122 // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons 123 // STRICT_NE doesn't invoke toString. 124 Assert.assertTrue(80 === obj.count); 125 } 126 objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf"); 127 objectWithPrimitiveFunctionNotEqualToAnyNumber("toString"); 128 129 function objectEqualButNotStrictlyEqual(val, obj) { 130 EQ(val, obj); 131 STRICT_NE(val, obj); 132 } 133 134 function numberEqualButNotStrictlyEqualToObject(num, obj) { 135 objectEqualButNotStrictlyEqual(num, obj); 136 objectEqualButNotStrictlyEqual(num, [obj]); 137 objectEqualButNotStrictlyEqual(num, [[obj]]); 138 } 139 140 function numberEqualButNotStrictlyEqualToZeroObjects(num) { 141 numberEqualButNotStrictlyEqualToObject(num, [0]); 142 numberEqualButNotStrictlyEqualToObject(num, ""); 143 numberEqualButNotStrictlyEqualToObject(num, []); 144 numberEqualButNotStrictlyEqualToObject(num, "0"); 145 } 146 147 numberEqualButNotStrictlyEqualToZeroObjects(0); 148 numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity); 149 numberEqualButNotStrictlyEqualToZeroObjects(false); 150 151 function numberEqualButNotStrictlyEqualToObjectEquivalent(num) { 152 var str = String(num); 153 objectEqualButNotStrictlyEqual(num, str); 154 objectEqualButNotStrictlyEqual(num, { valueOf: function() { return str }}); 155 objectEqualButNotStrictlyEqual(num, { toString: function() { return str }}); 156 objectEqualButNotStrictlyEqual(num, { valueOf: function() { return num }}); 157 objectEqualButNotStrictlyEqual(num, { toString: function() { return num }}); 158 } 159 160 numberEqualButNotStrictlyEqualToObjectEquivalent(1); 161 numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296); 162 numberEqualButNotStrictlyEqualToObjectEquivalent(1.2); 163 numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity); 164 numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity); 165 numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity); 166 numberEqualButNotStrictlyEqualToObjectEquivalent(0); 167 numberEqualButNotStrictlyEqualToObjectEquivalent(-0); 168 169 STRICT_EQ(1, new java.lang.Integer(1)); 170 STRICT_EQ(1, new java.lang.Double(1)); 171 STRICT_EQ(1.2, new java.lang.Double(1.2)); 172 173 function LE(x, y) { 174 // Exercise normal evaluation 175 Assert.assertTrue(x <= y); 176 Assert.assertTrue(y >= x); 177 Assert.assertFalse(x > y); 178 Assert.assertFalse(x < y); 179 // Exercise the branch optimizer 180 if (x <= y) { nop(); } else { Assert.fail(); } 181 if (y >= x) { nop(); } else { Assert.fail(); } 182 if (x > y) { Assert.fail(); } else { nop(); } 183 if (y < x) { Assert.fail(); } else { nop(); } 184 } 185 186 function mutuallyLessThanOrEqual(x, y) { 187 LE(x, y); 188 LE(y, x); 189 } 190 191 mutuallyLessThanOrEqual(0, null); 192 mutuallyLessThanOrEqual(false, null); 193 mutuallyLessThanOrEqual(1/Infinity, null); 194 195 function mutuallyLessThanEqualToObjectWithValue(num, val) { 196 mutuallyLessThanOrEqual(num, { valueOf: function() { return val } }); 197 mutuallyLessThanOrEqual(num, { toString: function() { return val } }); 198 } 199 200 mutuallyLessThanEqualToObjectWithValue(false, 0); 201 mutuallyLessThanEqualToObjectWithValue(false, ""); 202 203 mutuallyLessThanEqualToObjectWithValue(true, 1); 204 mutuallyLessThanEqualToObjectWithValue(true, "1"); 205 206 function lessThanEqualToObjectEquivalent(num) { 207 var str = String(num); 208 mutuallyLessThanOrEqual(num, str); 209 mutuallyLessThanEqualToObjectWithValue(num, num); 210 mutuallyLessThanEqualToObjectWithValue(num, str); 211 } 212 213 lessThanEqualToObjectEquivalent(1); 214 lessThanEqualToObjectEquivalent(4294967296); 215 lessThanEqualToObjectEquivalent(1.2); 216 lessThanEqualToObjectEquivalent(Infinity); 217 lessThanEqualToObjectEquivalent(-Infinity); 218 lessThanEqualToObjectEquivalent(1/Infinity); 219 lessThanEqualToObjectEquivalent(0); 220 lessThanEqualToObjectEquivalent(-0); 221 222 function INCOMPARABLE(x, y) { 223 // Exercise normal evaluation 224 Assert.assertFalse(x < y); 225 Assert.assertFalse(x > y); 226 Assert.assertFalse(x <= y); 227 Assert.assertFalse(x >= y); 228 Assert.assertFalse(y < x); 229 Assert.assertFalse(y > x); 230 Assert.assertFalse(y <= x); 231 Assert.assertFalse(y >= x); 232 // Exercise the branch optimizer 233 if (x < y) { Assert.fail(); } else { nop(); } 234 if (x > y) { Assert.fail(); } else { nop(); } 235 if (x <= y) { Assert.fail(); } else { nop(); } 236 if (x >= y) { Assert.fail(); } else { nop(); } 237 if (y < x) { Assert.fail(); } else { nop(); } 238 if (y > x) { Assert.fail(); } else { nop(); } 239 if (y <= x) { Assert.fail(); } else { nop(); } 240 if (y >= x) { Assert.fail(); } else { nop(); } 241 } 242 243 function isIncomparable(value) { 244 cmpToAnyNumber(INCOMPARABLE, value); 245 } 246 247 isIncomparable(void 0); 248 isIncomparable({ valueOf: function() { return NaN }}); 249 isIncomparable({ toString: function() { return NaN }}); 250 251 // Force ScriptRuntime.LT(Object, Object) etc. comparisons 252 function cmpObj(fn, x, y) { 253 fn({valueOf: function() { return x }}, {valueOf: function() { return y }}); 254 } 255 256 function LT(x, y) { 257 Assert.assertTrue(x < y); 258 Assert.assertTrue(y > x); 259 Assert.assertFalse(x >= y); 260 Assert.assertFalse(y <= x); 261 } 262 263 cmpObj(LT, 1, 2); 264 cmpObj(LT, 1, "2"); 265 cmpObj(LT, "1", 2); 266 cmpObj(LT, "a", "b"); 267 cmpObj(LT, -Infinity, 0); 268 cmpObj(LT, 0, Infinity); 269 cmpObj(LT, -Infinity, Infinity); 270 cmpObj(INCOMPARABLE, 1, NaN); 271 cmpObj(INCOMPARABLE, NaN, NaN); 272 cmpObj(INCOMPARABLE, "boo", NaN); 273 cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN 274 275 // Test that a comparison call site can deoptimize from (int, int) to (object, object) 276 (function(){ 277 var x = [1, 2, "a"]; 278 var y = [2, "3", "b"]; 279 for(var i = 0; i < 3; ++i) { 280 Assert.assertTrue(x[i] < y[i]); 281 } 282 })();