diff options
Diffstat (limited to 'test/scanners/javascript/trace-test.in.js')
-rw-r--r-- | test/scanners/javascript/trace-test.in.js | 5930 |
1 files changed, 5930 insertions, 0 deletions
diff --git a/test/scanners/javascript/trace-test.in.js b/test/scanners/javascript/trace-test.in.js new file mode 100644 index 0000000..de0e03e --- /dev/null +++ b/test/scanners/javascript/trace-test.in.js @@ -0,0 +1,5930 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/** + * A number of the tests in this file depend on the setting of + * HOTLOOP. Define some constants up front, so they're easy to grep + * for. + */ +// The HOTLOOP constant we depend on; only readable from our stats +// object in debug builds. +const haveTracemonkey = !!(this.tracemonkey) +const HOTLOOP = haveTracemonkey ? tracemonkey.HOTLOOP : 2; +// The loop count at which we trace +const RECORDLOOP = HOTLOOP; +// The loop count at which we run the trace +const RUNLOOP = HOTLOOP + 1; + +var gDoMandelbrotTest = true; +if ("gSkipSlowTests" in this && gSkipSlowTests) { + print("** Skipping slow tests"); + gDoMandelbrotTest = false; +} + +if (!('gSrcdir' in this)) + gSrcdir = '.'; + +if (!('gReportSummary' in this)) + gReportSummary = true; + +var testName = null; +if ("arguments" in this && arguments.length > 0) + testName = arguments[0]; +var fails = [], passes = []; + +function jitstatHandler(f) +{ + if (!haveTracemonkey) + return; + + // XXXbz this is a nasty hack, but I can't figure out a way to + // just use jitstats.tbl here + f("recorderStarted"); + f("recorderAborted"); + f("traceCompleted"); + f("sideExitIntoInterpreter"); + f("timeoutIntoInterpreter"); + f("typeMapMismatchAtEntry"); + f("returnToDifferentLoopHeader"); + f("traceTriggered"); + f("globalShapeMismatchAtEntry"); + f("treesTrashed"); + f("slotPromoted"); + f("unstableLoopVariable"); + f("breakLoopExits"); + f("returnLoopExits"); + f("mergedLoopExits") + f("noCompatInnerTrees"); + f("blacklisted"); +} + +var jitProps = {}; +jitstatHandler(function(prop) { + jitProps[prop] = true; + }); +var hadJITstats = false; +for (var p in jitProps) + hadJITstats = true; + +function test(f) +{ + // Clear out any accumulated confounding state in the oracle / JIT cache. + gc(); + + if (!testName || testName == f.name) { + var expectedJITstats = f.jitstats; + if (hadJITstats && expectedJITstats) + { + var expectedProps = {}; + jitstatHandler(function(prop) { + if (prop in expectedJITstats) + expectedProps[prop] = true; + }); + for (var p in expectedJITstats) + { + if (!(p in expectedProps)) + throw "Bad property in " + f.name + ".jitstats: " + p; + } + } + + // Collect our jit stats + var localJITstats = {}; + jitstatHandler(function(prop) { + localJITstats[prop] = tracemonkey[prop]; + }); + check(f.name, f(), f.expected, localJITstats, expectedJITstats); + } +} + +function map_test(t, cases) +{ + for (var i = 0; i < cases.length; i++) { + function c() { return t(cases[i].input); } + c.expected = cases[i].expected; + c.name = t.name + "(" + uneval(cases[i].input) + ")"; + test(c); + } +} + +// Use this function to compare expected and actual test results. +// Types must match. +// For numbers, treat NaN as matching NaN, distinguish 0 and -0, and +// tolerate a certain degree of error for other values. +// +// These are the same criteria used by the tests in js/tests, except that +// we distinguish 0 and -0. +function close_enough(expected, actual) +{ + if (typeof expected != typeof actual) + return false; + if (typeof expected != 'number') + return actual == expected; + + // Distinguish NaN from other values. Using x != x comparisons here + // works even if tests redefine isNaN. + if (actual != actual) + return expected != expected + if (expected != expected) + return false; + + // Tolerate a certain degree of error. + if (actual != expected) + return Math.abs(actual - expected) <= 1E-10; + + // Distinguish 0 and -0. + if (actual == 0) + return (1 / actual > 0) == (1 / expected > 0); + + return true; +} + +function check(desc, actual, expected, oldJITstats, expectedJITstats) +{ + if (close_enough(expected, actual)) { + var pass = true; + jitstatHandler(function(prop) { + if (expectedJITstats && prop in expectedJITstats && + expectedJITstats[prop] != + tracemonkey[prop] - oldJITstats[prop]) { + pass = false; + } + }); + if (pass) { + passes.push(desc); + return print("TEST-PASS | trace-test.js |", desc); + } + } + fails.push(desc); + var expectedStats = ""; + if (expectedJITstats) { + jitstatHandler(function(prop) { + if (prop in expectedJITstats) { + if (expectedStats) + expectedStats += " "; + expectedStats += + prop + ": " + expectedJITstats[prop]; + } + }); + } + var actualStats = ""; + if (expectedJITstats) { + jitstatHandler(function(prop) { + if (prop in expectedJITstats) { + if (actualStats) + actualStats += " "; + actualStats += prop + ": " + (tracemonkey[prop]-oldJITstats[prop]); + } + }); + } + print("TEST-UNEXPECTED-FAIL | trace-test.js |", desc, ": expected", typeof(expected), + "(", uneval(expected), ")", + (expectedStats ? " [" + expectedStats + "] " : ""), + "!= actual", + typeof(actual), "(", uneval(actual), ")", + (actualStats ? " [" + actualStats + "] " : "")); +} + +function ifInsideLoop() +{ + var cond = true, intCond = 5, count = 0; + for (var i = 0; i < 100; i++) { + if (cond) + count++; + if (intCond) + count++; + } + return count; +} +ifInsideLoop.expected = 200; +test(ifInsideLoop); + +function bitwiseAnd_inner(bitwiseAndValue) { + for (var i = 0; i < 60000; i++) + bitwiseAndValue = bitwiseAndValue & i; + return bitwiseAndValue; +} +function bitwiseAnd() +{ + return bitwiseAnd_inner(12341234); +} +bitwiseAnd.expected = 0; +test(bitwiseAnd); + +if (!testName || testName == "bitwiseGlobal") { + bitwiseAndValue = Math.pow(2,32); + for (var i = 0; i < 60000; i++) + bitwiseAndValue = bitwiseAndValue & i; + check("bitwiseGlobal", bitwiseAndValue, 0); +} + + +function equalInt() +{ + var i1 = 55, one = 1, zero = 0, undef; + var o1 = { }, o2 = { }; + var s = "5"; + var hits = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + for (var i = 0; i < 5000; i++) { + if (i1 == 55) hits[0]++; + if (i1 != 56) hits[1]++; + if (i1 < 56) hits[2]++; + if (i1 > 50) hits[3]++; + if (i1 <= 60) hits[4]++; + if (i1 >= 30) hits[5]++; + if (i1 == 7) hits[6]++; + if (i1 != 55) hits[7]++; + if (i1 < 30) hits[8]++; + if (i1 > 90) hits[9]++; + if (i1 <= 40) hits[10]++; + if (i1 >= 70) hits[11]++; + if (o1 == o2) hits[12]++; + if (o2 != null) hits[13]++; + if (s < 10) hits[14]++; + if (true < zero) hits[15]++; + if (undef > one) hits[16]++; + if (undef < zero) hits[17]++; + } + return hits.toString(); +} +equalInt.expected = "5000,5000,5000,5000,5000,5000,0,0,0,0,0,0,0,5000,5000,0,0,0"; +test(equalInt); + +var a; +function setelem() +{ + a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; + a = a.concat(a, a, a); + var l = a.length; + for (var i = 0; i < l; i++) { + a[i] = i; + } + return a.toString(); +} +setelem.expected = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83"; +test(setelem); + +function getelem_inner(a) +{ + var accum = 0; + var l = a.length; + for (var i = 0; i < l; i++) { + accum += a[i]; + } + return accum; +} +function getelem() +{ + return getelem_inner(a); +} +getelem.expected = 3486; +test(getelem); + +globalName = 907; +function name() +{ + var a = 0; + for (var i = 0; i < 100; i++) + a = globalName; + return a; +} +name.expected = 907; +test(name); + +var globalInt = 0; +if (!testName || testName == "globalGet") { + for (var i = 0; i < 500; i++) + globalInt = globalName + i; + check("globalGet", globalInt, globalName + 499); +} + +if (!testName || testName == "globalSet") { + for (var i = 0; i < 500; i++) + globalInt = i; + check("globalSet", globalInt, 499); +} + +function arith() +{ + var accum = 0; + for (var i = 0; i < 100; i++) { + accum += (i * 2) - 1; + } + return accum; +} +arith.expected = 9800; +test(arith); + +function lsh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = 0x1 << n; + return r; +} +map_test (lsh_inner, + [{input: 15, expected: 32768}, + {input: 55, expected: 8388608}, + {input: 1, expected: 2}, + {input: 0, expected: 1}]); + +function rsh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = 0x11010101 >> n; + return r; +} +map_test (rsh_inner, + [{input: 8, expected: 1114369}, + {input: 5, expected: 8914952}, + {input: 35, expected: 35659808}, + {input: -1, expected: 0}]); + +function ursh_inner(n) +{ + var r; + for (var i = 0; i < 35; i++) + r = -55 >>> n; + return r; +} +map_test (ursh_inner, + [{input: 8, expected: 16777215}, + {input: 33, expected: 2147483620}, + {input: 0, expected: 4294967241}, + {input: 1, expected: 2147483620}]); + +function doMath_inner(cos) +{ + var s = 0; + var sin = Math.sin; + for (var i = 0; i < 200; i++) + s = -Math.pow(sin(i) + cos(i * 0.75), 4); + return s; +} +function doMath() { + return doMath_inner(Math.cos); +} +doMath.expected = -0.5405549555611059; +test(doMath); + +function fannkuch() { + var count = Array(8); + var r = 8; + var done = 0; + while (done < 40) { + // write-out the first 30 permutations + done += r; + while (r != 1) { count[r - 1] = r; r--; } + while (true) { + count[r] = count[r] - 1; + if (count[r] > 0) break; + r++; + } + } + return done; +} +fannkuch.expected = 41; +test(fannkuch); + +function xprop() +{ + a = 0; + for (var i = 0; i < 20; i++) + a += 7; + return a; +} +xprop.expected = 140; +test(xprop); + +var a = 2; +function getprop_inner(o2) +{ + var o = {a:5}; + var t = this; + var x = 0; + for (var i = 0; i < 20; i++) { + t = this; + x += o.a + o2.a + this.a + t.a; + } + return x; +} +function getprop() { + return getprop_inner({a:9}); +} +getprop.expected = 360; +test(getprop); + +function mod() +{ + var mods = [-1,-1,-1,-1]; + var a = 9.5, b = -5, c = 42, d = (1/0); + for (var i = 0; i < 20; i++) { + mods[0] = a % b; + mods[1] = b % 1; + mods[2] = c % d; + mods[3] = c % a; + mods[4] = b % 0; + } + return mods.toString(); +} +mod.expected = "4.5,0,42,4,NaN"; +test(mod); + +function glob_f1() { + return 1; +} +function glob_f2() { + return glob_f1(); +} +function call() +{ + var q1 = 0, q2 = 0, q3 = 0, q4 = 0, q5 = 0; + var o = {}; + function f1() { + return 1; + } + function f2(f) { + return f(); + } + o.f = f1; + for (var i = 0; i < 100; ++i) { + q1 += f1(); + q2 += f2(f1); + q3 += glob_f1(); + q4 += o.f(); + q5 += glob_f2(); + } + var ret = String([q1, q2, q3, q4, q5]); + return ret; +} +call.expected = "100,100,100,100,100"; +test(call); + +function setprop() +{ + var obj = { a:-1 }; + var obj2 = { b:-1, a:-1 }; + for (var i = 0; i < 20; i++) { + obj2.b = obj.a = i; + } + return [obj.a, obj2.a, obj2.b].toString(); +} +setprop.expected = "19,-1,19"; +test(setprop); + +function testif() { + var q = 0; + for (var i = 0; i < 100; i++) { + if ((i & 1) == 0) + q++; + else + q--; + } + return q; +} +testif.expected = 0; +test(testif); + +var globalinc = 0; +function testincops(n) { + var i = 0, o = {p:0}, a = [0]; + n = 100; + + for (i = 0; i < n; i++); + while (i-- > 0); + for (i = 0; i < n; ++i); + while (--i >= 0); + + for (o.p = 0; o.p < n; o.p++) globalinc++; + while (o.p-- > 0) --globalinc; + for (o.p = 0; o.p < n; ++o.p) ++globalinc; + while (--o.p >= 0) globalinc--; + + ++i; // set to 0 + for (a[i] = 0; a[i] < n; a[i]++); + while (a[i]-- > 0); + for (a[i] = 0; a[i] < n; ++a[i]); + while (--a[i] >= 0); + + return [++o.p, ++a[i], globalinc].toString(); +} +testincops.expected = "0,0,0"; +test(testincops); + +function trees() { + var i = 0, o = [0,0,0]; + for (i = 0; i < 100; ++i) { + if ((i & 1) == 0) o[0]++; + else if ((i & 2) == 0) o[1]++; + else o[2]++; + } + return String(o); +} +trees.expected = "50,25,25"; +test(trees); + +function unboxint() { + var q = 0; + var o = [4]; + for (var i = 0; i < 100; ++i) + q = o[0] << 1; + return q; +} +unboxint.expected = 8; +test(unboxint); + +function strings() +{ + var a = [], b = -1; + var s = "abcdefghij", s2 = "a"; + var f = "f"; + var c = 0, d = 0, e = 0, g = 0; + for (var i = 0; i < 10; i++) { + a[i] = (s.substring(i, i+1) + s[i] + String.fromCharCode(s2.charCodeAt(0) + i)).concat(i) + i; + if (s[i] == f) + c++; + if (s[i] != 'b') + d++; + if ("B" > s2) + g++; // f already used + if (s2 < "b") + e++; + b = s.length; + } + return a.toString() + b + c + d + e + g; +} +strings.expected = "aaa00,bbb11,ccc22,ddd33,eee44,fff55,ggg66,hhh77,iii88,jjj991019100"; +test(strings); + +function dependentStrings() +{ + var a = []; + var t = "abcdefghijklmnopqrst"; + for (var i = 0; i < 10; i++) { + var s = t.substring(2*i, 2*i + 2); + a[i] = s + s.length; + } + return a.join(""); +} +dependentStrings.expected = "ab2cd2ef2gh2ij2kl2mn2op2qr2st2"; +test(dependentStrings); + +function stringConvert() +{ + var a = []; + var s1 = "F", s2 = "1.3", s3 = "5"; + for (var i = 0; i < 10; i++) { + a[0] = 1 >> s1; + a[1] = 10 - s2; + a[2] = 15 * s3; + a[3] = s3 | 32; + a[4] = s2 + 60; + // a[5] = 9 + s3; + // a[6] = -s3; + a[7] = s3 & "7"; + // a[8] = ~s3; + } + return a.toString(); +} +stringConvert.expected = "1,8.7,75,37,1.360,,,5"; +test(stringConvert); + +function orTestHelper(a, b, n) +{ + var k = 0; + for (var i = 0; i < n; i++) { + if (a || b) + k += i; + } + return k; +} + +var orNaNTest1, orNaNTest2; + +orNaNTest1 = new Function("return orTestHelper(NaN, NaN, 10);"); +orNaNTest1.name = 'orNaNTest1'; +orNaNTest1.expected = 0; +orNaNTest2 = new Function("return orTestHelper(NaN, 1, 10);"); +orNaNTest2.name = 'orNaNTest2'; +orNaNTest2.expected = 45; +test(orNaNTest1); +test(orNaNTest2); + +function andTestHelper(a, b, n) +{ + var k = 0; + for (var i = 0; i < n; i++) { + if (a && b) + k += i; + } + return k; +} + +if (!testName || testName == "truthies") { + (function () { + var opsies = ["||", "&&"]; + var falsies = [null, undefined, false, NaN, 0, ""]; + var truthies = [{}, true, 1, 42, 1/0, -1/0, "blah"]; + var boolies = [falsies, truthies]; + + // The for each here should abort tracing, so that this test framework + // relies only on the interpreter while the orTestHelper and andTestHelper + // functions get trace-JITed. + for each (var op in opsies) { + for (var i in boolies) { + for (var j in boolies[i]) { + var x = uneval(boolies[i][j]); + for (var k in boolies) { + for (var l in boolies[k]) { + var y = uneval(boolies[k][l]); + var prefix = (op == "||") ? "or" : "and"; + var f = new Function("return " + prefix + "TestHelper(" + x + "," + y + ",10)"); + f.name = prefix + "Test(" + x + "," + y + ")"; + f.expected = eval(x + op + y) ? 45 : 0; + test(f); + } + } + } + } + } + })(); +} + +function nonEmptyStack1Helper(o, farble) { + var a = []; + var j = 0; + for (var i in o) + a[j++] = i; + return a.join(""); +} + +function nonEmptyStack1() { + return nonEmptyStack1Helper({a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8}, "hi"); +} + +nonEmptyStack1.expected = "abcdefgh"; +test(nonEmptyStack1); + +function nonEmptyStack2() +{ + var a = 0; + for (var c in {a:1, b:2, c:3}) { + for (var i = 0; i < 10; i++) + a += i; + } + return String(a); +} +nonEmptyStack2.expected = "135"; +test(nonEmptyStack2); + +function arityMismatchMissingArg(arg) +{ + for (var a = 0, i = 1; i < 10000; i *= 2) { + a += i; + } + return a; +} +arityMismatchMissingArg.expected = 16383; +test(arityMismatchMissingArg); + +function arityMismatchExtraArg() +{ + return arityMismatchMissingArg(1, 2); +} +arityMismatchExtraArg.expected = 16383; +test(arityMismatchExtraArg); + +function MyConstructor(i) +{ + this.i = i; +} +MyConstructor.prototype.toString = function() {return this.i + ""}; + +function newTest() +{ + var a = []; + for (var i = 0; i < 10; i++) + a[i] = new MyConstructor(i); + return a.join(""); +} +newTest.expected = "0123456789"; +test(newTest); + +// The following functions use a delay line of length 2 to change the value +// of the callee without exiting the traced loop. This is obviously tuned to +// match the current HOTLOOP setting of 2. +function shapelessArgCalleeLoop(f, g, h, a) +{ + for (var i = 0; i < 10; i++) { + f(i, a); + f = g; + g = h; + } +} + +function shapelessVarCalleeLoop(f0, g, h, a) +{ + var f = f0; + for (var i = 0; i < 10; i++) { + f(i, a); + f = g; + g = h; + } +} + +function shapelessLetCalleeLoop(f0, g, h, a) +{ + for (var i = 0; i < 10; i++) { + let f = f0; + f(i, a); + f = g; + g = h; + } +} + +function shapelessUnknownCalleeLoop(n, f, g, h, a) +{ + for (var i = 0; i < 10; i++) { + (n || f)(i, a); + f = g; + g = h; + } +} + +function shapelessCalleeTest() +{ + var a = []; + + var helper = function (i, a) a[i] = i; + shapelessArgCalleeLoop(helper, helper, function (i, a) a[i] = -i, a); + + helper = function (i, a) a[10 + i] = i; + shapelessVarCalleeLoop(helper, helper, function (i, a) a[10 + i] = -i, a); + + helper = function (i, a) a[20 + i] = i; + shapelessLetCalleeLoop(helper, helper, function (i, a) a[20 + i] = -i, a); + + helper = function (i, a) a[30 + i] = i; + shapelessUnknownCalleeLoop(null, helper, helper, function (i, a) a[30 + i] = -i, a); + + try { + helper = {hack: 42}; + shapelessUnknownCalleeLoop(null, helper, helper, helper, a); + } catch (e) { + if (e + "" != "TypeError: f is not a function") + print("shapelessUnknownCalleeLoop: unexpected exception " + e); + } + return a.join(""); +} +shapelessCalleeTest.expected = "01-2-3-4-5-6-7-8-901-2-3-4-5-6-7-8-9012345678901-2-3-4-5-6-7-8-9"; +test(shapelessCalleeTest); + +function typeofTest() +{ + var values = ["hi", "hi", "hi", null, 5, 5.1, true, undefined, /foo/, typeofTest, [], {}], types = []; + for (var i = 0; i < values.length; i++) + types[i] = typeof values[i]; + return types.toString(); +} +typeofTest.expected = "string,string,string,object,number,number,boolean,undefined,object,function,object,object"; +test(typeofTest); + +function joinTest() +{ + var s = ""; + var a = []; + for (var i = 0; i < 8; i++) + a[i] = [String.fromCharCode(97 + i)]; + for (i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) + a[i][1 + j] = j; + } + for (i = 0; i < 8; i++) + s += a[i].join(","); + return s; +} +joinTest.expected = "a,0,1,2,3,4,5,6,7b,0,1,2,3,4,5,6,7c,0,1,2,3,4,5,6,7d,0,1,2,3,4,5,6,7e,0,1,2,3,4,5,6,7f,0,1,2,3,4,5,6,7g,0,1,2,3,4,5,6,7h,0,1,2,3,4,5,6,7"; +test(joinTest); + +function arity1(x) +{ + return (x == undefined) ? 1 : 0; +} +function missingArgTest() { + var q; + for (var i = 0; i < 10; i++) { + q = arity1(); + } + return q; +} +missingArgTest.expected = 1; +test(missingArgTest); + +JSON = function () { + return { + stringify: function stringify(value, whitelist) { + switch (typeof(value)) { + case "object": + return value.constructor.name; + } + } + }; +}(); + +function missingArgTest2() { + var testPairs = [ + ["{}", {}], + ["[]", []], + ['{"foo":"bar"}', {"foo":"bar"}], + ] + + var a = []; + for (var i=0; i < testPairs.length; i++) { + var s = JSON.stringify(testPairs[i][1]) + a[i] = s; + } + return a.join(","); +} +missingArgTest2.expected = "Object,Array,Object"; +test(missingArgTest2); + +function deepForInLoop() { + // NB: the number of props set in C is arefully tuned to match HOTLOOP = 2. + function C(){this.p = 1, this.q = 2} + C.prototype = {p:1, q:2, r:3, s:4, t:5}; + var o = new C; + var j = 0; + var a = []; + for (var i in o) + a[j++] = i; + return a.join(""); +} +deepForInLoop.expected = "pqrst"; +test(deepForInLoop); + +function nestedExit(x) { + var q = 0; + for (var i = 0; i < 10; ++i) + { + if (x) + ++q; + } +} +function nestedExitLoop() { + for (var j = 0; j < 10; ++j) + nestedExit(j < 7); + return "ok"; +} +nestedExitLoop.expected = "ok"; +test(nestedExitLoop); + +function bitsinbyte(b) { + var m = 1, c = 0; + while(m<0x100) { + if(b & m) c++; + m <<= 1; + } + return 1; +} +function TimeFunc(func) { + var x,y; + for(var y=0; y<256; y++) func(y); +} +function nestedExit2() { + TimeFunc(bitsinbyte); + return "ok"; +} +nestedExit2.expected = "ok"; +test(nestedExit2); + +function parsingNumbers() { + var s1 = "123"; + var s1z = "123zzz"; + var s2 = "123.456"; + var s2z = "123.456zzz"; + + var e1 = 123; + var e2 = 123.456; + + var r1, r1z, r2, r2z; + + for (var i = 0; i < 10; i++) { + r1 = parseInt(s1); + r1z = parseInt(s1z); + r2 = parseFloat(s2); + r2z = parseFloat(s2z); + } + + if (r1 == e1 && r1z == e1 && r2 == e2 && r2z == e2) + return "ok"; + return "fail"; +} +parsingNumbers.expected = "ok"; +test(parsingNumbers); + +function matchInLoop() { + var k = "hi"; + for (var i = 0; i < 10; i++) { + var result = k.match(/hi/) != null; + } + return result; +} +matchInLoop.expected = true; +test(matchInLoop); + +function testMatchAsCondition() { + var a = ['0', '0', '0', '0']; + var r = /0/; + "x".q; + for (var z = 0; z < 4; z++) + a[z].match(r) ? 1 : 2; +} +test(testMatchAsCondition); + +function deep1(x) { + if (x > 90) + return 1; + return 2; +} +function deep2() { + for (var i = 0; i < 100; ++i) + deep1(i); + return "ok"; +} +deep2.expected = "ok"; +test(deep2); + +function heavyFn1(i) { + if (i == 3) { + var x = 3; + return [0, i].map(function (i) i + x); + } + return []; +} +function testHeavy() { + for (var i = 0; i <= 3; i++) + heavyFn1(i); +} +test(testHeavy); + +function heavyFn2(i) { + if (i < 1000) + return heavyFn1(i); + return function () i; +} +function testHeavy2() { + for (var i = 0; i <= 3; i++) + heavyFn2(i); +} +test(testHeavy2); + +var merge_type_maps_x = 0, merge_type_maps_y = 0; +function merge_type_maps() { + for (merge_type_maps_x = 0; merge_type_maps_x < 50; ++merge_type_maps_x) + if ((merge_type_maps_x & 1) == 1) + ++merge_type_maps_y; + return [merge_type_maps_x,merge_type_maps_y].join(","); +} +merge_type_maps.expected = "50,25"; +test(merge_type_maps) + +function inner_double_outer_int() { + function f(i) { + for (var m = 0; m < 20; ++m) + for (var n = 0; n < 100; n += i) + ; + return n; + } + return f(.5); +} +inner_double_outer_int.expected = 100; +test(inner_double_outer_int); + +function newArrayTest() +{ + var a = []; + for (var i = 0; i < 10; i++) + a[i] = new Array(); + return a.map(function(x) x.length).toString(); +} +newArrayTest.expected="0,0,0,0,0,0,0,0,0,0"; +test(newArrayTest); + +function stringSplitTest() +{ + var s = "a,b" + var a = null; + for (var i = 0; i < 10; ++i) + a = s.split(","); + return a.join(); +} +stringSplitTest.expected="a,b"; +test(stringSplitTest); + +function stringSplitIntoArrayTest() +{ + var s = "a,b" + var a = []; + for (var i = 0; i < 10; ++i) + a[i] = s.split(","); + return a.join(); +} +stringSplitIntoArrayTest.expected="a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b"; +test(stringSplitIntoArrayTest); + +function forVarInWith() { + function foo() ({notk:42}); + function bar() ({p:1, q:2, r:3, s:4, t:5}); + var o = foo(); + var a = []; + with (o) { + for (var k in bar()) + a[a.length] = k; + } + return a.join(""); +} +forVarInWith.expected = "pqrst"; +test(forVarInWith); + +function inObjectTest() { + var o = {p: 1, q: 2, r: 3, s: 4, t: 5}; + var r = 0; + for (var i in o) { + if (!(i in o)) + break; + if ((i + i) in o) + break; + ++r; + } + return r; +} +inObjectTest.expected = 5; +test(inObjectTest); + +function inArrayTest() { + var a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + for (var i = 0; i < a.length; i++) { + if (!(i in a)) + break; + } + return i; +} +inArrayTest.expected = 10; +test(inArrayTest); + +function innerLoopIntOuterDouble() { + var n = 10000, i=0, j=0, count=0, limit=0; + for (i = 1; i <= n; ++i) { + limit = i * 1; + for (j = 0; j < limit; ++j) { + ++count; + } + } + return "" + count; +} +innerLoopIntOuterDouble.expected="50005000"; +test(innerLoopIntOuterDouble); + +function outerline(){ + var i=0; + var j=0; + + for (i = 3; i<= 100000; i+=2) + { + for (j = 3; j < 1000; j+=2) + { + if ((i & 1) == 1) + break; + } + } + return "ok"; +} +outerline.expected="ok"; +test(outerline); + +function addAccumulations(f) { + var a = f(); + var b = f(); + return a() + b(); +} + +function loopingAccumulator() { + var x = 0; + return function () { + for (var i = 0; i < 10; ++i) { + ++x; + } + return x; + } +} + +function testLoopingAccumulator() { + var x = addAccumulations(loopingAccumulator); + return x; +} +testLoopingAccumulator.expected = 20; +test(testLoopingAccumulator); + +function testBranchingLoop() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + x += 10; + } + x++; + } + return x; +} +testBranchingLoop.expected = 110; +test(testBranchingLoop); + +function testBranchingUnstableLoop() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + x += 10.1; + } + x++; + } + return x; +} +testBranchingUnstableLoop.expected = 110.1; +test(testBranchingUnstableLoop); + +function testBranchingUnstableLoopCounter() { + var x = 0; + for (var i=0; i < 100; ++i) { + if (i == 51) { + i += 1.1; + } + x++; + } + return x; +} +testBranchingUnstableLoopCounter.expected = 99; +test(testBranchingUnstableLoopCounter); + + +function testBranchingUnstableObject() { + var x = {s: "a"}; + var t = ""; + for (var i=0; i < 100; ++i) { + if (i == 51) + { + x.s = 5; + } + t += x.s; + } + return t.length; +} +testBranchingUnstableObject.expected = 100; +test(testBranchingUnstableObject); + +function testArrayDensityChange() { + var x = []; + var count = 0; + for (var i=0; i < 100; ++i) { + x[i] = "asdf"; + } + for (var i=0; i < x.length; ++i) { + if (i == 51) + { + x[199] = "asdf"; + } + if (x[i]) + count += x[i].length; + } + return count; +} +testArrayDensityChange.expected = 404; +test(testArrayDensityChange); + +function testDoubleToStr() { + var x = 0.0; + var y = 5.5; + for (var i = 0; i < 200; i++) { + x += parseFloat(y.toString()); + } + return x; +} +testDoubleToStr.expected = 5.5*200; +test(testDoubleToStr); + +function testNumberToString() { + var x = new Number(0); + for (var i = 0; i < 4; i++) + x.toString(); +} +test(testNumberToString); + +function testDecayingInnerLoop() { + var i, j, k = 10; + for (i = 0; i < 5000; ++i) { + for (j = 0; j < k; ++j); + --k; + } + return i; +} +testDecayingInnerLoop.expected = 5000; +test(testDecayingInnerLoop); + +function testContinue() { + var i; + var total = 0; + for (i = 0; i < 20; ++i) { + if (i == 11) + continue; + total++; + } + return total; +} +testContinue.expected = 19; +test(testContinue); + +function testContinueWithLabel() { + var i = 0; + var j = 20; + checkiandj : + while (i < 10) { + i += 1; + checkj : + while (j > 10) { + j -= 1; + if ((j % 2) == 0) + continue checkj; + } + } + return i + j; +} +testContinueWithLabel.expected = 20; +test(testContinueWithLabel); + +function testDivision() { + var a = 32768; + var b; + while (b !== 1) { + b = a / 2; + a = b; + } + return a; +} +testDivision.expected = 1; +test(testDivision); + +function testDivisionFloat() { + var a = 32768.0; + var b; + while (b !== 1) { + b = a / 2.0; + a = b; + } + return a === 1.0; +} +testDivisionFloat.expected = true; +test(testDivisionFloat); + +function testToUpperToLower() { + var s = "Hello", s1, s2; + for (i = 0; i < 100; ++i) { + s1 = s.toLowerCase(); + s2 = s.toUpperCase(); + } + return s1 + s2; +} +testToUpperToLower.expected = "helloHELLO"; +test(testToUpperToLower); + +function testReplace2() { + var s = "H e l l o", s1; + for (i = 0; i < 100; ++i) + s1 = s.replace(" ", ""); + return s1; +} +testReplace2.expected = "He l l o"; +test(testReplace2); + +function testBitwise() { + var x = 10000; + var y = 123456; + var z = 987234; + for (var i = 0; i < 50; i++) { + x = x ^ y; + y = y | z; + z = ~x; + } + return x + y + z; +} +testBitwise.expected = -1298; +test(testBitwise); + +function testSwitch() { + var x = 0; + var ret = 0; + for (var i = 0; i < 100; ++i) { + switch (x) { + case 0: + ret += 1; + break; + case 1: + ret += 2; + break; + case 2: + ret += 3; + break; + case 3: + ret += 4; + break; + default: + x = 0; + } + x++; + } + return ret; +} +testSwitch.expected = 226; +test(testSwitch); + +function testSwitchString() { + var x = "asdf"; + var ret = 0; + for (var i = 0; i < 100; ++i) { + switch (x) { + case "asdf": + x = "asd"; + ret += 1; + break; + case "asd": + x = "as"; + ret += 2; + break; + case "as": + x = "a"; + ret += 3; + break; + case "a": + x = "foo"; + ret += 4; + break; + default: + x = "asdf"; + } + } + return ret; +} +testSwitchString.expected = 200; +test(testSwitchString); + +function testNegZero1Helper(z) { + for (let j = 0; j < 5; ++j) { z = -z; } + return Math.atan2(0, -0) == Math.atan2(0, z); +} + +var testNegZero1 = function() { return testNegZero1Helper(0); } +testNegZero1.expected = true; +testNegZero1.name = 'testNegZero1'; +testNegZero1Helper(1); +test(testNegZero1); + +// No test case, just make sure this doesn't assert. +function testNegZero2() { + var z = 0; + for (let j = 0; j < 5; ++j) { ({p: (-z)}); } +} +testNegZero2(); + +function testConstSwitch() { + var x; + for (var j=0;j<5;++j) { switch(1.1) { case NaN: case 2: } x = 2; } + return x; +} +testConstSwitch.expected = 2; +test(testConstSwitch); + +function testConstSwitch2() { + var x; + for (var j = 0; j < 4; ++j) { switch(0/0) { } } + return "ok"; +} +testConstSwitch2.expected = "ok"; +test(testConstSwitch2); + +function testConstIf() { + var x; + for (var j=0;j<5;++j) { if (1.1 || 5) { } x = 2;} + return x; +} +testConstIf.expected = 2; +test(testConstIf); + +function testTypeofHole() { + var a = new Array(6); + a[5] = 3; + for (var i = 0; i < 6; ++i) + a[i] = typeof a[i]; + return a.join(","); +} +testTypeofHole.expected = "undefined,undefined,undefined,undefined,undefined,number" +test(testTypeofHole); + +function testNativeLog() { + var a = new Array(5); + for (var i = 0; i < 5; i++) { + a[i] = Math.log(Math.pow(Math.E, 10)); + } + return a.join(","); +} +testNativeLog.expected = "10,10,10,10,10"; +test(testNativeLog); + +function test_JSOP_ARGSUB() { + function f0() { return arguments[0]; } + function f1() { return arguments[1]; } + function f2() { return arguments[2]; } + function f3() { return arguments[3]; } + function f4() { return arguments[4]; } + function f5() { return arguments[5]; } + function f6() { return arguments[6]; } + function f7() { return arguments[7]; } + function f8() { return arguments[8]; } + function f9() { return arguments[9]; } + var a = []; + for (var i = 0; i < 10; i++) { + a[0] = f0('a'); + a[1] = f1('a','b'); + a[2] = f2('a','b','c'); + a[3] = f3('a','b','c','d'); + a[4] = f4('a','b','c','d','e'); + a[5] = f5('a','b','c','d','e','f'); + a[6] = f6('a','b','c','d','e','f','g'); + a[7] = f7('a','b','c','d','e','f','g','h'); + a[8] = f8('a','b','c','d','e','f','g','h','i'); + a[9] = f9('a','b','c','d','e','f','g','h','i','j'); + } + return a.join(""); +} +test_JSOP_ARGSUB.expected = "abcdefghij"; +test(test_JSOP_ARGSUB); + +function test_JSOP_ARGCNT() { + function f0() { return arguments.length; } + function f1() { return arguments.length; } + function f2() { return arguments.length; } + function f3() { return arguments.length; } + function f4() { return arguments.length; } + function f5() { return arguments.length; } + function f6() { return arguments.length; } + function f7() { return arguments.length; } + function f8() { return arguments.length; } + function f9() { return arguments.length; } + var a = []; + for (var i = 0; i < 10; i++) { + a[0] = f0('a'); + a[1] = f1('a','b'); + a[2] = f2('a','b','c'); + a[3] = f3('a','b','c','d'); + a[4] = f4('a','b','c','d','e'); + a[5] = f5('a','b','c','d','e','f'); + a[6] = f6('a','b','c','d','e','f','g'); + a[7] = f7('a','b','c','d','e','f','g','h'); + a[8] = f8('a','b','c','d','e','f','g','h','i'); + a[9] = f9('a','b','c','d','e','f','g','h','i','j'); + } + return a.join(","); +} +test_JSOP_ARGCNT.expected = "1,2,3,4,5,6,7,8,9,10"; +test(test_JSOP_ARGCNT); + +function testNativeMax() { + var out = [], k; + for (var i = 0; i < 5; ++i) { + k = Math.max(k, i); + } + out.push(k); + + k = 0; + for (var i = 0; i < 5; ++i) { + k = Math.max(k, i); + } + out.push(k); + + for (var i = 0; i < 5; ++i) { + k = Math.max(0, -0); + } + out.push((1 / k) < 0); + return out.join(","); +} +testNativeMax.expected = "NaN,4,false"; +test(testNativeMax); + +function testFloatArrayIndex() { + var a = []; + for (var i = 0; i < 10; ++i) { + a[3] = 5; + a[3.5] = 7; + } + return a[3] + "," + a[3.5]; +} +testFloatArrayIndex.expected = "5,7"; +test(testFloatArrayIndex); + +function testStrict() { + var n = 10, a = []; + for (var i = 0; i < 10; ++i) { + a[0] = (n === 10); + a[1] = (n !== 10); + a[2] = (n === null); + a[3] = (n == null); + } + return a.join(","); +} +testStrict.expected = "true,false,false,false"; +test(testStrict); + +function testSetPropNeitherMissNorHit() { + for (var j = 0; j < 5; ++j) { if (({}).__proto__ = 1) { } } + return "ok"; +} +testSetPropNeitherMissNorHit.expected = "ok"; +test(testSetPropNeitherMissNorHit); + +function testPrimitiveConstructorPrototype() { + var f = function(){}; + f.prototype = false; + for (let j=0;j<5;++j) { new f; } + return "ok"; +} +testPrimitiveConstructorPrototype.expected = "ok"; +test(testPrimitiveConstructorPrototype); + +function testSideExitInConstructor() { + var FCKConfig = {}; + FCKConfig.CoreStyles = + { + 'Bold': { }, + 'Italic': { }, + 'FontFace': { }, + 'Size' : + { + Overrides: [ ] + }, + + 'Color' : + { + Element: '', + Styles: { }, + Overrides: [ ] + }, + 'BackColor': { + Element : '', + Styles : { 'background-color' : '' } + }, + + }; + var FCKStyle = function(A) { + A.Element; + }; + + var pass = true; + for (var s in FCKConfig.CoreStyles) { + var x = new FCKStyle(FCKConfig.CoreStyles[s]); + if (!x) + pass = false; + } + return pass; +} +testSideExitInConstructor.expected = true; +test(testSideExitInConstructor); + +function testNot() { + var a = new Object(), b = null, c = "foo", d = "", e = 5, f = 0, g = 5.5, h = -0, i = true, j = false, k = undefined; + var r; + for (var i = 0; i < 10; ++i) + r = [!a, !b, !c, !d, !e, !f, !g, !h, !i, !j, !k]; + return r.join(","); +} +testNot.expected = "false,true,false,true,false,true,false,true,false,true,true"; +test(testNot); + +function doTestDifferingArgc(a, b) +{ + var k = 0; + for (var i = 0; i < 10; i++) + { + k += i; + } + return k; +} +function testDifferingArgc() +{ + var x = 0; + x += doTestDifferingArgc(1, 2); + x += doTestDifferingArgc(1); + x += doTestDifferingArgc(1, 2, 3); + return x; +} +testDifferingArgc.expected = 45*3; +test(testDifferingArgc); + +function doTestMoreArgcThanNargs() +{ + var x = 0; + for (var i = 0; i < 10; i++) + { + x = x + arguments[3]; + } + return x; +} +function testMoreArgcThanNargs() +{ + return doTestMoreArgcThanNargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +} +testMoreArgcThanNargs.expected = 4*10; +test(testMoreArgcThanNargs); + +// Test stack reconstruction after a nested exit +function testNestedExitStackInner(j, counter) { + ++counter; + var b = 0; + for (var i = 1; i <= RUNLOOP; i++) { + ++b; + var a; + // Make sure that once everything has been traced we suddenly switch to + // a different control flow the first time we run the outermost tree, + // triggering a side exit. + if (j < RUNLOOP) + a = 1; + else + a = 0; + ++b; + b += a; + } + return counter + b; +} +function testNestedExitStackOuter() { + var counter = 0; + for (var j = 1; j <= RUNLOOP; ++j) { + for (var k = 1; k <= RUNLOOP; ++k) { + counter = testNestedExitStackInner(j, counter); + } + } + return counter; +} +testNestedExitStackOuter.expected = 81; +test(testNestedExitStackOuter); + +function testHOTLOOPSize() { + return HOTLOOP > 1; +} +testHOTLOOPSize.expected = true; +test(testHOTLOOPSize); + +function testMatchStringObject() { + var a = new String("foo"); + var b; + for (i = 0; i < 300; i++) + b = a.match(/bar/); + return b; +} +testMatchStringObject.expected = null; +test(testMatchStringObject); + +function innerSwitch(k) +{ + var m = 0; + + switch (k) + { + case 0: + m = 1; + break; + } + + return m; +} +function testInnerSwitchBreak() +{ + var r = new Array(5); + for (var i = 0; i < 5; i++) + { + r[i] = innerSwitch(0); + } + + return r.join(","); +} +testInnerSwitchBreak.expected = "1,1,1,1,1"; +test(testInnerSwitchBreak); + +function testArrayNaNIndex() +{ + for (var j = 0; j < 4; ++j) { [this[NaN]]; } + for (var j = 0; j < 5; ++j) { if([1][-0]) { } } + return "ok"; +} +testArrayNaNIndex.expected = "ok"; +test(testArrayNaNIndex); + +function innerTestInnerMissingArgs(a,b,c,d) +{ + if (a) { + } else { + } +} +function doTestInnerMissingArgs(k) +{ + for (i = 0; i < 10; i++) { + innerTestInnerMissingArgs(k); + } +} +function testInnerMissingArgs() +{ + doTestInnerMissingArgs(1); + doTestInnerMissingArgs(0); + return 1; +} +testInnerMissingArgs.expected = 1; //Expected: that we don't crash. +test(testInnerMissingArgs); + +function regexpLastIndex() +{ + var n = 0; + var re = /hi/g; + var ss = " hi hi hi hi hi hi hi hi hi hi"; + for (var i = 0; i < 10; i++) { + // re.exec(ss); + n += (re.lastIndex > 0) ? 3 : 0; + re.lastIndex = 0; + } + return n; +} +regexpLastIndex.expected = 0; // 30; +test(regexpLastIndex); + +function testHOTLOOPCorrectness() { + var b = 0; + for (var i = 0; i < HOTLOOP; ++i) + ++b; + return b; +} +testHOTLOOPCorrectness.expected = HOTLOOP; +testHOTLOOPCorrectness.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 0 +}; +// Change the global shape right before doing the test +this.testHOTLOOPCorrectnessVar = 1; +test(testHOTLOOPCorrectness); + +function testRUNLOOPCorrectness() { + var b = 0; + for (var i = 0; i < RUNLOOP; ++i) { + ++b; + } + return b; +} +testRUNLOOPCorrectness.expected = RUNLOOP; +testRUNLOOPCorrectness.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 1 +}; +// Change the global shape right before doing the test +this.testRUNLOOPCorrectnessVar = 1; +test(testRUNLOOPCorrectness); + +function testDateNow() { + // Accessing global.Date for the first time will change the global shape, + // so do it before the loop starts; otherwise we have to loop an extra time + // to pick things up. + var time = Date.now(); + for (var j = 0; j < RUNLOOP; ++j) + time = Date.now(); + return "ok"; +} +testDateNow.expected = "ok"; +testDateNow.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 1 +}; +test(testDateNow); + +function testINITELEM() +{ + var x; + for (var i = 0; i < 10; ++i) + x = { 0: 5, 1: 5 }; + return x[0] + x[1]; +} +testINITELEM.expected = 10; +test(testINITELEM); + +function testUndefinedBooleanCmp() +{ + var t = true, f = false, x = []; + for (var i = 0; i < 10; ++i) { + x[0] = t == undefined; + x[1] = t != undefined; + x[2] = t === undefined; + x[3] = t !== undefined; + x[4] = t < undefined; + x[5] = t > undefined; + x[6] = t <= undefined; + x[7] = t >= undefined; + x[8] = f == undefined; + x[9] = f != undefined; + x[10] = f === undefined; + x[11] = f !== undefined; + x[12] = f < undefined; + x[13] = f > undefined; + x[14] = f <= undefined; + x[15] = f >= undefined; + } + return x.join(","); +} +testUndefinedBooleanCmp.expected = "false,true,false,true,false,false,false,false,false,true,false,true,false,false,false,false"; +test(testUndefinedBooleanCmp); + +function testConstantBooleanExpr() +{ + for (var j = 0; j < 3; ++j) { if(true <= true) { } } + return "ok"; +} +testConstantBooleanExpr.expected = "ok"; +test(testConstantBooleanExpr); + +function testNegativeGETELEMIndex() +{ + for (let i=0;i<3;++i) /x/[-4]; + return "ok"; +} +testNegativeGETELEMIndex.expected = "ok"; +test(testNegativeGETELEMIndex); + +function doTestInvalidCharCodeAt(input) +{ + var q = ""; + for (var i = 0; i < 10; i++) + q += input.charCodeAt(i); + return q; +} +function testInvalidCharCodeAt() +{ + return doTestInvalidCharCodeAt(""); +} +testInvalidCharCodeAt.expected = "NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN"; +test(testInvalidCharCodeAt); + +function FPQuadCmp() +{ + for (let j = 0; j < 3; ++j) { true == 0; } + return "ok"; +} +FPQuadCmp.expected = "ok"; +test(FPQuadCmp); + +function testDestructuring() { + var t = 0; + for (var i = 0; i < HOTLOOP + 1; ++i) { + var [r, g, b] = [1, 1, 1]; + t += r + g + b; + } + return t +} +testDestructuring.expected = (HOTLOOP + 1) * 3; +test(testDestructuring); + +function loopWithUndefined1(t, val) { + var a = new Array(6); + for (var i = 0; i < 6; i++) + a[i] = (t > val); + return a; +} +loopWithUndefined1(5.0, 2); //compile version with val=int + +function testLoopWithUndefined1() { + return loopWithUndefined1(5.0).join(","); //val=undefined +}; +testLoopWithUndefined1.expected = "false,false,false,false,false,false"; +test(testLoopWithUndefined1); + +function loopWithUndefined2(t, dostuff, val) { + var a = new Array(6); + for (var i = 0; i < 6; i++) { + if (dostuff) { + val = 1; + a[i] = (t > val); + } else { + a[i] = (val == undefined); + } + } + return a; +} +function testLoopWithUndefined2() { + var a = loopWithUndefined2(5.0, true, 2); + var b = loopWithUndefined2(5.0, true); + var c = loopWithUndefined2(5.0, false, 8); + var d = loopWithUndefined2(5.0, false); + return [a[0], b[0], c[0], d[0]].join(","); +} +testLoopWithUndefined2.expected = "true,true,false,true"; +test(testLoopWithUndefined2); + +//test no multitrees assert +function testBug462388() { + var c = 0, v; for each (let x in ["",v,v,v]) { for (c=0;c<4;++c) { } } + return true; +} +testBug462388.expected = true; +test(testBug462388); + +//test no multitrees assert +function testBug462407() { + for each (let i in [0, {}, 0, 1.5, {}, 0, 1.5, 0, 0]) { } + return true; +} +testBug462407.expected = true; +test(testBug462407); + +//test no multitrees assert +function testBug463490() { + function f(a, b, d) { + for (var i = 0; i < 10; i++) { + if (d) + b /= 2; + } + return a + b; + } + //integer stable loop + f(2, 2, false); + //double stable loop + f(3, 4.5, false); + //integer unstable branch + f(2, 2, true); + return true; +}; +testBug463490.expected = true; +test(testBug463490); + +// Test no assert (bug 464089) +function shortRecursiveLoop(b, c) { + for (var i = 0; i < c; i++) { + if (b) + shortRecursiveLoop(c - 1); + } +} +function testClosingRecursion() { + shortRecursiveLoop(false, 1); + shortRecursiveLoop(true, 3); + return true; +} +testClosingRecursion.expected = true; +test(testClosingRecursion); + +// Test no assert or crash from outer recorders (bug 465145) +function testBug465145() { + this.__defineSetter__("x", function(){}); + this.watch("x", function(){}); + y = this; + for (var z = 0; z < 2; ++z) { x = y }; + this.__defineSetter__("x", function(){}); + for (var z = 0; z < 2; ++z) { x = y }; +} + +function testTrueShiftTrue() { + var a = new Array(5); + for (var i=0;i<5;++i) a[i] = "" + (true << true); + return a.join(","); +} +testTrueShiftTrue.expected = "2,2,2,2,2"; +test(testTrueShiftTrue); + +// Test no assert or crash +function testBug465261() { + for (let z = 0; z < 2; ++z) { for each (let x in [0, true, (void 0), 0, (void + 0)]) { if(x){} } }; + return true; +} +testBug465261.expected = true; +test(testBug465261); + +function testBug465272() { + var a = new Array(5); + for (j=0;j<5;++j) a[j] = "" + ((5) - 2); + return a.join(","); +} +testBug465272.expected = "3,3,3,3,3" +test(testBug465272); + +function testBug465483() { + var a = new Array(4); + var c = 0; + for each (i in [4, 'a', 'b', (void 0)]) a[c++] = '' + (i + i); + return a.join(','); +} +testBug465483.expected = '8,aa,bb,NaN'; +test(testBug465483); + +function testNullCallee() { + try { + function f() { + var x = new Array(5); + for (var i = 0; i < 5; i++) + x[i] = a[i].toString(); + return x.join(','); + } + f([[1],[2],[3],[4],[5]]); + f([null, null, null, null, null]); + } catch (e) { + return true; + } + return false; +} +testNullCallee.expected = true; +test(testNullCallee); + +//test no multitrees assert +function testBug466128() { + for (let a = 0; a < 3; ++a) { + for each (let b in [1, 2, "three", 4, 5, 6, 7, 8]) { + } + } + return true; +} +testBug466128.expected = true; +test(testBug466128); + +//test no assert +function testBug465688() { + for each (let d in [-0x80000000, -0x80000000]) - -d; + return true; +} +testBug465688.expected = true; +test(testBug465688); + +//test no assert +function testBug466262() { + var e = 1; + for (var d = 0; d < 3; ++d) { + if (d == 2) { + e = ""; + } + } + return true; +} +testBug466262.expected = true; +test(testBug466262); + +function testNewDate() +{ + // Accessing global.Date for the first time will change the global shape, + // so do it before the loop starts; otherwise we have to loop an extra time + // to pick things up. + var start = new Date(); + var time = new Date(); + for (var j = 0; j < RUNLOOP; ++j) + time = new Date(); + return time > 0 && time >= start; +} +testNewDate.expected = true; +testNewDate.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 1 +}; +test(testNewDate); + +function testArrayPushPop() { + var a = [], sum1 = 0, sum2 = 0; + for (var i = 0; i < 10; ++i) + sum1 += a.push(i); + for (var i = 0; i < 10; ++i) + sum2 += a.pop(); + a.push(sum1); + a.push(sum2); + return a.join(","); +} +testArrayPushPop.expected = "55,45"; +test(testArrayPushPop); + +function testSlowArrayPop() { + var a = []; + for (var i = 0; i < RUNLOOP; i++) + a[i] = [0]; + a[RUNLOOP-1].__defineGetter__("0", function () { return 'xyzzy'; }); + + var last; + for (var i = 0; i < RUNLOOP; i++) + last = a[i].pop(); // reenters interpreter in getter + return last; +} +testSlowArrayPop.expected = 'xyzzy'; +test(testSlowArrayPop); + +// Same thing but it needs to reconstruct multiple stack frames (so, +// multiple functions called inside the loop) +function testSlowArrayPopMultiFrame() { + var a = []; + for (var i = 0; i < RUNLOOP; i++) + a[i] = [0]; + a[RUNLOOP-1].__defineGetter__("0", function () { return 23; }); + + function child(a, i) { + return a[i].pop(); // reenters interpreter in getter + } + function parent(a, i) { + return child(a, i); + } + function gramps(a, i) { + return parent(a, i); + } + + var last; + for (var i = 0; i < RUNLOOP; i++) + last = gramps(a, i); + return last; +} +testSlowArrayPopMultiFrame.expected = 23; +test(testSlowArrayPopMultiFrame); + +// Same thing but nested trees, each reconstructing one or more stack frames +// (so, several functions with loops, such that the loops end up being +// nested though they are not lexically nested) + +function testSlowArrayPopNestedTrees() { + var a = []; + for (var i = 0; i < RUNLOOP; i++) + a[i] = [0]; + a[RUNLOOP-1].__defineGetter__("0", function () { return 3.14159 }); + + function child(a, i, j, k) { + var last = 2.71828; + for (var l = 0; l < RUNLOOP; l++) + if (i == RUNLOOP-1 && j == RUNLOOP-1 && k == RUNLOOP-1) + last = a[l].pop(); // reenters interpreter in getter + return last; + } + function parent(a, i, j) { + var last; + for (var k = 0; k < RUNLOOP; k++) + last = child(a, i, j, k); + return last; + } + function gramps(a, i) { + var last; + for (var j = 0; j < RUNLOOP; j++) + last = parent(a, i, j); + return last; + } + + var last; + for (var i = 0; i < RUNLOOP; i++) + last = gramps(a, i); + return last; +} +testSlowArrayPopNestedTrees.expected = 3.14159; +test(testSlowArrayPopNestedTrees); + +function testResumeOp() { + var a = [1,"2",3,"4",5,"6",7,"8",9,"10",11,"12",13,"14",15,"16"]; + var x = ""; + while (a.length > 0) + x += a.pop(); + return x; +} +testResumeOp.expected = "16151413121110987654321"; +test(testResumeOp); + +function testUndefinedCmp() { + var a = false; + for (var j = 0; j < 4; ++j) { if (undefined < false) { a = true; } } + return a; +} +testUndefinedCmp.expected = false; +test(testUndefinedCmp); + +function reallyDeepNestedExit(schedule) +{ + var c = 0, j = 0; + for (var i = 0; i < 5; i++) { + for (j = 0; j < 4; j++) { + c += (schedule[i*4 + j] == 1) ? 1 : 2; + } + } + return c; +} +function testReallyDeepNestedExit() +{ + var c = 0; + var schedule1 = new Array(5*4); + var schedule2 = new Array(5*4); + for (var i = 0; i < 5*4; i++) { + schedule1[i] = 0; + schedule2[i] = 0; + } + /** + * First innermost compile: true branch runs through. + * Second '': false branch compiles new loop edge. + * First outer compile: expect true branch. + * Second '': hit false branch. + */ + schedule1[0*4 + 3] = 1; + var schedules = [schedule1, + schedule2, + schedule1, + schedule2, + schedule2]; + + for (var i = 0; i < 5; i++) { + c += reallyDeepNestedExit(schedules[i]); + } + return c; +} +testReallyDeepNestedExit.expected = 198; +test(testReallyDeepNestedExit); + +function testRegExpTest() { + var r = /abc/; + var flag = false; + for (var i = 0; i < 10; ++i) + flag = r.test("abc"); + return flag; +} +testRegExpTest.expected = true; +test(testRegExpTest); + +function testNumToString() { + var r = []; + var d = 123456789; + for (var i = 0; i < 10; ++i) { + r = [ + d.toString(), + (-d).toString(), + d.toString(10), + (-d).toString(10), + d.toString(16), + (-d).toString(16), + d.toString(36), + (-d).toString(36) + ]; + } + return r.join(","); +} +testNumToString.expected = "123456789,-123456789,123456789,-123456789,75bcd15,-75bcd15,21i3v9,-21i3v9"; +test(testNumToString); + +function testLongNumToString() { + var s; + for (var i = 0; i < 5; i++) + s = (0x08000000).toString(2); + return s; +} +testLongNumToString.expected = '1000000000000000000000000000'; +test(testLongNumToString); + +function testSubstring() { + for (var i = 0; i < 5; ++i) { + actual = "".substring(5); + } + return actual; +} +testSubstring.expected = ""; +test(testSubstring); + +function testForInLoopChangeIteratorType() { + for(y in [0,1,2]) y = NaN; + (function(){ + [].__proto__.u = void 0; + for (let y in [5,6,7,8]) + y = NaN; + delete [].__proto__.u; + })() + return "ok"; +} +testForInLoopChangeIteratorType.expected = "ok"; +test(testForInLoopChangeIteratorType); + +function testGrowDenseArray() { + var a = new Array(); + for (var i = 0; i < 10; ++i) + a[i] |= 5; + return a.join(","); +} +testGrowDenseArray.expected = "5,5,5,5,5,5,5,5,5,5"; +test(testGrowDenseArray); + +function testCallProtoMethod() { + function X() { this.x = 1; } + X.prototype.getName = function () { return "X"; } + + function Y() { this.x = 2; } + Y.prototype.getName = function() "Y"; + + var a = [new X, new X, new X, new X, new Y]; + var s = ''; + for (var i = 0; i < a.length; i++) + s += a[i].getName(); + return s; +} +testCallProtoMethod.expected = 'XXXXY'; +test(testCallProtoMethod); + +function testTypeUnstableForIn() { + var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; + var x = 0; + for (var i in a) { + i = parseInt(i); + x++; + } + return x; +} +testTypeUnstableForIn.expected = 16; +test(testTypeUnstableForIn); + +function testAddUndefined() { + for (var j = 0; j < 3; ++j) + (0 + void 0) && 0; +} +test(testAddUndefined); + +function testStringify() { + var t = true, f = false, u = undefined, n = 5, d = 5.5, s = "x"; + var a = []; + for (var i = 0; i < 10; ++i) { + a[0] = "" + t; + a[1] = t + ""; + a[2] = "" + f; + a[3] = f + ""; + a[4] = "" + u; + a[5] = u + ""; + a[6] = "" + n; + a[7] = n + ""; + a[8] = "" + d; + a[9] = d + ""; + a[10] = "" + s; + a[11] = s + ""; + } + return a.join(","); +} +testStringify.expected = "true,true,false,false,undefined,undefined,5,5,5.5,5.5,x,x"; +test(testStringify); + +function testObjectToString() { + var o = {toString: function()"foo"}; + var s = ""; + for (var i = 0; i < 10; i++) + s += o; + return s; +} +testObjectToString.expected = "foofoofoofoofoofoofoofoofoofoo"; +test(testObjectToString); + +function testObjectToNumber() { + var o = {valueOf: function()-3}; + var x = 0; + for (var i = 0; i < 10; i++) + x -= o; + return x; +} +testObjectToNumber.expected = 30; +test(testObjectToNumber); + +function my_iterator_next() { + if (this.i == 10) { + this.i = 0; + throw this.StopIteration; + } + return this.i++; +} +function testCustomIterator() { + var o = { + __iterator__: function () { + return { + i: 0, + next: my_iterator_next, + StopIteration: StopIteration + }; + } + }; + var a=[]; + for (var k = 0; k < 100; k += 10) { + for(var j in o) { + a[k + (j >> 0)] = j*k; + } + } + return a.join(); +} +testCustomIterator.expected = "0,0,0,0,0,0,0,0,0,0,0,10,20,30,40,50,60,70,80,90,0,20,40,60,80,100,120,140,160,180,0,30,60,90,120,150,180,210,240,270,0,40,80,120,160,200,240,280,320,360,0,50,100,150,200,250,300,350,400,450,0,60,120,180,240,300,360,420,480,540,0,70,140,210,280,350,420,490,560,630,0,80,160,240,320,400,480,560,640,720,0,90,180,270,360,450,540,630,720,810"; +test(testCustomIterator); + +function bug464403() { + print(8); + var u = [print, print, function(){}] + for each (x in u) for (u.e in [1,1,1,1]); + return "ok"; +} +bug464403.expected = "ok"; +test(bug464403); + +function testBoxDoubleWithDoubleSizedInt() +{ + var i = 0; + var a = new Array(3); + + while (i < a.length) + a[i++] = 0x5a827999; + return a.join(","); +} +testBoxDoubleWithDoubleSizedInt.expected = "1518500249,1518500249,1518500249"; +test(testBoxDoubleWithDoubleSizedInt); + +function testObjectOrderedCmp() +{ + var a = new Array(5); + for(var i=0;i<5;++i) a[i] = ({} < {}); + return a.join(","); +} +testObjectOrderedCmp.expected = "false,false,false,false,false"; +test(testObjectOrderedCmp); + +function testObjectOrderedCmp2() +{ + var a = new Array(5); + for(var i=0;i<5;++i) a[i] = ("" <= null); + return a.join(","); +} +testObjectOrderedCmp2.expected = "true,true,true,true,true"; +test(testObjectOrderedCmp2); + +function testLogicalNotNaN() { + var i = 0; + var a = new Array(5); + while (i < a.length) + a[i++] = !NaN; + return a.join(); +} +testLogicalNotNaN.expected = "true,true,true,true,true"; +test(testLogicalNotNaN); + +function testStringToInt32() { + var s = ""; + for (let j = 0; j < 5; ++j) s += ("1e+81" ^ 3); + return s; +} +testStringToInt32.expected = "33333"; +test(testStringToInt32); + +function testIn() { + var array = [3]; + var obj = { "-1": 5, "1.7": 3, "foo": 5, "1": 7 }; + var a = []; + for (let j = 0; j < 5; ++j) { + a.push("0" in array); + a.push(-1 in obj); + a.push(1.7 in obj); + a.push("foo" in obj); + a.push(1 in obj); + a.push("1" in array); + a.push(-2 in obj); + a.push(2.7 in obj); + a.push("bar" in obj); + a.push(2 in obj); + } + return a.join(","); +} +testIn.expected = "true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false"; +test(testIn); + +function testBranchCse() { + empty = []; + out = []; + for (var j=0;j<10;++j) { empty[42]; out.push((1 * (1)) | ""); } + return out.join(","); +} +testBranchCse.expected = "1,1,1,1,1,1,1,1,1,1"; +test(testBranchCse); + +function testMulOverflow() { + var a = []; + for (let j=0;j<5;++j) a.push(0 | ((0x60000009) * 0x60000009)); + return a.join(","); +} +testMulOverflow.expected = "-1073741824,-1073741824,-1073741824,-1073741824,-1073741824"; +test(testMulOverflow); + +function testThinLoopDemote() { + function f() + { + var k = 1; + for (var n = 0; n < 4; n++) { + k = (k * 10); + } + return k; + } + f(); + return f(); +} +testThinLoopDemote.expected = 10000; +testThinLoopDemote.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1, + traceTriggered: 2, + unstableLoopVariable: 0 +}; +test(testThinLoopDemote); + +var global = this; +function testWeirdDateParseOuter() +{ + var vDateParts = ["11", "17", "2008"]; + var out = []; + for (var vI = 0; vI < vDateParts.length; vI++) + out.push(testWeirdDateParseInner(vDateParts[vI])); + /* Mutate the global shape so we fall off trace; this causes + * additional oddity */ + global.x = Math.random(); + return out; +} +function testWeirdDateParseInner(pVal) +{ + var vR = 0; + for (var vI = 0; vI < pVal.length; vI++) { + var vC = pVal.charAt(vI); + if ((vC >= '0') && (vC <= '9')) + vR = (vR * 10) + parseInt(vC); + } + return vR; +} +function testWeirdDateParse() { + var result = []; + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + result = result.concat(testWeirdDateParseOuter()); + result = result.concat(testWeirdDateParseOuter()); + result.push(testWeirdDateParseInner("11")); + result.push(testWeirdDateParseInner("17")); + result.push(testWeirdDateParseInner("2008")); + return result.join(","); +} +testWeirdDateParse.expected = "11,17,2008,11,17,2008,11,17,2008,11,17,2008,11,17,2008"; +testWeirdDateParse.jitstats = { + recorderStarted: 8, + recorderAborted: 1, + traceCompleted: 7, + traceTriggered: 14, + unstableLoopVariable: 3, + noCompatInnerTrees: 1 +}; +test(testWeirdDateParse); + +function testUndemotableBinaryOp() { + var out = []; + for (let j = 0; j < 5; ++j) { out.push(6 - ((void 0) ^ 0x80000005)); } + return out.join(","); +} +testUndemotableBinaryOp.expected = "2147483649,2147483649,2147483649,2147483649,2147483649"; +test(testUndemotableBinaryOp); + +function testNullRelCmp() { + var out = []; + for(j=0;j<3;++j) { out.push(3 > null); out.push(3 < null); out.push(0 == null); out.push(3 == null); } + return out.join(","); +} +testNullRelCmp.expected = "true,false,false,false,true,false,false,false,true,false,false,false"; +test(testNullRelCmp); + +function testEqFalseEmptyString() { + var x = []; + for (var i=0;i<5;++i) x.push(false == ""); + return x.join(","); +} +testEqFalseEmptyString.expected = "true,true,true,true,true"; +test(testEqFalseEmptyString); + +function testIncDec2(ii) { + var x = []; + for (let j=0;j<5;++j) { + ii=j; + jj=j; + var kk=j; + x.push(ii--); + x.push(jj--); + x.push(kk--); + x.push(++ii); + x.push(++jj); + x.push(++kk); + } + return x.join(","); +} +function testIncDec() { + return testIncDec2(0); +} +testIncDec.expected = "0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4"; +test(testIncDec); + +function testApply() { + var q = []; + for (var i = 0; i < 10; ++i) + Array.prototype.push.apply(q, [5]); + return q.join(","); +} +testApply.expected = "5,5,5,5,5,5,5,5,5,5"; +test(testApply); + +function testNestedForIn() { + var a = {x: 1, y: 2, z: 3}; + var s = ''; + for (var p1 in a) + for (var p2 in a) + s += p1 + p2 + ' '; + return s; +} +testNestedForIn.expected = 'xx xy xz yx yy yz zx zy zz '; +test(testNestedForIn); + +function testForEach() { + var r; + var a = ["zero", "one", "two", "three"]; + for (var i = 0; i < RUNLOOP; i++) { + r = ""; + for each (var s in a) + r += s + " "; + } + return r; +} +testForEach.expected = "zero one two three "; +test(testForEach); + +function testThinForEach() { + var a = ["red"]; + var n = 0; + for (var i = 0; i < 10; i++) + for each (var v in a) + if (v) + n++; + return n; +} +testThinForEach.expected = 10; +test(testThinForEach); + +function testComparisons() +{ + // All the special values from each of the types in + // ECMA-262, 3rd ed. section 8 + var undefinedType, nullType, booleanType, stringType, numberType, objectType; + + var types = []; + types[undefinedType = 0] = "Undefined"; + types[nullType = 1] = "Null"; + types[booleanType = 2] = "Boolean"; + types[stringType = 3] = "String"; + types[numberType = 4] = "Number"; + types[objectType = 5] = "Object"; + + var JSVAL_INT_MIN = -Math.pow(2, 30); + var JSVAL_INT_MAX = Math.pow(2, 30) - 1; + + // Values from every ES3 type, hitting all the edge-case and special values + // that can be dreamed up + var values = + { + "undefined": + { + value: function() { return undefined; }, + type: undefinedType + }, + "null": + { + value: function() { return null; }, + type: nullType + }, + "true": + { + value: function() { return true; }, + type: booleanType + }, + "false": + { + value: function() { return false; }, + type: booleanType + }, + '""': + { + value: function() { return ""; }, + type: stringType + }, + '"a"': + { + // a > [, for string-object comparisons + value: function() { return "a"; }, + type: stringType + }, + '"Z"': + { + // Z < [, for string-object comparisons + value: function() { return "Z"; }, + type: stringType + }, + "0": + { + value: function() { return 0; }, + type: numberType + }, + "-0": + { + value: function() { return -0; }, + type: numberType + }, + "1": + { + value: function() { return 1; }, + type: numberType + }, + "Math.E": + { + value: function() { return Math.E; }, + type: numberType + }, + "JSVAL_INT_MIN - 1": + { + value: function() { return JSVAL_INT_MIN - 1; }, + type: numberType + }, + "JSVAL_INT_MIN": + { + value: function() { return JSVAL_INT_MIN; }, + type: numberType + }, + "JSVAL_INT_MIN + 1": + { + value: function() { return JSVAL_INT_MIN + 1; }, + type: numberType + }, + "JSVAL_INT_MAX - 1": + { + value: function() { return JSVAL_INT_MAX - 1; }, + type: numberType + }, + "JSVAL_INT_MAX": + { + value: function() { return JSVAL_INT_MAX; }, + type: numberType + }, + "JSVAL_INT_MAX + 1": + { + value: function() { return JSVAL_INT_MAX + 1; }, + type: numberType + }, + "Infinity": + { + value: function() { return Infinity; }, + type: numberType + }, + "-Infinity": + { + value: function() { return -Infinity; }, + type: numberType + }, + "NaN": + { + value: function() { return NaN; }, + type: numberType + }, + "{}": + { + value: function() { return {}; }, + type: objectType + }, + "{ valueOf: undefined }": + { + value: function() { return { valueOf: undefined }; }, + type: objectType + }, + "[]": + { + value: function() { return []; }, + type: objectType + }, + '[""]': + { + value: function() { return [""]; }, + type: objectType + }, + '["a"]': + { + value: function() { return ["a"]; }, + type: objectType + }, + "[0]": + { + value: function() { return [0]; }, + type: objectType + } + }; + + var orderOps = + { + "<": function(a, b) { return a < b; }, + ">": function(a, b) { return a > b; }, + "<=": function(a, b) { return a <= b; }, + ">=": function(a, b) { return a >= b; } + }; + var eqOps = + { + "==": function(a, b) { return a == b; }, + "!=": function(a, b) { return a != b; }, + "===": function(a, b) { return a === b; }, + "!==": function(a, b) { return a !== b; } + }; + + + var notEqualIncomparable = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + var notEqualLessThan = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": true, ">": false, "<=": true, ">=": false } + }; + var notEqualGreaterThan = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": true, "<=": false, ">=": true } + }; + var notEqualNorDifferent = + { + eq: { "==": false, "!=": true, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var strictlyEqual = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqual = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqualNotDifferent = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var looselyEqualIncomparable = + { + eq: { "==": true, "!=": false, "===": false, "!==": true }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + var strictlyEqualNotDifferent = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": true, ">=": true } + }; + var strictlyEqualIncomparable = + { + eq: { "==": true, "!=": false, "===": true, "!==": false }, + order: { "<": false, ">": false, "<=": false, ">=": false } + }; + + var comparingZeroToSomething = + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqualNotDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": strictlyEqual, + "-0": strictlyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualIncomparable, + "[0]": looselyEqual + }; + + var comparingObjectOrObjectWithValueUndefined = + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualNorDifferent, + "{ valueOf: undefined }": notEqualNorDifferent, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualGreaterThan + }; + + // Constructed expected-value matrix + var expected = + { + "undefined": + { + "undefined": strictlyEqualIncomparable, + "null": looselyEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualIncomparable, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualIncomparable, + '[""]': notEqualIncomparable, + '["a"]': notEqualIncomparable, + "[0]": notEqualIncomparable + }, + "null": + { + "undefined": looselyEqualIncomparable, + "null": strictlyEqualNotDifferent, + "true": notEqualLessThan, + "false": notEqualNorDifferent, + '""': notEqualNorDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualNorDifferent, + "-0": notEqualNorDifferent, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualIncomparable, + "[0]": notEqualNorDifferent + }, + "true": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": strictlyEqual, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": looselyEqual, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "false": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": strictlyEqual, + '""': looselyEqualNotDifferent, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualIncomparable, + "[0]": looselyEqual + }, + '""': + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': strictlyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": looselyEqual, + '[""]': looselyEqual, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '"a"': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': strictlyEqual, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualGreaterThan, + "{ valueOf: undefined }": notEqualGreaterThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': looselyEqualNotDifferent, + "[0]": notEqualGreaterThan + }, + '"Z"': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': strictlyEqual, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualGreaterThan + }, + "0": comparingZeroToSomething, + "-0": comparingZeroToSomething, + "1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": looselyEqual, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": strictlyEqual, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "Math.E": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": strictlyEqual, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MIN - 1": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": strictlyEqual, + "JSVAL_INT_MIN": notEqualLessThan, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MIN": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": strictlyEqual, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MIN + 1": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": strictlyEqual, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "JSVAL_INT_MAX - 1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": strictlyEqual, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MAX": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": strictlyEqual, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "JSVAL_INT_MAX + 1": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": notEqualGreaterThan, + "JSVAL_INT_MAX + 1": strictlyEqual, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "Infinity": + { + "undefined": notEqualIncomparable, + "null": notEqualGreaterThan, + "true": notEqualGreaterThan, + "false": notEqualGreaterThan, + '""': notEqualGreaterThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualGreaterThan, + "-0": notEqualGreaterThan, + "1": notEqualGreaterThan, + "Math.E": notEqualGreaterThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualGreaterThan, + "JSVAL_INT_MAX": notEqualGreaterThan, + "JSVAL_INT_MAX + 1": notEqualGreaterThan, + "Infinity": strictlyEqual, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualGreaterThan + }, + "-Infinity": + { + "undefined": notEqualIncomparable, + "null": notEqualLessThan, + "true": notEqualLessThan, + "false": notEqualLessThan, + '""': notEqualLessThan, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualLessThan, + "-0": notEqualLessThan, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualLessThan, + "JSVAL_INT_MIN": notEqualLessThan, + "JSVAL_INT_MIN + 1": notEqualLessThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": strictlyEqual, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualLessThan, + '[""]': notEqualLessThan, + '["a"]': notEqualIncomparable, + "[0]": notEqualLessThan + }, + "NaN": + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualIncomparable, + '"a"': notEqualIncomparable, + '"Z"': notEqualIncomparable, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualIncomparable, + "{ valueOf: undefined }": notEqualIncomparable, + "[]": notEqualIncomparable, + '[""]': notEqualIncomparable, + '["a"]': notEqualIncomparable, + "[0]": notEqualIncomparable + }, + "{}": comparingObjectOrObjectWithValueUndefined, + "{ valueOf: undefined }": comparingObjectOrObjectWithValueUndefined, + "[]": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '[""]': + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': looselyEqual, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualNorDifferent, + '[""]': notEqualNorDifferent, + '["a"]': notEqualLessThan, + "[0]": notEqualLessThan + }, + '["a"]': + { + "undefined": notEqualIncomparable, + "null": notEqualIncomparable, + "true": notEqualIncomparable, + "false": notEqualIncomparable, + '""': notEqualGreaterThan, + '"a"': looselyEqual, + '"Z"': notEqualGreaterThan, + "0": notEqualIncomparable, + "-0": notEqualIncomparable, + "1": notEqualIncomparable, + "Math.E": notEqualIncomparable, + "JSVAL_INT_MIN - 1": notEqualIncomparable, + "JSVAL_INT_MIN": notEqualIncomparable, + "JSVAL_INT_MIN + 1": notEqualIncomparable, + "JSVAL_INT_MAX - 1": notEqualIncomparable, + "JSVAL_INT_MAX": notEqualIncomparable, + "JSVAL_INT_MAX + 1": notEqualIncomparable, + "Infinity": notEqualIncomparable, + "-Infinity": notEqualIncomparable, + "NaN": notEqualIncomparable, + "{}": notEqualGreaterThan, + "{ valueOf: undefined }": notEqualGreaterThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualNorDifferent, + "[0]": notEqualGreaterThan + }, + "[0]": + { + "undefined": notEqualIncomparable, + "null": notEqualNorDifferent, + "true": notEqualLessThan, + "false": looselyEqual, + '""': notEqualGreaterThan, + '"a"': notEqualLessThan, + '"Z"': notEqualLessThan, + "0": looselyEqual, + "-0": looselyEqual, + "1": notEqualLessThan, + "Math.E": notEqualLessThan, + "JSVAL_INT_MIN - 1": notEqualGreaterThan, + "JSVAL_INT_MIN": notEqualGreaterThan, + "JSVAL_INT_MIN + 1": notEqualGreaterThan, + "JSVAL_INT_MAX - 1": notEqualLessThan, + "JSVAL_INT_MAX": notEqualLessThan, + "JSVAL_INT_MAX + 1": notEqualLessThan, + "Infinity": notEqualLessThan, + "-Infinity": notEqualGreaterThan, + "NaN": notEqualIncomparable, + "{}": notEqualLessThan, + "{ valueOf: undefined }": notEqualLessThan, + "[]": notEqualGreaterThan, + '[""]': notEqualGreaterThan, + '["a"]': notEqualLessThan, + "[0]": notEqualNorDifferent + } + }; + + + + var failures = []; + function fail(a, ta, b, tb, ex, ac, op) + { + failures.push("(" + a + " " + op + " " + b + ") wrong: " + + "expected " + ex + ", got " + ac + + " (types " + types[ta] + ", " + types[tb] + ")"); + } + + var result = false; + for (var i in values) + { + for (var j in values) + { + // Constants, so hoist to help JIT know that + var vala = values[i], valb = values[j]; + var a = vala.value(), b = valb.value(); + + for (var opname in orderOps) + { + var op = orderOps[opname]; + var expect = expected[i][j].order[opname]; + var failed = false; + + for (var iter = 0; iter < 5; iter++) + { + result = op(a, b); + failed = failed || result !== expect; + } + + if (failed) + fail(i, vala.type, j, valb.type, expect, result, opname); + } + + for (var opname in eqOps) + { + var op = eqOps[opname]; + var expect = expected[i][j].eq[opname]; + var failed = false; + + for (var iter = 0; iter < 5; iter++) + { + result = op(a, b); + failed = failed || result !== expect; + } + + if (failed) + fail(i, vala.type, j, valb.type, expect, result, opname); + } + } + } + + if (failures.length == 0) + return "no failures reported!"; + + return "\n" + failures.join(",\n"); +} +testComparisons.expected = "no failures reported!"; +test(testComparisons); + +function testBug504520() { + // A bug involving comparisons. + var arr = [1/0, 1/0, 1/0, 1/0, 1/0, 0]; + assertEq(arr.length > RUNLOOP, true); + + var s = ''; + for (var i = 0; i < arr.length; i++) + arr[i] >= 1/0 ? null : (s += i); + assertEq(s, '5'); +} +test(testBug504520); + +function testBug504520Harder() { + // test 1024 similar cases + var vals = [1/0, -1/0, 0, 0/0]; + var ops = ["===", "!==", "==", "!=", "<", ">", "<=", ">="]; + for each (var x in vals) { + for each (var y in vals) { + for each (var op in ops) { + for each (var z in vals) { + // Assume eval is correct. This depends on the global + // Infinity property not having been reassigned. + var xz = eval(x + op + z); + var yz = eval(y + op + z); + + var arr = [x, x, x, x, x, y]; + assertEq(arr.length > RUNLOOP, true); + var expected = [xz, xz, xz, xz, xz, yz]; + + // ?: looks superfluous but that's what we're testing here + var fun = eval( + '(function (arr, results) {\n' + + ' for (let i = 0; i < arr.length; i++)\n' + + ' results.push(arr[i]' + op + z + ' ? "true" : "false");\n' + + '});\n'); + var actual = []; + fun(arr, actual); + assertEq("" + actual, "" + expected); + } + } + } + } +} +test(testBug504520Harder); + +function testCaseAbort() +{ + var four = "4"; + var r = 0; + for (var i = 0; i < 5; i++) + { + switch (i) + { + case four: r += 1; break; + default: r += 2; break; + } + } + + return "" + r; +} +testCaseAbort.expected = "10"; +testCaseAbort.jitstats = { + recorderAborted: 0 +}; +test(testCaseAbort); + +function testApplyCallHelper(f) { + var r = []; + for (var i = 0; i < 10; ++i) f.call(); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4]); + r.push(x); + for (var i = 0; i < 10; ++i) f.call(this,0,1,2,3,4,5); + r.push(x); + for (var i = 0; i < 10; ++i) f.apply(this,[0,1,2,3,4,5]) + r.push(x); + return(r.join(",")); +} +function testApplyCall() { + var r = testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; }); + r += testApplyCallHelper(function (a0,a1,a2,a3,a4,a5,a6,a7) { x = [a0,a1,a2,a3,a4,a5,a6,a7]; }); + return r; +} +testApplyCall.expected = +",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,," + +",,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,,0,,,,,,,,0,1,,,,,,,0,1,,,,,,,0,1,2,,,,,,0,1,2,,,,,,0,1,2,3,,,,,0,1,2,3,,,,,0,1,2,3,4,,,,0,1,2,3,4,,,,0,1,2,3,4,5,,,0,1,2,3,4,5,,"; +test(testApplyCall); + +function testApplyUnboxHelper(f,a) { + var q; + for (var i = 0; i < 10; ++i) + q = f.apply(f,a); + return q; +} +function testApplyUnbox() { + var f = function(x) { return x; } + return [testApplyUnboxHelper(f,[1]), testApplyUnboxHelper(f,[true])].join(","); +} +testApplyUnbox.expected = "1,true"; +test(testApplyUnbox); + +function testCallPick() { + function g(x,a) { + x.f(); + } + + var x = []; + x.f = function() { } + + var y = []; + y.f = function() { } + + var z = [x,x,x,x,x,y,y,y,y,y]; + + for (var i = 0; i < 10; ++i) + g.call(this, z[i], ""); + return true; +} +testCallPick.expected = true; +test(testCallPick); + +function testInvertNullAfterNegateNull() +{ + for (var i = 0; i < 5; i++) !null; + for (var i = 0; i < 5; i++) -null; + return "no assertion"; +} +testInvertNullAfterNegateNull.expected = "no assertion"; +test(testInvertNullAfterNegateNull); + +function testUnaryImacros() +{ + function checkArg(x) + { + return 1; + } + + var o = { valueOf: checkArg, toString: null }; + var count = 0; + var v = 0; + for (var i = 0; i < 5; i++) + v += +o + -(-o); + + var results = [v === 10 ? "valueOf passed" : "valueOf failed"]; + + o.valueOf = null; + o.toString = checkArg; + + for (var i = 0; i < 5; i++) + v += +o + -(-o); + + results.push(v === 20 ? "toString passed" : "toString failed"); + + return results.join(", "); +} +testUnaryImacros.expected = "valueOf passed, toString passed"; +test(testUnaryImacros); + +function testAddAnyInconvertibleObject() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return "" + count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = 5 + o; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "594") + return "expected q === '594', got " + q + " (type " + typeof q + ")"; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with 5 + o"; // hey, a rhyme! + + return "pass"; +} +testAddAnyInconvertibleObject.expected = "pass"; +testAddAnyInconvertibleObject.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testAddAnyInconvertibleObject); + +function testAddInconvertibleObjectAny() +{ + var count = 0; + function toString() + { + ++count; + if (count == 95) + return {}; + return "" + count; + } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o + 5; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "945") + return "expected q === '945', got " + q + " (type " + typeof q + ")"; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with o + 5"; + + return "pass"; +} +testAddInconvertibleObjectAny.expected = "pass"; +testAddInconvertibleObjectAny.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testAddInconvertibleObjectAny); + +function testAddInconvertibleObjectInconvertibleObject() +{ + var count1 = 0; + function toString1() { ++count1; if (count1 == 95) return {}; return "" + count1; } + var o1 = {valueOf: undefined, toString: toString1}; + var count2 = 0; + function toString2() { ++count2; if (count2 == 95) return {}; return "" + count2; } + var o2 = {valueOf: undefined, toString: toString2}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o1 + o2; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== "9494") + return "expected q === '9494', got " + q + " (type " + typeof q + ")"; + if (count1 !== 95) + return "expected count1 === 95, got " + count1; + if (count2 !== 94) + return "expected count2 === 94, got " + count2; + } + if (!threw) + return "expected throw with o1 + o2"; + + return "pass"; +} +testAddInconvertibleObjectInconvertibleObject.expected = "pass"; +testAddInconvertibleObjectInconvertibleObject.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testAddInconvertibleObjectInconvertibleObject); + +function testBitOrAnyInconvertibleObject() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = 1 | o; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 95) + return "expected q === 95, got " + q; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with 2 | o"; // hey, a rhyme! + + return "pass"; +} +testBitOrAnyInconvertibleObject.expected = "pass"; +testBitOrAnyInconvertibleObject.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testBitOrAnyInconvertibleObject); + +function testBitOrInconvertibleObjectAny() +{ + var count = 0; + function toString() { ++count; if (count == 95) return {}; return count; } + var o = {valueOf: undefined, toString: toString}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o | 1; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 95) + return "expected q === 95, got " + q; + if (count !== 95) + return "expected count === 95, got " + count; + } + if (!threw) + return "expected throw with o | 2"; + + return "pass"; +} +testBitOrInconvertibleObjectAny.expected = "pass"; +testBitOrInconvertibleObjectAny.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testBitOrInconvertibleObjectAny); + +function testBitOrInconvertibleObjectInconvertibleObject() +{ + var count1 = 0; + function toString1() { ++count1; if (count1 == 95) return {}; return count1; } + var o1 = {valueOf: undefined, toString: toString1}; + var count2 = 0; + function toString2() { ++count2; if (count2 == 95) return {}; return count2; } + var o2 = {valueOf: undefined, toString: toString2}; + + var threw = false; + try + { + for (var i = 0; i < 100; i++) + var q = o1 | o2; + } + catch (e) + { + threw = true; + if (i !== 94) + return "expected i === 94, got " + i; + if (q !== 94) + return "expected q === 94, got " + q; + if (count1 !== 95) + return "expected count1 === 95, got " + count1; + if (count2 !== 94) + return "expected count2 === 94, got " + count2; + } + if (!threw) + return "expected throw with o1 | o2"; + + return "pass"; +} +testBitOrInconvertibleObjectInconvertibleObject.expected = "pass"; +testBitOrInconvertibleObjectInconvertibleObject.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 3 +}; +test(testBitOrInconvertibleObjectInconvertibleObject); + +function testCaseTypeMismatchBadness() +{ + for (var z = 0; z < 3; ++z) + { + switch ("") + { + default: + case 9: + break; + + case "": + case <x/>: + break; + } + } + + return "no crash"; +} +testCaseTypeMismatchBadness.expected = "no crash"; +testCaseTypeMismatchBadness.jitstats = { + recorderAborted: 0 +}; +test(testCaseTypeMismatchBadness); + +function testDoubleComparison() +{ + for (var i = 0; i < 500000; ++i) + { + switch (1 / 0) + { + case Infinity: + } + } + + return "finished"; +} +testDoubleComparison.expected = "finished"; +testDoubleComparison.jitstats = { + sideExitIntoInterpreter: 1 +}; +test(testDoubleComparison); + +function testLirBufOOM() +{ + var a = [ + "12345678901234", + "123456789012", + "1234567890123456789012345678", + "12345678901234567890123456789012345678901234567890123456", + "f", + "$", + "", + "f()", + "(\\*)", + "b()", + "()", + "(#)", + "ABCDEFGHIJK", + "ABCDEFGHIJKLM", + "ABCDEFGHIJKLMNOPQ", + "ABCDEFGH", + "(.)", + "(|)", + "()$", + "/()", + "(.)$" + ]; + + for (var j = 0; j < 200; ++j) { + var js = "" + j; + for (var i = 0; i < a.length; i++) + "".match(a[i] + js) + } + return "ok"; +} +testLirBufOOM.expected = "ok"; +test(testLirBufOOM); + +function testStringResolve() { + var x = 0; + for each (let d in [new String('q'), new String('q'), new String('q')]) { + if (("" + (0 in d)) === "true") + x++; + } + return x; +} +testStringResolve.expected = 3; +test(testStringResolve); + +//test no multitrees assert +function testGlobalMultitrees1() { + (function() { + for (var j = 0; j < 4; ++j) { + for each (e in ['A', 1, 'A']) { + } + } + })(); + return true; +} +testGlobalMultitrees1.expected = true; +test(testGlobalMultitrees1); + +var q = []; +for each (b in [0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF]) { + for each (let e in [{}, {}, {}, "", {}]) { + b = (b | 0x40000000) + 1; + q.push(b); + } +} +function testLetWithUnstableGlobal() { + return q.join(","); +} +testLetWithUnstableGlobal.expected = "2147483648,-1073741823,-1073741822,-1073741821,-1073741820,2147483648,-1073741823,-1073741822,-1073741821,-1073741820,2147483648,-1073741823,-1073741822,-1073741821,-1073741820"; +test(testLetWithUnstableGlobal); +delete b; +delete q; + +for each (testBug474769_b in [1, 1, 1, 1.5, 1, 1]) { + (function() { for each (let testBug474769_h in [0, 0, 1.4, ""]) {} })() +} +function testBug474769() { + return testBug474769_b; +} +testBug474769.expected = 1; +test(testBug474769); + +function testReverseArgTypes() { + for (var j = 0; j < 4; ++j) ''.replace('', /x/); + return 1; +} +testReverseArgTypes.expected = 1; +test(testReverseArgTypes); + +function testBug458838() { + var a = 1; + function g() { + var b = 0 + for (var i = 0; i < 10; ++i) { + b += a; + } + return b; + } + + return g(); +} +testBug458838.expected = 10; +testBug458838.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceCompleted: 1 +}; +test(testBug458838); + +function testInterpreterReentry() { + this.__defineSetter__('x', function(){}) + for (var j = 0; j < 5; ++j) { x = 3; } + return 1; +} +testInterpreterReentry.expected = 1; +test(testInterpreterReentry); + +function testInterpreterReentry2() { + var a = false; + var b = {}; + var c = false; + var d = {}; + this.__defineGetter__('e', function(){}); + for (let f in this) print(f); + [1 for each (g in this) for each (h in [])] + return 1; +} +testInterpreterReentry2.expected = 1; +test(testInterpreterReentry2); + +function testInterpreterReentry3() { + for (let i=0;i<5;++i) this["y" + i] = function(){}; + this.__defineGetter__('e', function (x2) { yield; }); + [1 for each (a in this) for (b in {})]; + return 1; +} +testInterpreterReentry3.expected = 1; +test(testInterpreterReentry3); + +function testInterpreterReentry4() { + var obj = {a:1, b:1, c:1, d:1, get e() 1000 }; + for (var p in obj) + obj[p]; +} +test(testInterpreterReentry4); + +function testInterpreterReentry5() { + var arr = [0, 1, 2, 3, 4]; + arr.__defineGetter__("4", function() 1000); + for (var i = 0; i < 5; i++) + arr[i]; + for (var p in arr) + arr[p]; +} +test(testInterpreterReentry5); + +function testInterpreterReentry6() { + var obj = {a:1, b:1, c:1, d:1, set e(x) { this._e = x; }}; + for (var p in obj) + obj[p] = "grue"; + return obj._e; +} +testInterpreterReentry6.expected = "grue"; +test(testInterpreterReentry6); + +function testInterpreterReentry7() { + var arr = [0, 1, 2, 3, 4]; + arr.__defineSetter__("4", function(x) { this._4 = x; }); + for (var i = 0; i < 5; i++) + arr[i] = "grue"; + var tmp = arr._4; + for (var p in arr) + arr[p] = "bleen"; + return tmp + " " + arr._4; +} +testInterpreterReentry7.expected = "grue bleen"; +test(testInterpreterReentry7); + +// Bug 462027 comment 54. +function testInterpreterReentery8() { + var e = <x><y/></x>; + for (var j = 0; j < 4; ++j) { +[e]; } +} +test(testInterpreterReentery8); + +function testHolePushing() { + var a = ["foobar", "baz"]; + for (var i = 0; i < 5; i++) + a = [, "overwritten", "new"]; + var s = "["; + for (i = 0; i < a.length; i++) { + s += (i in a) ? a[i] : "<hole>"; + if (i != a.length - 1) + s += ","; + } + return s + "], " + (0 in a); +} +testHolePushing.expected = "[<hole>,overwritten,new], false"; +test(testHolePushing); + +function testDeepBail1() { + var y = <z/>; + for (var i = 0; i < RUNLOOP; i++) + "" in y; +} +test(testDeepBail1); + +/* Array comprehension tests */ + +function Range(start, stop) { + this.i = start; + this.stop = stop; +} +Range.prototype = { + __iterator__: function() this, + next: function() { + if (this.i >= this.stop) + throw StopIteration; + return this.i++; + } +}; + +function range(start, stop) { + return new Range(start, stop); +} + +function testArrayComp1() { + return [a for (a in range(0, 10))].join(''); +} +testArrayComp1.expected='0123456789'; +test(testArrayComp1); + +function testArrayComp2() { + return [a + b for (a in range(0, 5)) for (b in range(0, 5))].join(''); +} +testArrayComp2.expected='0123412345234563456745678'; +test(testArrayComp2); + +function testSwitchUndefined() +{ + var x = undefined; + var y = 0; + for (var i = 0; i < 5; i++) + { + switch (x) + { + default: + y++; + } + } + return y; +} +testSwitchUndefined.expected = 5; +test(testSwitchUndefined); + +function testTableSwitch1() { + var x = 'miss'; + var i, j = 0; + for (i = 0; i < RUNLOOP + 10; i++) { + switch (x) { + case 1: case 2: case 3: case 4: case 5: throw "FAIL"; + default: j++; + } + } + assertEq(i, j); +} +testTableSwitch1.jitstats = { + recorderStarted: 1, + sideExitIntoInterpreter: 1, + recorderAborted: 0, + traceCompleted: 1 +}; +test(testTableSwitch1); + +function testTableSwitch2() { + var arr = [2, 2, 2, 2, 2, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5]; + var s = ''; + for (var i = 0; i < arr.length; i++) { + switch (arr[i]) { + case 0: case 1: case 3: case 4: + throw "FAIL"; + case 2: + s += '2'; + break; + case 5: + s += '5'; + } + } + assertEq(s, arr.join("")); +} +testTableSwitch2.jitstats = { + recorderStarted: 1, + sideExitIntoInterpreter: 4, + recorderAborted: 0, + traceCompleted: 3 +}; +test(testTableSwitch2); + +function testGeneratorDeepBail() { + function g() { yield 2; } + var iterables = [[1], [], [], [], g()]; + + var total = 0; + for (let i = 0; i < iterables.length; i++) + for each (let j in iterables[i]) + total += j; + return total; +} +testGeneratorDeepBail.expected = 3; +test(testGeneratorDeepBail); + +function testRegexpGet() { + var re = /hi/; + var a = []; + for (let i = 0; i < 5; ++i) + a.push(re.source); + return a.toString(); +} +testRegexpGet.expected = "hi,hi,hi,hi,hi"; +test(testRegexpGet); + +function testThrowingObjectEqUndefined() +{ + try + { + var obj = { toString: function() { throw 0; } }; + for (var i = 0; i < 5; i++) + "" + (obj == undefined); + return i === 5; + } + catch (e) + { + return "" + e; + } +} +testThrowingObjectEqUndefined.expected = true; +testThrowingObjectEqUndefined.jitstats = { + sideExitIntoInterpreter: 1 +}; +test(testThrowingObjectEqUndefined); + +function x4(v) { return "" + v + v + v + v; } +function testConvertibleObjectEqUndefined() +{ + var compares = + [ + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + false, false, false, false, + undefined, undefined, undefined, undefined, + ]; + var count = 0; + var obj = { valueOf: function() { count++; return 1; } }; + var results = compares.map(function(v) { return "unwritten"; }); + + for (var i = 0, sz = compares.length; i < sz; i++) + results[i] = compares[i] == obj; + + return results.join("") + count; +} +testConvertibleObjectEqUndefined.expected = + x4(false) + x4(false) + x4(false) + x4(false) + x4(false) + x4(false) + + x4(false) + x4(false) + x4(false) + x4(false) + "20"; +testConvertibleObjectEqUndefined.jitstats = { + sideExitIntoInterpreter: 3 +}; +test(testConvertibleObjectEqUndefined); + +function testUndefinedPropertyAccess() { + var x = [1,2,3]; + var y = {}; + var a = { foo: 1 }; + y.__proto__ = x; + var z = [x, x, x, y, y, y, y, a, a, a]; + var s = ""; + for (var i = 0; i < z.length; ++i) + s += z[i].foo; + return s; +} +testUndefinedPropertyAccess.expected = "undefinedundefinedundefinedundefinedundefinedundefinedundefined111"; +testUndefinedPropertyAccess.jitstats = { + traceCompleted: 3 +}; +test(testUndefinedPropertyAccess); + +q = ""; +function g() { q += "g"; } +function h() { q += "h"; } +a = [g, g, g, g, h]; +for (i=0; i<5; i++) { f = a[i]; f(); } + +function testRebranding() { + return q; +} +testRebranding.expected = "ggggh"; +test(testRebranding); +delete q; +delete g; +delete h; +delete a; +delete f; + +function testRebranding2() { + // Same as testRebranding, but the object to be rebranded isn't the global. + var x = "FAIL"; + function g(){} + function h(){ x = "ok"; } + var obj = {m: g}; + var arr = [g, g, g, g, h]; + assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < 5; i++) { + obj.m = arr[i]; + obj.m(); + } + return x; +} +testRebranding2.expected = "ok"; +test(testRebranding2); + +function testBug502914() { + // Assigning a non-function to a function-valued property on trace should + // bump the shape. + function f1() {} + function C() {} + var x = C.prototype = {m: f1}; + x.m(); // brand scope + var arr = [new C, new C, new C, x]; + try { + for (var i = 0; i < 4; i++) { + arr[i].m = 12; + x.m(); // should throw last time through + } + } catch (exc) { + return exc.constructor.name; + } + return "no exception"; +} +testBug502914.expected = "TypeError"; +test(testBug502914); + +function testLambdaCtor() { + var a = []; + for (var x = 0; x < RUNLOOP; ++x) { + var f = function(){}; + a[a.length] = new f; + } + + // This prints false until the upvar2 bug is fixed: + // print(a[HOTLOOP].__proto__ !== a[HOTLOOP-1].__proto__); + + // Assert that the last f was properly constructed. + return a[RUNLOOP-1].__proto__ === f.prototype; +} +testLambdaCtor.expected = true; +test(testLambdaCtor); + +function testNonStubGetter() { + let ([] = false) { (this.watch("x", /a/g)); }; + (function () { (eval("(function(){for each (x in [1, 2, 2]);});"))(); })(); + this.unwatch("x"); + return "ok"; +} +testNonStubGetter.expected = "ok"; +test(testNonStubGetter); + +function testString() { + var q; + for (var i = 0; i <= RUNLOOP; ++i) { + q = []; + q.push(String(void 0)); + q.push(String(true)); + q.push(String(5)); + q.push(String(5.5)); + q.push(String("5")); + q.push(String([5])); + } + return q.join(","); +} +testString.expected = "undefined,true,5,5.5,5,5"; +testString.jitstats = { + recorderStarted: 1, + sideExitIntoInterpreter: 1 +}; +test(testString); + +function testToStringBeforeValueOf() +{ + var o = {toString: function() { return "s"; }, valueOf: function() { return "v"; } }; + var a = []; + for (var i = 0; i < 10; i++) + a.push(String(o)); + return a.join(","); +} +testToStringBeforeValueOf.expected = "s,s,s,s,s,s,s,s,s,s"; +testToStringBeforeValueOf.jitstats = { + recorderStarted: 1, + sideExitIntoInterpreter: 1 +}; +test(testToStringBeforeValueOf); + +function testNullToString() +{ + var a = []; + for (var i = 0; i < 10; i++) + a.push(String(null)); + for (i = 0; i < 10; i++) { + var t = typeof a[i]; + if (t != "string") + a.push(t); + } + return a.join(","); +} +testNullToString.expected = "null,null,null,null,null,null,null,null,null,null"; +testNullToString.jitstats = { + recorderStarted: 2, + sideExitIntoInterpreter: 2, + recorderAborted: 0 +}; +test(testNullToString); + +function testAddNull() +{ + var rv; + for (var x = 0; x < HOTLOOP + 1; ++x) + rv = null + [,,]; + return rv; +} +testAddNull.expected = "null,"; +testAddNull.jitstats = { + recorderStarted: 1, + sideExitIntoInterpreter: 1, + recorderAborted: 0 +}; +test(testAddNull); + +function testClosures() +{ + function MyObject(id) { + var thisObject = this; + this.id = id; + this.toString = str; + + function str() { + return "" + this.id + thisObject.id; + } + } + + var a = []; + for (var i = 0; i < 5; i++) + a.push(new MyObject(i)); + return a.toString(); +} +testClosures.expected = "00,11,22,33,44"; +test(testClosures); + +function testMoreClosures() { + var f = {}, max = 3; + + var hello = function(n) { + function howdy() { return n * n } + f.test = howdy; + }; + + for (var i = 0; i <= max; i++) + hello(i); + + return f.test(); +} +testMoreClosures.expected = 9; +test(testMoreClosures); + +function testLambdaInitedVar() { + var jQuery = function (a, b) { + return jQuery && jQuery.length; + } + return jQuery(); +} + +testLambdaInitedVar.expected = 2; +test(testLambdaInitedVar); + +function testNestedEscapingLambdas() +{ + try { + return (function() { + var a = [], r = []; + function setTimeout(f, t) { + a.push(f); + } + + function runTimeouts() { + for (var i = 0; i < a.length; i++) + a[i](); + } + + var $foo = "#nothiddendiv"; + setTimeout(function(){ + r.push($foo); + setTimeout(function(){ + r.push($foo); + }, 100); + }, 100); + + runTimeouts(); + + return r.join(""); + })(); + } catch (e) { + return e; + } +} +testNestedEscapingLambdas.expected = "#nothiddendiv#nothiddendiv"; +test(testNestedEscapingLambdas); + +function testPropagatedFunArgs() +{ + var win = this; + var res = [], q = []; + function addEventListener(name, func, flag) { + q.push(func); + } + + var pageInfo, obs; + addEventListener("load", handleLoad, true); + + var observer = { + observe: function(win, topic, data) { + // obs.removeObserver(observer, "page-info-dialog-loaded"); + handlePageInfo(); + } + }; + + function handleLoad() { + pageInfo = { toString: function() { return "pageInfo"; } }; + obs = { addObserver: function (obs, topic, data) { obs.observe(win, topic, data); } }; + obs.addObserver(observer, "page-info-dialog-loaded", false); + } + + function handlePageInfo() { + res.push(pageInfo); + function $(aId) { res.push(pageInfo); }; + var feedTab = $("feedTab"); + } + + q[0](); + return res.join(','); +} +testPropagatedFunArgs.expected = "pageInfo,pageInfo"; +test(testPropagatedFunArgs); + +// Second testPropagatedFunArgs test -- this is a crash-test. +(function () { + var escapee; + + function testPropagatedFunArgs() + { + const magic = 42; + + var win = this; + var res = [], q = []; + function addEventListener(name, func, flag) { + q.push(func); + } + + var pageInfo = "pageInfo", obs; + addEventListener("load", handleLoad, true); + + var observer = { + observe: function(win, topic, data) { + // obs.removeObserver(observer, "page-info-dialog-loaded"); + handlePageInfo(); + } + }; + + function handleLoad() { + //pageInfo = { toString: function() { return "pageInfo"; } }; + obs = { addObserver: function (obs, topic, data) { obs.observe(win, topic, data); } }; + obs.addObserver(observer, "page-info-dialog-loaded", false); + } + + function handlePageInfo() { + res.push(pageInfo); + function $(aId) { + function notSafe() { + return magic; + } + notSafe(); + res.push(pageInfo); + }; + var feedTab = $("feedTab"); + } + + escapee = q[0]; + return res.join(','); + } + + testPropagatedFunArgs(); + + escapee(); +})(); + +function testStringLengthNoTinyId() +{ + var x = "unset"; + var t = new String(""); + for (var i = 0; i < 5; i++) + x = t["-1"]; + + var r = "t['-1'] is " + x; + t["-1"] = "foo"; + r += " when unset, '" + t["-1"] + "' when set"; + return r; +} +testStringLengthNoTinyId.expected = "t['-1'] is undefined when unset, 'foo' when set"; +test(testStringLengthNoTinyId); + +function testLengthInString() +{ + var s = new String(); + var res = "length" in s; + for (var i = 0; i < 5; i++) + res = res && ("length" in s); + res = res && s.hasOwnProperty("length"); + for (var i = 0; i < 5; i++) + res = res && s.hasOwnProperty("length"); + return res; +} +testLengthInString.expected = true; +test(testLengthInString); + +function testSlowArrayLength() +{ + var counter = 0; + var a = []; + a[10000000 - 1] = 0; + for (var i = 0; i < a.length; i++) + counter++; + return counter; +} +testSlowArrayLength.expected = 10000000; +testSlowArrayLength.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 1 +}; +test(testSlowArrayLength); + +function testObjectLength() +{ + var counter = 0; + var a = {}; + a.length = 10000000; + for (var i = 0; i < a.length; i++) + counter++; + return counter; +} +testObjectLength.expected = 10000000; +testObjectLength.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 1 +}; +test(testObjectLength); + +function testChangingObjectWithLength() +{ + var obj = { length: 10 }; + var dense = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + var slow = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; slow.slow = 5; + + /* + * The elements of objs constitute a De Bruijn sequence repeated 4x to trace + * and run native code for every object and transition. + */ + var objs = [obj, obj, obj, obj, + obj, obj, obj, obj, + dense, dense, dense, dense, + obj, obj, obj, obj, + slow, slow, slow, slow, + dense, dense, dense, dense, + dense, dense, dense, dense, + slow, slow, slow, slow, + slow, slow, slow, slow, + obj, obj, obj, obj]; + + var counter = 0; + + for (var i = 0, sz = objs.length; i < sz; i++) + { + var o = objs[i]; + for (var j = 0; j < o.length; j++) + counter++; + } + + return counter; +} +testChangingObjectWithLength.expected = 400; +testChangingObjectWithLength.jitstats = { + recorderAborted: 0, + sideExitIntoInterpreter: 15 // empirically determined +}; +test(testChangingObjectWithLength); + +function testNEWINIT() +{ + var a; + for (var i = 0; i < 10; ++i) + a = [{}]; + return uneval(a); +} +testNEWINIT.expected = "[{}]"; +test(testNEWINIT); + +function testNEWINIT_DOUBLE() +{ + for (var z = 0; z < 2; ++z) { ({ 0.1: null })} + return "ok"; +} +testNEWINIT_DOUBLE.expected = "ok"; +test(testNEWINIT_DOUBLE); + +function testIntOverflow() { + // int32_max - 7 + var ival = 2147483647 - 7; + for (var i = 0; i < 30; i++) { + ival += 2; + } + return (ival < 2147483647); +} +testIntOverflow.expected = false; +testIntOverflow.jitstats = { + recorderStarted: 2, + recorderAborted: 0, + traceCompleted: 2, + traceTriggered: 2, +}; +test(testIntOverflow); + +function testIntUnderflow() { + // int32_min + 8 + var ival = -2147483648 + 8; + for (var i = 0; i < 30; i++) { + ival -= 2; + } + return (ival > -2147483648); +} +testIntUnderflow.expected = false; +testIntUnderflow.jitstats = { + recorderStarted: 2, + recorderAborted: 0, + traceCompleted: 2, + traceTriggered: 2, +}; +test(testIntUnderflow); + +function testCALLELEM() +{ + function f() { + return 5; + } + + function g() { + return 7; + } + + var x = [f,f,f,f,g]; + var y = 0; + for (var i = 0; i < 5; ++i) + y = x[i](); + return y; +} +testCALLELEM.expected = 7; +test(testCALLELEM); + +function testNewString() +{ + var o = { toString: function() { return "string"; } }; + var r = []; + for (var i = 0; i < 5; i++) + r.push(typeof new String(o)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(3)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(2.5)); + for (var i = 0; i < 5; i++) + r.push(typeof new String("string")); + for (var i = 0; i < 5; i++) + r.push(typeof new String(null)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(true)); + for (var i = 0; i < 5; i++) + r.push(typeof new String(undefined)); + return r.length === 35 && r.every(function(v) { return v === "object"; }); +} +testNewString.expected = true; +testNewString.jitstats = { + recorderStarted: 7, + recorderAborted: 0, + traceCompleted: 7, + sideExitIntoInterpreter: 7 +}; +test(testNewString); + +function testWhileObjectOrNull() +{ + try + { + for (var i = 0; i < 3; i++) + { + var o = { p: { p: null } }; + while (o.p) + o = o.p; + } + return "pass"; + } + catch (e) + { + return "threw exception: " + e; + } +} +testWhileObjectOrNull.expected = "pass"; +test(testWhileObjectOrNull); + +function testDenseArrayProp() +{ + [].__proto__.x = 1; + ({}).__proto__.x = 2; + var a = [[],[],[],({}).__proto__]; + for (var i = 0; i < a.length; ++i) + uneval(a[i].x); + delete [].__proto__.x; + delete ({}).__proto__.x; + return "ok"; +} +testDenseArrayProp.expected = "ok"; +test(testDenseArrayProp); + +function testNewWithNonNativeProto() +{ + function f() { } + var a = f.prototype = []; + for (var i = 0; i < 5; i++) + var o = new f(); + return Object.getPrototypeOf(o) === a && o.splice === Array.prototype.splice; +} +testNewWithNonNativeProto.expected = true; +testNewWithNonNativeProto.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + sideExitIntoInterpreter: 1 +}; +test(testNewWithNonNativeProto); + +function testLengthOnNonNativeProto() +{ + var o = {}; + o.__proto__ = [3]; + for (var j = 0; j < 5; j++) + o[0]; + + var o2 = {}; + o2.__proto__ = []; + for (var j = 0; j < 5; j++) + o2.length; + + function foo() { } + foo.__proto__ = []; + for (var j = 0; j < 5; j++) + foo.length; + + return "no assertion"; +} +testLengthOnNonNativeProto.expected = "no assertion"; +test(testLengthOnNonNativeProto); + +function testDeepPropertyShadowing() +{ + function h(node) { + var x = 0; + while (node) { + x++; + node = node.parent; + } + return x; + } + var tree = {__proto__: {__proto__: {parent: null}}}; + h(tree); + h(tree); + tree.parent = {}; + assertEq(h(tree), 2); +} +test(testDeepPropertyShadowing); + +// Complicated whitebox test for bug 487845. +function testGlobalShapeChangeAfterDeepBail() { + function f(name) { + this[name] = 1; // may change global shape + for (var i = 0; i < 4; i++) + ; // MonitorLoopEdge eventually triggers assertion + } + + // When i==3, deep-bail, then change global shape enough times to exhaust + // the array of GlobalStates. + var arr = [[], [], [], ["bug0", "bug1", "bug2", "bug3", "bug4"]]; + for (var i = 0; i < arr.length; i++) + arr[i].forEach(f); +} +test(testGlobalShapeChangeAfterDeepBail); +for (let i = 0; i < 5; i++) + delete this["bug" + i]; + +function testFunctionIdentityChange() +{ + function a() {} + function b() {} + + var o = { a: a, b: b }; + + for (var prop in o) + { + for (var i = 0; i < 1000; i++) + o[prop](); + } + + return true; +} +testFunctionIdentityChange.expected = true; +testFunctionIdentityChange.jitstats = { + recorderStarted: 2, + traceCompleted: 2, + sideExitIntoInterpreter: 3 +}; +test(testFunctionIdentityChange); + +function testStringObjectLength() { + var x = new String("foo"), y = 0; + for (var i = 0; i < 10; ++i) + y = x.length; + return y; +} +testStringObjectLength.expected = 3; +test(testStringObjectLength); + +var _quit; +function testNestedDeepBail() +{ + _quit = false; + function loop() { + for (var i = 0; i < 4; i++) + ; + } + loop(); + + function f() { + loop(); + _quit = true; + } + var stk = [[1], [], [], [], []]; + while (!_quit) + stk.pop().forEach(f); +} +test(testNestedDeepBail); +delete _quit; + +function testSlowNativeCtor() { + for (var i = 0; i < 4; i++) + new Date().valueOf(); +} +test(testSlowNativeCtor); + +function testSlowNativeBail() { + var a = ['0', '1', '2', '3', '+']; + try { + for (var i = 0; i < a.length; i++) + new RegExp(a[i]); + } catch (exc) { + assertEq(""+exc.stack.match(/^RegExp/), "RegExp"); + } +} +test(testSlowNativeBail); + +/* Test the proper operation of the left shift operator. This is especially + * important on ARM as an explicit mask is required at the native instruction + * level. */ +function testShiftLeft() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = 1 << (shifts[i] + 256); + + return r.join(","); +} +testShiftLeft.expected = + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648,"+ + "1,2,128,256,32768,65536,8388608,16777216,-2147483648"; +test(testShiftLeft); + +/* Test the proper operation of the logical right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ +function testShiftRightLogical() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >>> (shifts[i] + 256); + + return r.join(","); +} +/* Note: Arguments to the ">>>" operator are converted to unsigned 32-bit + * integers during evaluation. As a result, -2147483648 >>> 0 evaluates to the + * unsigned interpretation of the same value, which is 2147483648. */ +testShiftRightLogical.expected = + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1,"+ + "2147483648,1073741824,16777216,8388608,65536,32768,256,128,1"; +test(testShiftRightLogical); + +/* Test the proper operation of the arithmetic right shift operator. This is + * especially important on ARM as an explicit mask is required at the native + * instruction level. */ +function testShiftRightArithmetic() +{ + var r = []; + var i = 0; + var j = 0; + + var shifts = [0,1,7,8,15,16,23,24,31]; + + /* Samples from the simple shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> shifts[i]; + + /* Samples outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 32); + + /* Samples far outside the normal shift range. */ + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 224); + for (i = 0; i < shifts.length; i++) + r[j++] = -2147483648 >> (shifts[i] + 256); + + return r.join(","); +} +testShiftRightArithmetic.expected = + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1,"+ + "-2147483648,-1073741824,-16777216,-8388608,-65536,-32768,-256,-128,-1"; +test(testShiftRightArithmetic); + +function testStringConstructorWithExtraArg() { + for (let i = 0; i < 5; ++i) + new String(new String(), 2); + return "ok"; +} +testStringConstructorWithExtraArg.expected = "ok"; +test(testStringConstructorWithExtraArg); + +function testConstructorBail() { + for (let i = 0; i < 5; ++i) new Number(/x/); +} +test(testConstructorBail); + +function testNewArrayCount() +{ + var a = []; + for (var i = 0; i < 5; i++) + a = [0]; + assertEq(a.__count__, 1); + for (var i = 0; i < 5; i++) + a = [0, , 2]; + assertEq(a.__count__, 2); +} +test(testNewArrayCount); + +function testNewArrayCount2() { + var x = 0; + for (var i = 0; i < 10; ++i) + x = new Array(1,2,3).__count__; + return x; +} +testNewArrayCount2.expected = 3; +test(testNewArrayCount2); + +function testGetCallObjInlined(i) { + if (i > 7) eval("1"); + return 1; +} + +function testGetCallObj() { + for (var i = 0; i < 10; ++i) + testGetCallObjInlined(i); + return "ok"; +} +testGetCallObj.expected = "ok"; +test(testGetCallObj); + +function testGetThis() { + for (var i = 0; i < 3; ++i) { + (function() { return this; })(); + } + return "ok"; +} +testGetThis.expected = "ok"; +test(testGetThis); + +function testArrayNamedProp() { + for (var x = 0; x < 10; ++x) { [4].sort-- } + return "ok"; +} +testArrayNamedProp.expected = "ok"; +test(testArrayNamedProp); + +function testUndemoteLateGlobalSlots() { + for each (aaa in ["", "", 0/0, ""]) { + ++aaa; + for each (bbb in [0, "", aaa, "", 0, "", 0/0]) { + } + } + delete aaa; + delete bbb; + return "ok"; +} +testUndemoteLateGlobalSlots.expected = "ok"; +test(testUndemoteLateGlobalSlots); + +function testSetProtoRegeneratesObjectShape() +{ + var f = function() {}; + var g = function() {}; + g.prototype.__proto__ = {}; + + function iq(obj) + { + for (var i = 0; i < 10; ++i) + "" + obj.prototype; + } + + iq(f); + iq(f); + iq(f); + iq(f); + iq(g); + + if (shapeOf(f.prototype) === shapeOf(g.prototype)) + return "object shapes same after proto of one is changed"; + + return true; +} +testSetProtoRegeneratesObjectShape.expected = true; +test(testSetProtoRegeneratesObjectShape); + +function testFewerGlobalsInInnerTree() { + for each (a in [new Number(1), new Number(1), {}, {}, new Number(1)]) { + for each (b in [2, "", 2, "", "", ""]) { + for each (c in [{}, {}, 3, 3, 3, 3, {}, {}]) { + 4 + a; + } + } + } + delete a; + delete b; + delete c; + return "ok"; +} +testFewerGlobalsInInnerTree.expected = "ok"; +test(testFewerGlobalsInInnerTree); + +function testMethodInit() { // bug 503198 + function o() { return 'o'; } + function k() { return 'k'; } + + var x; + for (var i = 0; i < 10; i++) + x = {o: o, k: k}; + return x.o() + x.k(); +} +testMethodInit.expected = "ok"; +testMethodInit.jitstats = { + recorderStarted: 1, + traceCompleted: 1, + sideExitIntoInterpreter: 1 +}; +test(testMethodInit); + +function testMethodSet() { // bug 503198 + function o() { return 'o'; } + function k() { return 'k'; } + + var x; + for (var i = 0; i < 10; i++) { + x = {}; + x.o = o; + x.k = k; + } + return x.o() + x.k(); +} +testMethodSet.expected = "ok"; +testMethodSet.jitstats = { + recorderStarted: 1, + traceCompleted: 1, + sideExitIntoInterpreter: 1 +}; +test(testMethodSet); + +function testMethodInitSafety() { + function f() { return 'fail'; } + function g() { return 'ok'; } + + var s; + var arr = [f, f, f, f, g]; + assertEq(arr.length > RUNLOOP, true); + for (var i = 0; i < arr.length; i++) { + var x = {m: arr[i]}; + s = x.m(); + } + return s; +} +testMethodInitSafety.expected = "ok"; +test(testMethodInitSafety); + +function testModuloWithNegative1() { + var v = 0; + for (var i = 0; i < 2; ++i) { + c = v; + v -= 1; + for (var j = 0; j < 2; ++j) + c %= -1; + } + return 1/c; +} +testModuloWithNegative1.expected = -Infinity; +test(testModuloWithNegative1); + +function testDivisionWithNegative1() { + for (var i = 3; i >= 0; --i) + c = i / -1; + return 1/c; +} +testDivisionWithNegative1.expected = -Infinity; +test(testDivisionWithNegative1); + +function testInt32ToId() +{ + // Ensure that a property which is a negative integer that does not fit in a + // jsval is properly detected by the 'in' operator. + var obj = { "-1073741828": 17 }; + var index = -1073741819; + var a = []; + for (var i = 0; i < 10; i++) + { + a.push(index in obj); + index--; + } + + // Ensure that a property which is a negative integer that does not fit in a + // jsval is properly *not* detected by the 'in' operator. In this case + // wrongly applying INT_TO_JSID to -2147483648 will shift off the sign bit + // (the only bit set in that number) and bitwise-or that value with 1, + // producing jsid(1) -- which actually represents "0", not "-2147483648". + // Thus 'in' will report a "-2147483648" property when none exists, because + // it thinks the request was really whether the object had property "0". + var obj2 = { 0: 17 }; + var b = []; + var index = -(1 << 28); + for (var i = 0; i < 10; i++) + { + b.push(index in obj2); + index = index - (1 << 28); + } + + return a.join(",") + b.join(","); +} +testInt32ToId.expected = + "false,false,false,false,false,false,false,false,false,true" + + "false,false,false,false,false,false,false,false,false,false"; +testInt32ToId.jitstats = { + sideExitIntoInterpreter: 2 +}; +test(testInt32ToId); + +function testOwnPropertyWithInOperator() +{ + var o = { 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6 }; + var a = []; + for (var i = 0; i < 7; i++) + a.push(i in o); + return a.join(","); +} +testOwnPropertyWithInOperator.expected = "true,true,true,true,true,true,true"; +testOwnPropertyWithInOperator.jitstats = { + sideExitIntoInterpreter: 1 +}; +test(testOwnPropertyWithInOperator); + +function testBug501690() { + // Property cache assertion when 3 objects along a prototype chain have the same shape. + function B(){} + B.prototype = {x: 123}; + + function D(){} + D.prototype = new B; + D.prototype.x = 1; // [1] shapeOf(B.prototype) == shapeOf(D.prototype) + + arr = [new D, new D, new D, D.prototype]; // [2] all the same shape + for (var i = 0; i < 4; i++) + assertEq(arr[i].x, 1); // same kshape [2], same vshape [1] +} +test(testBug501690); + +function testObjectVsPrototype() { + function D() {} + var b = D.prototype = {x: 1}; + var d = new D; + var arr = [b, b, b, d]; + for (var i = 0; i < 4; i++) + arr[i].x = i; + + d.y = 12; + assertEq(d.x, 3); +} +test(testObjectVsPrototype); + +function testEliminatedGuardWithinAnchor() { + for (let i = 0; i < 5; ++i) { i / (i * i); } + return "ok"; +} +testEliminatedGuardWithinAnchor.expected = "ok"; +testOwnPropertyWithInOperator.jitstats = { + sideExitIntoInterpreter: 3 +}; +test(testEliminatedGuardWithinAnchor); + +function testNativeSetter() { + var re = /foo/; + var N = RUNLOOP + 10; + for (var i = 0; i < N; i++) + re.lastIndex = i; + assertEq(re.lastIndex, N - 1); +} +testNativeSetter.jitstats = { + recorderStarted: 1, + recorderAborted: 0, + traceTriggered: 1, + sideExitIntoInterpreter: 1 +}; +test(testNativeSetter); + +function testBug507425() { + var r = /x/; + for (var i = 0; i < 3; i++) + r.lastIndex = 0; // call a setter + var s = ';'; + try { + for (i = 0; i < 80; i++) + s += s; // call js_CanLeaveTrace + } catch (exc) { + return "ok"; + } +} +testBug507425.expected = "ok"; +test(testBug507425); + +/***************************************************************************** + * * + * _____ _ _ _____ ______ _____ _______ * + * |_ _| \ | |/ ____| ____| __ \__ __| * + * | | | \| | (___ | |__ | |__) | | | * + * | | | . ` |\___ \| __| | _ / | | * + * _| |_| |\ |____) | |____| | \ \ | | * + * |_____|_| \_|_____/|______|_| \_\ |_| * + * * + * * + * _______ ______ _____ _______ _____ * + * |__ __| ____|/ ____|__ __/ ____| * + * | | | |__ | (___ | | | (___ * + * | | | __| \___ \ | | \___ \ * + * | | | |____ ____) | | | ____) | * + * |_| |______|_____/ |_| |_____/ * + * * + * * + * ____ ______ ______ ____ _____ ______ _ _ ______ _____ ______ * + * | _ \| ____| ____/ __ \| __ \| ____| | | | | ____| __ \| ____| * + * | |_) | |__ | |__ | | | | |__) | |__ | |__| | |__ | |__) | |__ * + * | _ <| __| | __|| | | | _ /| __| | __ | __| | _ /| __| * + * | |_) | |____| | | |__| | | \ \| |____ | | | | |____| | \ \| |____ * + * |____/|______|_| \____/|_| \_\______| |_| |_|______|_| \_\______| * + * * + *****************************************************************************/ + +load(gSrcdir + "/math-trace-tests.js"); + +// BEGIN MANDELBROT STUFF +// XXXbz I would dearly like to wrap it up into a function to avoid polluting +// the global scope, but the function ends up heavyweight, and then we lose on +// the jit. +if (gDoMandelbrotTest) { +load(gSrcdir + "/mandelbrot-results.js"); +//function testMandelbrotAll() { + // Configuration options that affect which codepaths we follow. + var doImageData = true; + var avoidSparseArray = true; + + // Control of iteration numbers and sizing. We'll do + // scaler * colorNames.length iterations or so before deciding that we + // don't escape. + const scaler = 5; + const numRows = 600; + const numCols = 600; + + const colorNames = [ + "black", + "green", + "blue", + "red", + "purple", + "orange", + "cyan", + "yellow", + "magenta", + "brown", + "pink", + "chartreuse", + "darkorange", + "crimson", + "gray", + "deeppink", + "firebrick", + "lavender", + "lawngreen", + "lightsalmon", + "lime", + "goldenrod" + ]; + const threshold = (colorNames.length - 1) * scaler; + + // Now set up our colors + var colors = []; + // 3-part for loop (iterators buggy, we will add a separate test for them) + for (var colorNameIdx = 0; colorNameIdx < colorNames.length; ++colorNameIdx) { + //for (var colorNameIdx in colorNames) { + colorNameIdx = parseInt(colorNameIdx); + colors.push([colorNameIdx, colorNameIdx, colorNameIdx, 0]); + } + + // Storage for our point data + var points; + + var scratch = {}; + var scratchZ = {}; + function complexMult(a, b) { + var newr = a.r * b.r - a.i * b.i; + var newi = a.r * b.i + a.i * b.r; + scratch.r = newr; + scratch.i = newi; + return scratch; + } + function complexAdd(a, b) { + scratch.r = a.r + b.r; + scratch.i = a.i + b.i; + return scratch; + } + function abs(a) { + return Math.sqrt(a.r * a.r + a.i * a.i); + } + + function escapeAbsDiff(normZ, absC) { + var absZ = Math.sqrt(normZ); + return normZ > absZ + absC; + } + + function escapeNorm2(normZ) { + return normZ > 4; + } + + function fuzzyColors(i) { + return Math.floor(i / scaler) + 1; + } + + function moddedColors(i) { + return (i % (colorNames.length - 1)) + 1; + } + + function computeEscapeSpeedObjects(real, imag) { + var c = { r: real, i: imag } + scratchZ.r = scratchZ.i = 0; + var absC = abs(c); + for (var i = 0; i < threshold; ++i) { + scratchZ = complexAdd(c, complexMult(scratchZ, scratchZ)); + if (escape(scratchZ.r * scratchZ.r + scratchZ.i * scratchZ.i, + absC)) { + return colorMap(i); + } + } + return 0; + } + + function computeEscapeSpeedOneObject(real, imag) { + // fold in the fact that we start with 0 + var r = real; + var i = imag; + var absC = abs({r: real, i: imag}); + for (var j = 0; j < threshold; ++j) { + var r2 = r * r; + var i2 = i * i; + if (escape(r2 + i2, absC)) { + return colorMap(j); + } + i = 2 * r * i + imag; + r = r2 - i2 + real; + } + return 0; + } + + function computeEscapeSpeedDoubles(real, imag) { + // fold in the fact that we start with 0 + var r = real; + var i = imag; + var absC = Math.sqrt(real * real + imag * imag); + for (var j = 0; j < threshold; ++j) { + var r2 = r * r; + var i2 = i * i; + if (escape(r2 + i2, absC)) { + return colorMap(j); + } + i = 2 * r * i + imag; + r = r2 - i2 + real; + } + return 0; + } + + var computeEscapeSpeed = computeEscapeSpeedDoubles; + var escape = escapeNorm2; + var colorMap = fuzzyColors; + + function addPointOrig(pointArray, n, i, j) { + if (!points[n]) { + points[n] = []; + points[n].push([i, j, 1, 1]); + } else { + var point = points[n][points[n].length-1]; + if (point[0] == i && point[1] == j - point[3]) { + ++point[3]; + } else { + points[n].push([i, j, 1, 1]); + } + } + } + + function addPointImagedata(pointArray, n, col, row) { + var slotIdx = ((row * numCols) + col) * 4; + pointArray[slotIdx] = colors[n][0]; + pointArray[slotIdx+1] = colors[n][1]; + pointArray[slotIdx+2] = colors[n][2]; + pointArray[slotIdx+3] = colors[n][3]; + } + + function createMandelSet() { + var realRange = { min: -2.1, max: 1 }; + var imagRange = { min: -1.5, max: 1.5 }; + + var addPoint; + if (doImageData) { + addPoint = addPointImagedata; + points = new Array(4*numCols*numRows); + if (avoidSparseArray) { + for (var idx = 0; idx < 4*numCols*numRows; ++idx) { + points[idx] = 0; + } + } + } else { + addPoint = addPointOrig; + points = []; + } + var realStep = (realRange.max - realRange.min)/numCols; + var imagStep = (imagRange.min - imagRange.max)/numRows; + for (var i = 0, curReal = realRange.min; + i < numCols; + ++i, curReal += realStep) { + for (var j = 0, curImag = imagRange.max; + j < numRows; + ++j, curImag += imagStep) { + var n = computeEscapeSpeed(curReal, curImag); + addPoint(points, n, i, j) + } + } + var result; + if (doImageData) { + if (colorMap == fuzzyColors) { + result = mandelbrotImageDataFuzzyResult; + } else { + result = mandelbrotImageDataModdedResult; + } + } else { + result = mandelbrotNoImageDataResult; + } + return points.toSource() == result; + } + + createMandelSet.expected = true; + + const escapeTests = [ escapeAbsDiff ]; + const colorMaps = [ fuzzyColors, moddedColors ]; + const escapeComputations = [ computeEscapeSpeedObjects, + computeEscapeSpeedOneObject, + computeEscapeSpeedDoubles ]; + // Test all possible escape-speed generation codepaths, using the + // imageData + sparse array avoidance storage. + doImageData = true; + avoidSparseArray = true; + for (var escapeIdx in escapeTests) { + escape = escapeTests[escapeIdx]; + for (var colorMapIdx in colorMaps) { + colorMap = colorMaps[colorMapIdx]; + for (var escapeComputationIdx in escapeComputations) { + computeEscapeSpeed = escapeComputations[escapeComputationIdx]; + test(createMandelSet); + } + } + } + + // Test all possible storage strategies. Note that we already tested + // doImageData == true with avoidSparseArray == true. + escape = escapeAbsDiff; + colorMap = fuzzyColors; // This part doesn't really matter too much here + computeEscapeSpeed = computeEscapeSpeedDoubles; + + doImageData = true; + avoidSparseArray = false; + test(createMandelSet); + + escape = escapeNorm2; + doImageData = false; // avoidSparseArray doesn't matter here + test(createMandelSet); +//} +//testMandelbrotAll(); +} /* if (gDoMandelbrotTest) */ +// END MANDELBROT STUFF + +/***************************************************************************** + * _ _ ____ _ __ ____ _____ ______ * + * | \ | |/ __ \ | \/ |/ __ \| __ \| ____| * + * | \| | | | | | \ / | | | | |__) | |__ * + * | . ` | | | | | |\/| | | | | _ /| __| * + * | |\ | |__| | | | | | |__| | | \ \| |____ * + * |_| \_|\____/ |_| |_|\____/|_| \_\______| * + * * + * _______ ______ _____ _______ _____ * + * |__ __| ____|/ ____|__ __/ ____| * + * | | | |__ | (___ | | | (___ * + * | | | __| \___ \ | | \___ \ * + * | | | |____ ____) | | | ____) | * + * |_| |______|_____/ |_| |_____/ * + * * + * ______ _______ ______ _____ _ _ ______ _____ ______ _ * + * /\ | ____|__ __| ____| __ \ | | | | ____| __ \| ____| | * + * / \ | |__ | | | |__ | |__) | | |__| | |__ | |__) | |__ | | * + * / /\ \ | __| | | | __| | _ / | __ | __| | _ /| __| | | * + * / ____ \| | | | | |____| | \ \ | | | | |____| | \ \| |____|_| * + * /_/ \_\_| |_| |______|_| \_\ |_| |_|______|_| \_\______(_) * + * * + *****************************************************************************/ + +/* NOTE: Keep this test last, since it screws up all for...in loops after it. */ +function testGlobalProtoAccess() { + return "ok"; +} +this.__proto__.a = 3; for (var j = 0; j < 4; ++j) { [a]; } +testGlobalProtoAccess.expected = "ok"; +test(testGlobalProtoAccess); + +/* Keep these at the end so that we can see the summary after the trace-debug spew. */ +if (gReportSummary) { + print("\npassed:", passes.length && passes.join(",")); + print("\nFAILED:", fails.length && fails.join(",")); +} |