[MediaStream] Clear cached gUM prompt state
[WebKit-https.git] / JSTests / stress / inline-call-to-recursive-tail-call.js
1 "use strict";
2
3 // factorial calls aux that tail-calls back into factorial.
4 // It is not OK to turn that tail call into a jump back to the top of the function, because the call to aux is not a tail call.
5 function factorial(n) {
6     function aux(n) {
7         if (n == 1)
8             return 1;
9         return factorial(n - 1);
10     }
11
12     return n * aux(n);
13 }
14
15 // Same, but this time with an irrelevant tail call in factorial.
16 // This exercises a different code path because the recursive tail call optimization aborts early if the op_enter block is not split, and it is split by the detection of a tail call.
17 function factorial2(n) {
18     function aux2(n) {
19         if (n == 1)
20             return 1;
21         return factorial2(n - 1);
22     }
23     function id(n) {
24         return n;
25     }
26
27     return id(n * aux2(n));
28 }
29
30 // This time, aux is tail-calling itself: the optimization is valid but must jump to the start of aux3, not of factorial3.
31 function factorial3(n) {
32     function aux3(n, acc) {
33         if (n == 1)
34             return acc;
35         return aux3 (n-1, n*acc);
36     }
37
38     return n * aux3(n-1, 1);
39 }
40
41 // In this case, it is valid to jump all the way to the top of factorial4, because all calls are tail calls.
42 function factorial4(n, acc) {
43     function aux4(n, acc) {
44         if (n == 1)
45             return acc;
46         return factorial4(n-1, n*acc);
47     }
48
49     if (acc)
50         return aux4(n, acc);
51     return aux4(n, 1);
52 }
53
54 // This function is used to test that recursing with a different number of arguments doesn't mess up with the stack.
55 // The first two tail calls should be optimized, but not the last one (no place on the stack for the third argument).
56 function foo(a, b) {
57     if (a == 0)
58         return 42;
59     if (a == 1)
60         return foo(a - 1);
61     if (a == 2)
62         return foo(b - 1, a);
63     return foo (b - 1, a, 43);
64 }
65
66 // Same deal as foo, just with an inlining thrown into the mix.
67 // Even the first tail call should not be optimized in this case, for subtle reasons.
68 function bar(x, y) {
69     function auxBar(a, b) {
70         if (a == 0)
71             return 42;
72         if (a == 1)
73             return foo(a - 1);
74         if (a == 2)
75             return foo(b - 1, a);
76         return foo (b - 1, a, 43);
77     }
78
79     return auxBar(x, y);
80 }
81
82 function test(result, expected, name) {
83     if (result != expected)
84         throw "Wrong result for " + name + ": " + result + " instead of " + expected;
85 }
86
87 for (var i = 0; i < 10000; ++i) {
88     test(factorial(20), 2432902008176640000, "factorial");
89     test(factorial2(20), 2432902008176640000, "factorial2");
90     test(factorial3(20), 2432902008176640000, "factorial3");
91     test(factorial4(20), 2432902008176640000, "factorial4");
92     test(foo(10, 10), 42, "foo");
93     test(bar(10, 10), 42, "bar");
94 }