blob: b42bedcbe6e369ece4b07ff557dfdc0142701594 [file] [log] [blame]
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JavaScript Engine testing utilities.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Mike Shaver
* Brendan Eich
* Andreas Gal
* David Anderson
* Boris Zbarsky
* Brian Crowder
* Blake Kaplan
* Robert Sayre
* Vladimir Vukicevic
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gTestfile = 'trace-test.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 'none';
var summary = 'trace-capability mini-testsuite';
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
/**
* 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");
}
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)
{
var pass = false;
if (close_enough(expected, actual)) {
pass = true;
jitstatHandler(function(prop) {
if (expectedJITstats && prop in expectedJITstats &&
expectedJITstats[prop] !=
tracemonkey[prop] - oldJITstats[prop]) {
pass = false;
}
});
if (pass) {
reportCompare(expected, actual, desc);
passes.push(desc);
return print("TEST-PASS | trace-test.js |", desc);
}
}
if (expected instanceof RegExp) {
pass = reportMatch(expected, actual + '', desc);
if (pass) {
jitstatHandler(function(prop) {
if (expectedJITstats && prop in expectedJITstats &&
expectedJITstats[prop] !=
tracemonkey[prop] - oldJITstats[prop]) {
pass = false;
}
});
}
if (pass) {
passes.push(desc);
return print(desc, ": passed");
}
}
reportCompare(expected, actual, 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|{},\[\],{"foo":"bar"})/;
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: 2,
recorderAborted: 0,
traceCompleted: 2,
traceTriggered: 2,
unstableLoopVariable: 1
};
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 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 threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o = {valueOf: undefined, toString: toString};
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: 93
};
test(testAddAnyInconvertibleObject);
function testAddInconvertibleObjectAny()
{
var count = 0;
function toString()
{
++count;
if (count == 95)
return {};
return "" + count;
}
var threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o = {valueOf: undefined, toString: toString};
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: 93
};
test(testAddInconvertibleObjectAny);
function testAddInconvertibleObjectInconvertibleObject()
{
var count1 = 0;
function toString1() { ++count1; if (count1 == 95) return {}; return "" + count1; }
var count2 = 0;
function toString2() { ++count2; if (count2 == 95) return {}; return "" + count2; }
var threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o1 = {valueOf: undefined, toString: toString1};
var o2 = {valueOf: undefined, toString: toString2};
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: 93
};
test(testAddInconvertibleObjectInconvertibleObject);
function testBitOrAnyInconvertibleObject()
{
var count = 0;
function toString() { ++count; if (count == 95) return {}; return count; }
var threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o = {valueOf: undefined, toString: toString};
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: 93
};
test(testBitOrAnyInconvertibleObject);
function testBitOrInconvertibleObjectAny()
{
var count = 0;
function toString() { ++count; if (count == 95) return {}; return count; }
var threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o = {valueOf: undefined, toString: toString};
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: 93
};
test(testBitOrInconvertibleObjectAny);
function testBitOrInconvertibleObjectInconvertibleObject()
{
var count1 = 0;
function toString1() { ++count1; if (count1 == 95) return {}; return count1; }
var count2 = 0;
function toString2() { ++count2; if (count2 == 95) return {}; return count2; }
var threw = false;
try
{
for (var i = 0; i < 100; i++)
{
var o1 = {valueOf: undefined, toString: toString1};
var o2 = {valueOf: undefined, toString: toString2};
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: 93
};
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 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 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);
/*****************************************************************************
* *
* _____ _ _ _____ ______ _____ _______ *
* |_ _| \ | |/ ____| ____| __ \__ __| *
* | | | \| | (___ | |__ | |__) | | | *
* | | | . ` |\___ \| __| | _ / | | *
* _| |_| |\ |____) | |____| | \ \ | | *
* |_____|_| \_|_____/|______|_| \_\ |_| *
* *
* *
* _______ ______ _____ _______ _____ *
* |__ __| ____|/ ____|__ __/ ____| *
* | | | |__ | (___ | | | (___ *
* | | | __| \___ \ | | \___ \ *
* | | | |____ ____) | | | ____) | *
* |_| |______|_____/ |_| |_____/ *
* *
* *
* ____ ______ ______ ____ _____ ______ _ _ ______ _____ ______ *
* | _ \| ____| ____/ __ \| __ \| ____| | | | | ____| __ \| ____| *
* | |_) | |__ | |__ | | | | |__) | |__ | |__| | |__ | |__) | |__ *
* | _ <| __| | __|| | | | _ /| __| | __ | __| | _ /| __| *
* | |_) | |____| | | |__| | | \ \| |____ | | | | |____| | \ \| |____ *
* |____/|______|_| \____/|_| \_\______| |_| |_|______|_| \_\______| *
* *
*****************************************************************************/
// math-trace-tests.js is a separate file here.
// MANDELBROT STUFF deleted
/*****************************************************************************
* _ _ ____ _ __ ____ _____ ______ *
* | \ | |/ __ \ | \/ |/ __ \| __ \| ____| *
* | \| | | | | | \ / | | | | |__) | |__ *
* | . ` | | | | | |\/| | | | | _ /| __| *
* | |\ | |__| | | | | | |__| | | \ \| |____ *
* |_| \_|\____/ |_| |_|\____/|_| \_\______| *
* *
* _______ ______ _____ _______ _____ *
* |__ __| ____|/ ____|__ __/ ____| *
* | | | |__ | (___ | | | (___ *
* | | | __| \___ \ | | \___ \ *
* | | | |____ ____) | | | ____) | *
* |_| |______|_____/ |_| |_____/ *
* *
* ______ _______ ______ _____ _ _ ______ _____ ______ _ *
* /\ | ____|__ __| ____| __ \ | | | | ____| __ \| ____| | *
* / \ | |__ | | | |__ | |__) | | |__| | |__ | |__) | |__ | | *
* / /\ \ | __| | | | __| | _ / | __ | __| | _ /| __| | | *
* / ____ \| | | | | |____| | \ \ | | | | |____| | \ \| |____|_| *
* /_/ \_\_| |_| |______|_| \_\ |_| |_|______|_| \_\______(_) *
* *
*****************************************************************************/
/* 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);
jit(false);
/* 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(","));
}