2 * A number of the tests in this file depend on the setting of
3 * HOTLOOP. Define some constants up front, so they're easy to grep
6 // The HOTLOOP constant we depend on; only readable from our stats
7 // object in debug builds.
8 const haveTracemonkey
= !!(this.tracemonkey
)
9 const HOTLOOP
= haveTracemonkey
? tracemonkey
.HOTLOOP
: 2;
10 // The loop count at which we trace
11 const RECORDLOOP
= HOTLOOP
;
12 // The loop count at which we run the trace
13 const RUNLOOP
= HOTLOOP
+ 1;
16 if ("arguments" in this && arguments
.length
> 0)
17 testName
= arguments
[0];
18 var fails
= [], passes
=[];
20 function jitstatHandler(f
)
22 if (!haveTracemonkey
) {
25 // XXXbz this is a nasty hack, but I can't figure out a way to
26 // just use jitstats.tbl here
30 f("sideExitIntoInterpreter");
31 f("typeMapMismatchAtEntry");
32 f("returnToDifferentLoopHeader");
34 f("globalShapeMismatchAtEntry");
37 f("unstableLoopVariable");
44 if (!testName
|| testName
== f
.name
) {
45 // Collect our jit stats
46 var localJITstats
= {};
47 jitstatHandler(function(prop
, local
, global
) {
48 localJITstats
[prop
] = tracemonkey
[prop
];
50 check(f
.name
, f(), f
.expected
, localJITstats
, f
.jitstats
);
54 function check(desc
, actual
, expected
, oldJITstats
, expectedJITstats
)
56 if (expected
== actual
) {
58 jitstatHandler(function(prop
) {
59 if (expectedJITstats
&& prop
in expectedJITstats
&&
60 expectedJITstats
[prop
] !=
61 tracemonkey
[prop
] - oldJITstats
[prop
]) {
67 return print(desc
, ": passed");
71 var expectedStats
= "";
72 if (expectedJITstats
) {
73 jitstatHandler(function(prop
) {
74 if (prop
in expectedJITstats
) {
78 prop
+ ": " + expectedJITstats
[prop
];
83 if (expectedJITstats
) {
84 jitstatHandler(function(prop
) {
85 if (prop
in expectedJITstats
) {
88 actualStats
+= prop
+ ": " + (tracemonkey
[prop
]-oldJITstats
[prop
]);
92 print(desc
, ": FAILED: expected", typeof(expected
), "(", expected
, ")",
93 (expectedStats
? " [" + expectedStats
+ "] " : ""),
95 typeof(actual
), "(", actual
, ")",
96 (actualStats
? " [" + actualStats
+ "] " : ""));
99 function ifInsideLoop()
101 var cond
= true, intCond
= 5, count
= 0;
102 for (var i
= 0; i
< 100; i
++) {
110 ifInsideLoop
.expected
= 200;
113 function bitwiseAnd_inner(bitwiseAndValue
) {
114 for (var i
= 0; i
< 60000; i
++)
115 bitwiseAndValue
= bitwiseAndValue
& i
;
116 return bitwiseAndValue
;
118 function bitwiseAnd()
120 return bitwiseAnd_inner(12341234);
122 bitwiseAnd
.expected
= 0;
125 if (!testName
|| testName
== "bitwiseGlobal") {
126 bitwiseAndValue
= Math
.pow(2,32);
127 for (var i
= 0; i
< 60000; i
++)
128 bitwiseAndValue
= bitwiseAndValue
& i
;
129 check("bitwiseGlobal", bitwiseAndValue
, 0);
135 var i1
= 55, one
= 1, zero
= 0, undef
;
136 var o1
= { }, o2
= { };
138 var hits
= [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
139 for (var i
= 0; i
< 5000; i
++) {
140 if (i1
== 55) hits
[0]++;
141 if (i1
!= 56) hits
[1]++;
142 if (i1
< 56) hits
[2]++;
143 if (i1
> 50) hits
[3]++;
144 if (i1
<= 60) hits
[4]++;
145 if (i1
>= 30) hits
[5]++;
146 if (i1
== 7) hits
[6]++;
147 if (i1
!= 55) hits
[7]++;
148 if (i1
< 30) hits
[8]++;
149 if (i1
> 90) hits
[9]++;
150 if (i1
<= 40) hits
[10]++;
151 if (i1
>= 70) hits
[11]++;
152 if (o1
== o2
) hits
[12]++;
153 if (o2
!= null) hits
[13]++;
154 if (s
< 10) hits
[14]++;
155 if (true < zero
) hits
[15]++;
156 if (undef
> one
) hits
[16]++;
157 if (undef
< zero
) hits
[17]++;
159 return hits
.toString();
161 equalInt
.expected
= "5000,5000,5000,5000,5000,5000,0,0,0,0,0,0,0,5000,5000,0,0,0";
167 a
= [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
168 a
= a
.concat(a
, a
, a
);
170 for (var i
= 0; i
< l
; i
++) {
175 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";
178 function getelem_inner(a
)
182 for (var i
= 0; i
< l
; i
++) {
189 return getelem_inner(a
);
191 getelem
.expected
= 3486;
198 for (var i
= 0; i
< 100; i
++)
206 if (!testName
|| testName
== "globalGet") {
207 for (var i
= 0; i
< 500; i
++)
208 globalInt
= globalName
+ i
;
209 check("globalGet", globalInt
, globalName
+ 499);
212 if (!testName
|| testName
== "globalSet") {
213 for (var i
= 0; i
< 500; i
++)
215 check("globalSet", globalInt
, 499);
221 for (var i
= 0; i
< 100; i
++) {
222 accum
+= (i
* 2) - 1;
226 arith
.expected
= 9800;
229 function lsh_inner(n
)
232 for (var i
= 0; i
< 35; i
++)
238 return [lsh_inner(15),lsh_inner(55),lsh_inner(1),lsh_inner(0)];
240 lsh
.expected
= "32768,8388608,2,1";
243 function rsh_inner(n
)
246 for (var i
= 0; i
< 35; i
++)
252 return [rsh_inner(8),rsh_inner(5),rsh_inner(35),rsh_inner(-1)];
254 rsh
.expected
= "1114369,8914952,35659808,0";
257 function ursh_inner(n
)
260 for (var i
= 0; i
< 35; i
++)
265 return [ursh_inner(8),ursh_inner(33),ursh_inner(0),ursh_inner(1)];
267 ursh
.expected
= "16777215,2147483620,4294967241,2147483620";
270 function doMath_inner(cos
)
274 for (var i
= 0; i
< 200; i
++)
275 s
= -Math
.pow(sin(i
) + cos(i
* 0.75), 4);
279 return doMath_inner(Math
.cos
);
281 doMath
.expected
= -0.5405549555611059;
284 function fannkuch() {
285 var count
= Array(8);
289 // write-out the first 30 permutations
291 while (r
!= 1) { count
[r
- 1] = r
; r
--; }
293 count
[r
] = count
[r
] - 1;
294 if (count
[r
] > 0) break;
300 fannkuch
.expected
= 41;
306 for (var i
= 0; i
< 20; i
++)
310 xprop
.expected
= 140;
314 function getprop_inner(o2
)
319 for (var i
= 0; i
< 20; i
++) {
321 x
+= o
.a
+ o2
.a
+ this.a
+ t
.a
;
326 return getprop_inner({a
:9});
328 getprop
.expected
= 360;
333 var mods
= [-1,-1,-1,-1];
334 var a
= 9.5, b
= -5, c
= 42, d
= (1/0);
335 for (var i
= 0; i
< 20; i
++) {
342 return mods
.toString();
344 mod
.expected
= "4.5,0,42,4,NaN";
355 var q1
= 0, q2
= 0, q3
= 0, q4
= 0, q5
= 0;
364 for (var i
= 0; i
< 100; ++i
) {
371 var ret
= [q1
, q2
, q3
, q4
, q5
];
374 call
.expected
= "100,100,100,100,100";
380 var obj2
= { b
:-1, a
:-1 };
381 for (var i
= 0; i
< 20; i
++) {
384 return [obj
.a
, obj2
.a
, obj2
.b
].toString();
386 setprop
.expected
= "19,-1,19";
391 for (var i
= 0; i
< 100; i
++) {
399 testif
.expected
= "0";
403 function testincops(n
) {
404 var i
= 0, o
= {p
:0}, a
= [0];
407 for (i
= 0; i
< n
; i
++);
409 for (i
= 0; i
< n
; ++i
);
412 for (o
.p
= 0; o
.p
< n
; o
.p
++) globalinc
++;
413 while (o
.p
-- > 0) --globalinc
;
414 for (o
.p
= 0; o
.p
< n
; ++o
.p
) ++globalinc
;
415 while (--o
.p
>= 0) globalinc
--;
418 for (a
[i
] = 0; a
[i
] < n
; a
[i
]++);
420 for (a
[i
] = 0; a
[i
] < n
; ++a
[i
]);
423 return [++o
.p
, ++a
[i
], globalinc
].toString();
425 testincops
.expected
= "0,0,0";
429 var i
= 0, o
= [0,0,0];
430 for (i
= 0; i
< 100; ++i
) {
431 if ((i
& 1) == 0) o
[0]++;
432 else if ((i
& 2) == 0) o
[1]++;
437 trees
.expected
= "50,25,25";
440 function unboxint() {
443 for (var i
= 0; i
< 100; ++i
)
447 unboxint
.expected
= "8";
453 var s
= "abcdefghij", s2
= "a";
455 var c
= 0, d
= 0, e
= 0, g
= 0;
456 for (var i
= 0; i
< 10; i
++) {
457 a
[i
] = (s
.substring(i
, i
+1) + s
[i
] + String
.fromCharCode(s2
.charCodeAt(0) + i
)).concat(i
) + i
;
463 g
++; // f already used
468 return a
.toString() + b
+ c
+ d
+ e
+ g
;
470 strings
.expected
= "aaa00,bbb11,ccc22,ddd33,eee44,fff55,ggg66,hhh77,iii88,jjj991019100";
473 function dependentStrings()
476 var t
= "abcdefghijklmnopqrst";
477 for (var i
= 0; i
< 10; i
++) {
478 var s
= t
.substring(2*i
, 2*i
+ 2);
483 dependentStrings
.expected
= "ab2cd2ef2gh2ij2kl2mn2op2qr2st2";
484 test(dependentStrings
);
486 function stringConvert()
489 var s1
= "F", s2
= "1.3", s3
= "5";
490 for (var i
= 0; i
< 10; i
++) {
503 stringConvert
.expected
= "1,8.7,75,37,1.360,,,5";
506 function orTestHelper(a
, b
, n
)
509 for (var i
= 0; i
< n
; i
++) {
516 var orNaNTest1
, orNaNTest2
;
518 orNaNTest1
= new Function("return orTestHelper(NaN, NaN, 10);");
519 orNaNTest1
.name
= 'orNaNTest1';
520 orNaNTest1
.expected
= '0';
521 orNaNTest2
= new Function("return orTestHelper(NaN, 1, 10);");
522 orNaNTest2
.name
= 'orNaNTest2';
523 orNaNTest2
.expected
= '45';
527 function andTestHelper(a
, b
, n
)
530 for (var i
= 0; i
< n
; i
++) {
537 if (!testName
|| testName
== "truthies") {
539 var opsies
= ["||", "&&"];
540 var falsies
= [null, undefined, false, NaN
, 0, ""];
541 var truthies
= [{}, true, 1, 42, 1/0, -1/0, "blah"];
542 var boolies
= [falsies
, truthies
];
544 // The for each here should abort tracing, so that this test framework
545 // relies only on the interpreter while the orTestHelper and andTestHelper
546 // functions get trace-JITed.
547 for each (var op
in opsies
) {
548 for (var i
in boolies
) {
549 for (var j
in boolies
[i
]) {
550 var x
= uneval(boolies
[i
][j
]);
551 for (var k
in boolies
) {
552 for (var l
in boolies
[k
]) {
553 var y
= uneval(boolies
[k
][l
]);
554 var prefix
= (op
== "||") ? "or" : "and";
555 var f
= new Function("return " + prefix
+ "TestHelper(" + x
+ "," + y
+ ",10)");
556 f
.name
= prefix
+ "Test(" + x
+ "," + y
+ ")";
557 f
.expected
= eval(x
+ op
+ y
) ? 45 : 0;
567 function nonEmptyStack1Helper(o
, farble
) {
575 function nonEmptyStack1() {
576 return nonEmptyStack1Helper({a
:1,b
:2,c
:3,d
:4,e
:5,f
:6,g
:7,h
:8}, "hi");
579 nonEmptyStack1
.expected
= "abcdefgh";
580 test(nonEmptyStack1
);
582 function nonEmptyStack2()
585 for (var c
in {a
:1, b
:2, c
:3}) {
586 for (var i
= 0; i
< 10; i
++)
591 nonEmptyStack2
.expected
= "135";
592 test(nonEmptyStack2
);
594 function arityMismatchMissingArg(arg
)
596 for (var a
= 0, i
= 1; i
< 10000; i
*= 2) {
601 arityMismatchMissingArg
.expected
= 16383;
602 test(arityMismatchMissingArg
);
604 function arityMismatchExtraArg()
606 return arityMismatchMissingArg(1, 2);
608 arityMismatchExtraArg
.expected
= 16383;
609 test(arityMismatchExtraArg
);
611 function MyConstructor(i
)
615 MyConstructor
.prototype.toString = function() {return this.i
+ ""};
620 for (var i
= 0; i
< 10; i
++)
621 a
[i
] = new MyConstructor(i
);
624 newTest
.expected
= "0123456789";
627 // The following functions use a delay line of length 2 to change the value
628 // of the callee without exiting the traced loop. This is obviously tuned to
629 // match the current HOTLOOP setting of 2.
630 function shapelessArgCalleeLoop(f
, g
, h
, a
)
632 for (var i
= 0; i
< 10; i
++) {
639 function shapelessVarCalleeLoop(f0
, g
, h
, a
)
642 for (var i
= 0; i
< 10; i
++) {
649 function shapelessLetCalleeLoop(f0
, g
, h
, a
)
651 for (var i
= 0; i
< 10; i
++) {
659 function shapelessUnknownCalleeLoop(n
, f
, g
, h
, a
)
661 for (var i
= 0; i
< 10; i
++) {
668 function shapelessCalleeTest()
672 var helper = function (i
, a
) a
[i
] = i
;
673 shapelessArgCalleeLoop(helper
, helper
, function (i
, a
) a
[i
] = -i
, a
);
675 helper = function (i
, a
) a
[10 + i
] = i
;
676 shapelessVarCalleeLoop(helper
, helper
, function (i
, a
) a
[10 + i
] = -i
, a
);
678 helper = function (i
, a
) a
[20 + i
] = i
;
679 shapelessLetCalleeLoop(helper
, helper
, function (i
, a
) a
[20 + i
] = -i
, a
);
681 helper = function (i
, a
) a
[30 + i
] = i
;
682 shapelessUnknownCalleeLoop(null, helper
, helper
, function (i
, a
) a
[30 + i
] = -i
, a
);
686 shapelessUnknownCalleeLoop(null, helper
, helper
, helper
, a
);
688 if (e
+ "" != "TypeError: f is not a function")
689 print("shapelessUnknownCalleeLoop: unexpected exception " + e
);
693 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";
694 test(shapelessCalleeTest
);
696 function typeofTest()
698 var values
= ["hi", "hi", "hi", null, 5, 5.1, true, undefined, /foo/, typeofTest
, [], {}], types
= [];
699 for (var i
= 0; i
< values
.length
; i
++)
700 types
[i
] = typeof values
[i
];
701 return types
.toString();
703 typeofTest
.expected
= "string,string,string,object,number,number,boolean,undefined,object,function,object,object";
710 for (var i
= 0; i
< 8; i
++)
711 a
[i
] = [String
.fromCharCode(97 + i
)];
712 for (i
= 0; i
< 8; i
++) {
713 for (var j
= 0; j
< 8; j
++)
716 for (i
= 0; i
< 8; i
++)
720 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";
725 return (x
== undefined) ? 1 : 0;
727 function missingArgTest() {
729 for (var i
= 0; i
< 10; i
++) {
734 missingArgTest
.expected
= "1"
735 test(missingArgTest
);
739 stringify
: function stringify(value
, whitelist
) {
740 switch (typeof(value
)) {
742 return value
.constructor.name
;
748 function missingArgTest2() {
752 ['{"foo":"bar"}', {"foo":"bar"}],
756 for (var i
=0; i
< testPairs
.length
; i
++) {
757 var s
= JSON
.stringify(testPairs
[i
][1])
762 missingArgTest2
.expected
= "Object,Array,Object";
763 test(missingArgTest2
);
765 function deepForInLoop() {
766 // NB: the number of props set in C is arefully tuned to match HOTLOOP = 2.
767 function C(){this.p
= 1, this.q
= 2}
768 C
.prototype = {p
:1, q
:2, r
:3, s
:4, t
:5};
776 deepForInLoop
.expected
= "pqrst";
779 function nestedExit(x
) {
781 for (var i
= 0; i
< 10; ++i
)
785 function nestedExitLoop() {
786 for (var j
= 0; j
< 10; ++j
)
790 nestedExitLoop
.expected
= "ok";
791 test(nestedExitLoop
);
793 function bitsinbyte(b
) {
801 function TimeFunc(func
) {
803 for(var y
=0; y
<256; y
++) func(y
);
805 function nestedExit2() {
806 TimeFunc(bitsinbyte
);
809 nestedExit2
.expected
= "ok";
812 function parsingNumbers() {
816 var s2z
= "123.456zzz";
821 var r1
, r1z
, r2
, r2z
;
823 for (var i
= 0; i
< 10; i
++) {
827 r2z
= parseFloat(s2z
);
830 if (r1
== e1
&& r1z
== e1
&& r2
== e2
&& r2z
== e2
)
834 parsingNumbers
.expected
= "ok";
835 test(parsingNumbers
);
837 function matchInLoop() {
839 for (var i
= 0; i
< 10; i
++) {
840 var result
= k
.match(/hi/) != null;
844 matchInLoop
.expected
= true;
853 for (var i
= 0; i
< 100; ++i
)
857 deep2
.expected
= "ok";
860 var merge_type_maps_x
= 0, merge_type_maps_y
= 0;
861 function merge_type_maps() {
862 for (merge_type_maps_x
= 0; merge_type_maps_x
< 50; ++merge_type_maps_x
)
863 if ((merge_type_maps_x
& 1) == 1)
865 return [merge_type_maps_x
,merge_type_maps_y
].join(",");
867 merge_type_maps
.expected
= "50,25";
868 test(merge_type_maps
)
870 function inner_double_outer_int() {
872 for (var m
= 0; m
< 20; ++m
)
873 for (var n
= 0; n
< 100; n
+= i
)
879 inner_double_outer_int
.expected
= "100";
880 test(inner_double_outer_int
);
882 function newArrayTest()
885 for (var i
= 0; i
< 10; i
++)
887 return a
.map(function(x
) x
.length
).toString();
889 newArrayTest
.expected
="0,0,0,0,0,0,0,0,0,0";
892 function stringSplitTest()
896 for (var i
= 0; i
< 10; ++i
)
900 stringSplitTest
.expected
="a,b";
901 test(stringSplitTest
);
903 function stringSplitIntoArrayTest()
907 for (var i
= 0; i
< 10; ++i
)
911 stringSplitIntoArrayTest
.expected
="a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b";
912 test(stringSplitIntoArrayTest
);
914 function forVarInWith() {
915 function foo() ({notk
:42});
916 function bar() ({p
:1, q
:2, r
:3, s
:4, t
:5});
925 forVarInWith
.expected
= "pqrst";
928 function inObjectTest() {
929 var o
= {p
: 1, q
: 2, r
: 3, s
: 4, t
: 5};
940 inObjectTest
.expected
= 5;
943 function inArrayTest() {
944 var a
= [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
945 for (var i
= 0; i
< a
.length
; i
++) {
951 inArrayTest
.expected
= 10;
954 function innerLoopIntOuterDouble() {
955 var n
= 10000, i
=0, j
=0, count
=0, limit
=0;
956 for (i
= 1; i
<= n
; ++i
) {
958 for (j
= 0; j
< limit
; ++j
) {
964 innerLoopIntOuterDouble
.expected
="50005000";
965 test(innerLoopIntOuterDouble
);
967 function outerline(){
971 for (i
= 3; i
<= 100000; i
+=2)
972 for (j
= 3; j
< 1000; j
+=2)
977 outerline
.expected
="ok";
980 function addAccumulations(f
) {
986 function loopingAccumulator() {
989 for (var i
= 0; i
< 10; ++i
) {
996 function testLoopingAccumulator() {
997 var x
= addAccumulations(loopingAccumulator
);
1000 testLoopingAccumulator
.expected
= 20;
1001 test(testLoopingAccumulator
);
1003 function testBranchingLoop() {
1005 for (var i
=0; i
< 100; ++i
) {
1013 testBranchingLoop
.expected
= 110;
1014 test(testBranchingLoop
);
1016 function testBranchingUnstableLoop() {
1018 for (var i
=0; i
< 100; ++i
) {
1026 testBranchingUnstableLoop
.expected
= 110.1;
1027 test(testBranchingUnstableLoop
);
1029 function testBranchingUnstableLoopCounter() {
1031 for (var i
=0; i
< 100; ++i
) {
1039 testBranchingUnstableLoopCounter
.expected
= 99;
1040 test(testBranchingUnstableLoopCounter
);
1043 function testBranchingUnstableObject() {
1046 for (var i
=0; i
< 100; ++i
) {
1055 testBranchingUnstableObject
.expected
= 100;
1056 test(testBranchingUnstableObject
);
1058 function testArrayDensityChange() {
1061 for (var i
=0; i
< 100; ++i
) {
1064 for (var i
=0; i
< x
.length
; ++i
) {
1070 count
+= x
[i
].length
;
1074 testArrayDensityChange
.expected
= 404;
1075 test(testArrayDensityChange
);
1077 function testDoubleToStr() {
1080 for (var i
= 0; i
< 200; i
++) {
1081 x
+= parseFloat(y
.toString());
1085 testDoubleToStr
.expected
= 5.5*200;
1086 test(testDoubleToStr
);
1088 function testNumberToString() {
1089 var x
= new Number(0);
1090 for (var i
= 0; i
< 4; i
++)
1093 test(testNumberToString
);
1095 function testDecayingInnerLoop() {
1097 for (i
= 0; i
< 5000; ++i
) {
1098 for (j
= 0; j
< k
; ++j
);
1103 testDecayingInnerLoop
.expected
= 5000;
1104 test(testDecayingInnerLoop
);
1106 function testContinue() {
1109 for (i
= 0; i
< 20; ++i
) {
1116 testContinue
.expected
= 19;
1119 function testContinueWithLabel() {
1134 testContinueWithLabel
.expected
= 20;
1135 test(testContinueWithLabel
);
1137 function testDivision() {
1146 testDivision
.expected
= 1;
1149 function testDivisionFloat() {
1158 testDivisionFloat
.expected
= true;
1159 test(testDivisionFloat
);
1161 function testToUpperToLower() {
1162 var s
= "Hello", s1
, s2
;
1163 for (i
= 0; i
< 100; ++i
) {
1164 s1
= s
.toLowerCase();
1165 s2
= s
.toUpperCase();
1169 testToUpperToLower
.expected
= "helloHELLO";
1170 test(testToUpperToLower
);
1172 function testReplace2() {
1173 var s
= "H e l l o", s1
;
1174 for (i
= 0; i
< 100; ++i
) {
1175 s1
= s
.replace(" ", "");
1179 testReplace2
.expected
= "He l l o";
1182 function testBitwise() {
1186 for (var i
= 0; i
< 50; i
++) {
1193 testBitwise
.expected
= -1298;
1196 function testSwitch() {
1199 for (var i
= 0; i
< 100; ++i
) {
1220 testSwitch
.expected
= 226;
1223 function testSwitchString() {
1226 for (var i
= 0; i
< 100; ++i
) {
1250 testSwitchString
.expected
= 200;
1251 test(testSwitchString
);
1253 function testNegZero1Helper(z
) {
1254 for (let j
= 0; j
< 5; ++j
) { z
= -z
; }
1255 return Math
.atan2(0, -0) == Math
.atan2(0, z
);
1258 var testNegZero1 = function() { return testNegZero1Helper(0); }
1259 testNegZero1
.expected
= true;
1260 testNegZero1
.name
= 'testNegZero1';
1261 testNegZero1Helper(1);
1264 // No test case, just make sure this doesn't assert.
1265 function testNegZero2() {
1267 for (let j
= 0; j
< 5; ++j
) { ({p
: (-z
)}); }
1271 function testConstSwitch() {
1273 for (var j
=0;j
<5;++j
) { switch(1.1) { case NaN
: case 2: } x
= 2; }
1276 testConstSwitch
.expected
= 2;
1277 test(testConstSwitch
);
1279 function testConstSwitch2() {
1281 for (var j
= 0; j
< 4; ++j
) { switch(0/0) { } }
1284 testConstSwitch2
.expected
= "ok";
1285 test(testConstSwitch2
);
1287 function testConstIf() {
1289 for (var j
=0;j
<5;++j
) { if (1.1 || 5) { } x
= 2;}
1292 testConstIf
.expected
= 2;
1295 function testTypeofHole() {
1296 var a
= new Array(6);
1298 for (var i
= 0; i
< 6; ++i
)
1302 testTypeofHole
.expected
= "undefined,undefined,undefined,undefined,undefined,number"
1303 test(testTypeofHole
);
1305 function testNativeLog() {
1306 var a
= new Array(5);
1307 for (var i
= 0; i
< 5; i
++) {
1308 a
[i
] = Math
.log(Math
.pow(Math
.E
, 10));
1312 testNativeLog
.expected
= "10,10,10,10,10";
1313 test(testNativeLog
);
1315 function test_JSOP_ARGSUB() {
1316 function f0() { return arguments
[0]; }
1317 function f1() { return arguments
[1]; }
1318 function f2() { return arguments
[2]; }
1319 function f3() { return arguments
[3]; }
1320 function f4() { return arguments
[4]; }
1321 function f5() { return arguments
[5]; }
1322 function f6() { return arguments
[6]; }
1323 function f7() { return arguments
[7]; }
1324 function f8() { return arguments
[8]; }
1325 function f9() { return arguments
[9]; }
1327 for (var i
= 0; i
< 10; i
++) {
1330 a
[2] = f2('a','b','c');
1331 a
[3] = f3('a','b','c','d');
1332 a
[4] = f4('a','b','c','d','e');
1333 a
[5] = f5('a','b','c','d','e','f');
1334 a
[6] = f6('a','b','c','d','e','f','g');
1335 a
[7] = f7('a','b','c','d','e','f','g','h');
1336 a
[8] = f8('a','b','c','d','e','f','g','h','i');
1337 a
[9] = f9('a','b','c','d','e','f','g','h','i','j');
1341 test_JSOP_ARGSUB
.expected
= "abcdefghij";
1342 test(test_JSOP_ARGSUB
);
1344 function test_JSOP_ARGCNT() {
1345 function f0() { return arguments
.length
; }
1346 function f1() { return arguments
.length
; }
1347 function f2() { return arguments
.length
; }
1348 function f3() { return arguments
.length
; }
1349 function f4() { return arguments
.length
; }
1350 function f5() { return arguments
.length
; }
1351 function f6() { return arguments
.length
; }
1352 function f7() { return arguments
.length
; }
1353 function f8() { return arguments
.length
; }
1354 function f9() { return arguments
.length
; }
1356 for (var i
= 0; i
< 10; i
++) {
1359 a
[2] = f2('a','b','c');
1360 a
[3] = f3('a','b','c','d');
1361 a
[4] = f4('a','b','c','d','e');
1362 a
[5] = f5('a','b','c','d','e','f');
1363 a
[6] = f6('a','b','c','d','e','f','g');
1364 a
[7] = f7('a','b','c','d','e','f','g','h');
1365 a
[8] = f8('a','b','c','d','e','f','g','h','i');
1366 a
[9] = f9('a','b','c','d','e','f','g','h','i','j');
1370 test_JSOP_ARGCNT
.expected
= "1,2,3,4,5,6,7,8,9,10";
1371 test(test_JSOP_ARGCNT
);
1373 function testNativeMax() {
1375 for (var i
= 0; i
< 5; ++i
) {
1381 for (var i
= 0; i
< 5; ++i
) {
1386 for (var i
= 0; i
< 5; ++i
) {
1387 k
= Math
.max(0, -0);
1389 out
.push((1 / k
) < 0);
1390 return out
.join(",");
1392 testNativeMax
.expected
= "NaN,4,false";
1393 test(testNativeMax
);
1395 function testFloatArrayIndex() {
1397 for (var i
= 0; i
< 10; ++i
) {
1401 return a
[3] + "," + a
[3.5];
1403 testFloatArrayIndex
.expected
= "5,7";
1404 test(testFloatArrayIndex
);
1406 function testStrict() {
1408 for (var i
= 0; i
< 10; ++i
) {
1411 a
[2] = (n
=== null);
1416 testStrict
.expected
= "true,false,false,false";
1419 function testSetPropNeitherMissNorHit() {
1420 for (var j
= 0; j
< 5; ++j
) { if (({}).__proto__
= 1) { } }
1423 testSetPropNeitherMissNorHit
.expected
= "ok";
1424 test(testSetPropNeitherMissNorHit
);
1426 function testPrimitiveConstructorPrototype() {
1427 var f = function(){};
1428 f
.prototype = false;
1429 for (let j
=0;j
<5;++j
) { new f
; }
1432 testPrimitiveConstructorPrototype
.expected
= "ok";
1433 test(testPrimitiveConstructorPrototype
);
1435 function testSideExitInConstructor() {
1437 FCKConfig
.CoreStyles
=
1455 Styles
: { 'background-color' : '' }
1459 var FCKStyle = function(A
) {
1464 for (var s
in FCKConfig
.CoreStyles
) {
1465 var x
= new FCKStyle(FCKConfig
.CoreStyles
[s
]);
1466 if (!x
) pass
= false;
1470 testSideExitInConstructor
.expected
= true;
1471 test(testSideExitInConstructor
);
1473 function testNot() {
1474 var a
= new Object(), b
= null, c
= "foo", d
= "", e
= 5, f
= 0, g
= 5.5, h
= -0, i
= true, j
= false, k
= undefined;
1476 for (var i
= 0; i
< 10; ++i
) {
1477 r
= [!a
, !b
, !c
, !d
, !e
, !f
, !g
, !h
, !i
, !j
, !k
];
1481 testNot
.expected
= "false,true,false,true,false,true,false,true,false,true,true";
1484 function doTestDifferingArgc(a
, b
)
1487 for (var i
= 0; i
< 10; i
++)
1493 function testDifferingArgc()
1496 x
+= doTestDifferingArgc(1, 2);
1497 x
+= doTestDifferingArgc(1);
1498 x
+= doTestDifferingArgc(1, 2, 3);
1501 testDifferingArgc
.expected
= 45*3;
1502 test(testDifferingArgc
);
1504 function doTestMoreArgcThanNargs()
1507 for (var i
= 0; i
< 10; i
++)
1509 x
= x
+ arguments
[3];
1513 function testMoreArgcThanNargs()
1515 return doTestMoreArgcThanNargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1517 testMoreArgcThanNargs
.expected
= 4*10;
1518 test(testMoreArgcThanNargs
);
1520 // Test stack reconstruction after a nested exit
1521 function testNestedExitStackInner(j
, counter
) {
1524 for (var i
= 1; i
<= RUNLOOP
; i
++) {
1527 // Make sure that once everything has been traced we suddenly switch to
1528 // a different control flow the first time we run the outermost tree,
1529 // triggering a side exit.
1539 function testNestedExitStackOuter() {
1541 for (var j
= 1; j
<= RUNLOOP
; ++j
) {
1542 for (var k
= 1; k
<= RUNLOOP
; ++k
) {
1543 counter
= testNestedExitStackInner(j
, counter
);
1548 testNestedExitStackOuter
.expected
= 81;
1549 testNestedExitStackOuter
.jitstats
= {
1554 test(testNestedExitStackOuter
);
1556 function testHOTLOOPSize() {
1559 testHOTLOOPSize
.expected
= true;
1560 test(testHOTLOOPSize
);
1562 function testMatchStringObject() {
1563 var a
= new String("foo");
1565 for (i
= 0; i
< 300; i
++) {
1570 testMatchStringObject
.expected
= null;
1571 test(testMatchStringObject
);
1573 function innerSwitch(k
)
1586 function testInnerSwitchBreak()
1588 var r
= new Array(5);
1589 for (var i
= 0; i
< 5; i
++)
1591 r
[i
] = innerSwitch(0);
1596 testInnerSwitchBreak
.expected
= "1,1,1,1,1";
1597 test(testInnerSwitchBreak
);
1599 function testArrayNaNIndex()
1601 for (var j
= 0; j
< 4; ++j
) { [this[NaN
]]; }
1602 for (var j
= 0; j
< 5; ++j
) { if([1][-0]) { } }
1605 testArrayNaNIndex
.expected
= "ok";
1606 test(testArrayNaNIndex
);
1608 function innerTestInnerMissingArgs(a
,b
,c
,d
)
1614 function doTestInnerMissingArgs(k
)
1616 for (i
= 0; i
< 10; i
++) {
1617 innerTestInnerMissingArgs(k
);
1620 function testInnerMissingArgs()
1622 doTestInnerMissingArgs(1);
1623 doTestInnerMissingArgs(0);
1626 testInnerMissingArgs
.expected
= 1; //Expected: that we don't crash.
1627 test(testInnerMissingArgs
);
1629 function regexpLastIndex()
1633 var ss
= " hi hi hi hi hi hi hi hi hi hi";
1634 for (var i
= 0; i
< 10; i
++) {
1636 n
+= (re
.lastIndex
> 0) ? 3 : 0;
1641 regexpLastIndex
.expected
= 0; // 30;
1642 test(regexpLastIndex
);
1644 function testHOTLOOPCorrectness() {
1646 for (var i
= 0; i
< HOTLOOP
; ++i
) {
1651 testHOTLOOPCorrectness
.expected
= HOTLOOP
;
1652 testHOTLOOPCorrectness
.jitstats
= {
1657 // Change the global shape right before doing the test
1658 this.testHOTLOOPCorrectnessVar
= 1;
1659 test(testHOTLOOPCorrectness
);
1661 function testRUNLOOPCorrectness() {
1663 for (var i
= 0; i
< RUNLOOP
; ++i
) {
1668 testRUNLOOPCorrectness
.expected
= RUNLOOP
;
1669 testRUNLOOPCorrectness
.jitstats
= {
1674 // Change the global shape right before doing the test
1675 this.testRUNLOOPCorrectnessVar
= 1;
1676 test(testRUNLOOPCorrectness
);
1678 function testDateNow() {
1679 // Accessing global.Date for the first time will change the global shape,
1680 // so do it before the loop starts; otherwise we have to loop an extra time
1681 // to pick things up.
1682 var time
= Date
.now();
1683 for (var j
= 0; j
< RUNLOOP
; ++j
) {
1688 testDateNow
.expected
= "ok";
1689 testDateNow
.jitstats
= {
1696 function testINITELEM()
1699 for (var i
= 0; i
< 10; ++i
)
1703 testINITELEM
.expected
= 10;
1706 function testUndefinedBooleanCmp()
1708 var t
= true, f
= false, x
= [];
1709 for (var i
= 0; i
< 10; ++i
) {
1710 x
[0] = t
== undefined;
1711 x
[1] = t
!= undefined;
1712 x
[2] = t
=== undefined;
1713 x
[3] = t
!== undefined;
1714 x
[4] = t
< undefined;
1715 x
[5] = t
> undefined;
1716 x
[6] = t
<= undefined;
1717 x
[7] = t
>= undefined;
1718 x
[8] = f
== undefined;
1719 x
[9] = f
!= undefined;
1720 x
[10] = f
=== undefined;
1721 x
[11] = f
!== undefined;
1722 x
[12] = f
< undefined;
1723 x
[13] = f
> undefined;
1724 x
[14] = f
<= undefined;
1725 x
[15] = f
>= undefined;
1729 testUndefinedBooleanCmp
.expected
= "false,true,false,true,false,false,false,false,false,true,false,true,false,false,false,false";
1730 test(testUndefinedBooleanCmp
);
1732 function testConstantBooleanExpr()
1734 for (var j
= 0; j
< 3; ++j
) { if(true <= true) { } }
1737 testConstantBooleanExpr
.expected
= "ok";
1738 test(testConstantBooleanExpr
);
1740 function testNegativeGETELEMIndex()
1742 for (let i
=0;i
<3;++i
) /x
/[-4];
1745 testNegativeGETELEMIndex
.expected
= "ok";
1746 test(testNegativeGETELEMIndex
);
1748 function doTestInvalidCharCodeAt(input
)
1751 for (var i
= 0; i
< 10; i
++)
1752 q
+= input
.charCodeAt(i
);
1755 function testInvalidCharCodeAt()
1757 return doTestInvalidCharCodeAt("");
1759 testInvalidCharCodeAt
.expected
= "NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN";
1760 test(testInvalidCharCodeAt
);
1762 function FPQuadCmp()
1764 for (let j
= 0; j
< 3; ++j
) { true == 0; }
1767 FPQuadCmp
.expected
= "ok";
1770 function testDestructuring() {
1772 for (var i
= 0; i
< HOTLOOP
+ 1; ++i
) {
1773 var [r
, g
, b
] = [1, 1, 1];
1778 testDestructuring
.expected
= (HOTLOOP
+ 1) * 3;
1779 test(testDestructuring
);
1781 // BEGIN MANDELBROT STUFF
1782 // XXXbz I would dearly like to wrap it up into a function to avoid polluting
1783 // the global scope, but the function ends up heavyweight, and then we lose on
1785 load("mandelbrot-results.js");
1786 //function testMandelbrotAll() {
1787 // Configuration options that affect which codepaths we follow.
1788 var doImageData
= true;
1789 var avoidSparseArray
= true;
1791 // Control of iteration numbers and sizing. We'll do
1792 // scaler * colorNames.length iterations or so before deciding that we
1795 const numRows
= 600;
1796 const numCols
= 600;
1798 // For now, avoid hitting memory pressure
1799 gcparam("maxBytes", 1300000000);
1800 gcparam("maxMallocBytes", 1300000000);
1802 const colorNames
= [
1826 const threshold
= (colorNames
.length
- 1) * scaler
;
1828 // Now set up our colors
1830 // 3-part for loop (iterators buggy, we will add a separate test for them)
1831 for (var colorNameIdx
= 0; colorNameIdx
< colorNames
.length
; ++colorNameIdx
) {
1832 //for (var colorNameIdx in colorNames) {
1833 colorNameIdx
= parseInt(colorNameIdx
);
1834 colors
.push([colorNameIdx
, colorNameIdx
, colorNameIdx
, 0]);
1837 // Storage for our point data
1842 function complexMult(a
, b
) {
1843 var newr
= a
.r
* b
.r
- a
.i
* b
.i
;
1844 var newi
= a
.r
* b
.i
+ a
.i
* b
.r
;
1849 function complexAdd(a
, b
) {
1850 scratch
.r
= a
.r
+ b
.r
;
1851 scratch
.i
= a
.i
+ b
.i
;
1855 return Math
.sqrt(a
.r
* a
.r
+ a
.i
* a
.i
);
1858 function escapeAbsDiff(normZ
, absC
) {
1859 var absZ
= Math
.sqrt(normZ
);
1860 return normZ
> absZ
+ absC
;
1863 function escapeNorm2(normZ
) {
1867 function fuzzyColors(i
) {
1868 return Math
.floor(i
/ scaler
) + 1;
1871 function moddedColors(i
) {
1872 return (i
% (colorNames
.length
- 1)) + 1;
1875 function computeEscapeSpeedObjects(real
, imag
) {
1876 var c
= { r
: real
, i
: imag
}
1877 scratchZ
.r
= scratchZ
.i
= 0;
1879 for (var i
= 0; i
< threshold
; ++i
) {
1880 scratchZ
= complexAdd(c
, complexMult(scratchZ
, scratchZ
));
1881 if (escape(scratchZ
.r
* scratchZ
.r
+ scratchZ
.i
* scratchZ
.i
,
1889 function computeEscapeSpeedOneObject(real
, imag
) {
1890 // fold in the fact that we start with 0
1893 var absC
= abs({r
: real
, i
: imag
});
1894 for (var j
= 0; j
< threshold
; ++j
) {
1897 if (escape(r2
+ i2
, absC
)) {
1900 i
= 2 * r
* i
+ imag
;
1906 function computeEscapeSpeedDoubles(real
, imag
) {
1907 // fold in the fact that we start with 0
1910 var absC
= Math
.sqrt(real
* real
+ imag
* imag
);
1911 for (var j
= 0; j
< threshold
; ++j
) {
1914 if (escape(r2
+ i2
, absC
)) {
1917 i
= 2 * r
* i
+ imag
;
1923 var computeEscapeSpeed
= computeEscapeSpeedDoubles
;
1924 var escape
= escapeNorm2
;
1925 var colorMap
= fuzzyColors
;
1927 function addPointOrig(pointArray
, n
, i
, j
) {
1930 points
[n
].push([i
, j
, 1, 1]);
1932 var point
= points
[n
][points
[n
].length
-1];
1933 if (point
[0] == i
&& point
[1] == j
- point
[3]) {
1936 points
[n
].push([i
, j
, 1, 1]);
1941 function addPointImagedata(pointArray
, n
, col
, row
) {
1942 var slotIdx
= ((row
* numCols
) + col
) * 4;
1943 pointArray
[slotIdx
] = colors
[n
][0];
1944 pointArray
[slotIdx
+1] = colors
[n
][1];
1945 pointArray
[slotIdx
+2] = colors
[n
][2];
1946 pointArray
[slotIdx
+3] = colors
[n
][3];
1949 function createMandelSet() {
1950 var realRange
= { min
: -2.1, max
: 1 };
1951 var imagRange
= { min
: -1.5, max
: 1.5 };
1955 addPoint
= addPointImagedata
;
1956 points
= new Array(4*numCols
*numRows
);
1957 if (avoidSparseArray
) {
1958 for (var idx
= 0; idx
< 4*numCols
*numRows
; ++idx
) {
1963 addPoint
= addPointOrig
;
1966 var realStep
= (realRange
.max
- realRange
.min
)/numCols
;
1967 var imagStep
= (imagRange
.min
- imagRange
.max
)/numRows
;
1968 for (var i
= 0, curReal
= realRange
.min
;
1970 ++i
, curReal
+= realStep
) {
1971 for (var j
= 0, curImag
= imagRange
.max
;
1973 ++j
, curImag
+= imagStep
) {
1974 var n
= computeEscapeSpeed(curReal
, curImag
);
1975 addPoint(points
, n
, i
, j
)
1980 if (colorMap
== fuzzyColors
) {
1981 result
= mandelbrotImageDataFuzzyResult
;
1983 result
= mandelbrotImageDataModdedResult
;
1986 result
= mandelbrotNoImageDataResult
;
1988 return points
.toSource() == result
;
1991 createMandelSet
.expected
= true;
1993 const escapeTests
= [ escapeAbsDiff
];
1994 const colorMaps
= [ fuzzyColors
, moddedColors
];
1995 const escapeComputations
= [ computeEscapeSpeedObjects
,
1996 computeEscapeSpeedOneObject
,
1997 computeEscapeSpeedDoubles
];
1998 // Test all possible escape-speed generation codepaths, using the
1999 // imageData + sparse array avoidance storage.
2001 avoidSparseArray
= true;
2002 for (var escapeIdx
in escapeTests
) {
2003 escape
= escapeTests
[escapeIdx
];
2004 for (var colorMapIdx
in colorMaps
) {
2005 colorMap
= colorMaps
[colorMapIdx
];
2006 for (var escapeComputationIdx
in escapeComputations
) {
2007 computeEscapeSpeed
= escapeComputations
[escapeComputationIdx
];
2008 test(createMandelSet
);
2013 // Test all possible storage strategies. Note that we already tested
2014 // doImageData == true with avoidSparseArray == true.
2015 escape
= escapeAbsDiff
;
2016 colorMap
= fuzzyColors
; // This part doesn't really matter too much here
2017 computeEscapeSpeed
= computeEscapeSpeedDoubles
;
2020 avoidSparseArray
= false;
2021 test(createMandelSet
);
2023 escape
= escapeNorm2
;
2024 doImageData
= false; // avoidSparseArray doesn't matter here
2025 test(createMandelSet
);
2027 //testMandelbrotAll();
2028 // END MANDELBROT STUFF
2030 /* Keep this test last, since it screws up all for...in loops after it */
2031 function testGlobalProtoAccess() {
2034 this.__proto__
.a
= 3; for (var j
= 0; j
< 4; ++j
) { [a
]; }
2035 testGlobalProtoAccess
.expected
= "ok";
2036 test(testGlobalProtoAccess
);
2038 function testNewDate()
2040 // Accessing global.Date for the first time will change the global shape,
2041 // so do it before the loop starts; otherwise we have to loop an extra time
2042 // to pick things up.
2043 var start
= new Date();
2044 var time
= new Date();
2045 for (var j
= 0; j
< RUNLOOP
; ++j
) {
2048 return time
> 0 && time
>= start
;
2050 testNewDate
.expected
= true;
2051 testNewDate
.jitstats
= {
2058 function testArrayPushPop() {
2059 var a
= [], sum1
= 0, sum2
= 0;
2060 for (var i
= 0; i
< 10; ++i
)
2062 for (var i
= 0; i
< 10; ++i
)
2068 testArrayPushPop
.expected
= "55,45";
2069 test(testArrayPushPop
);
2071 function testResumeOp() {
2072 var a
= [1,"2",3,"4",5,"6",7,"8",9,"10",11,"12",13,"14",15,"16"];
2074 while (a
.length
> 0)
2078 testResumeOp
.expected
= "16151413121110987654321";
2081 function testUndefinedCmp() {
2083 for (var j
= 0; j
< 4; ++j
) { if (undefined < false) { a
= true; } }
2086 testUndefinedCmp
.expected
= false;
2087 test(testUndefinedCmp
);
2089 function reallyDeepNestedExit(schedule
)
2092 for (var i
= 0; i
< 5; i
++) {
2093 for (j
= 0; j
< 4; j
++) {
2094 c
+= (schedule
[i
*4 + j
] == 1) ? 1 : 2;
2099 function testReallyDeepNestedExit()
2102 var schedule1
= new Array(5*4);
2103 var schedule2
= new Array(5*4);
2104 for (var i
= 0; i
< 5*4; i
++) {
2109 * First innermost compile: true branch runs through.
2110 * Second '': false branch compiles new loop edge.
2111 * First outer compile: expect true branch.
2112 * Second '': hit false branch.
2114 schedule1
[0*4 + 3] = 1;
2115 var schedules
= [schedule1
,
2121 for (var i
= 0; i
< 5; i
++) {
2122 c
+= reallyDeepNestedExit(schedules
[i
]);
2126 testReallyDeepNestedExit
.expected
= 198;
2127 test(testReallyDeepNestedExit
);
2129 /* Keep these at the end so that we can see the summary after the trace-debug spew. */
2130 print("\npassed:", passes
.length
&& passes
.join(","));
2131 print("\nFAILED:", fails
.length
&& fails
.join(","));