[JSC] Do not use EagerRun on tests counting recompilation
[WebKit-https.git] / JSTests / stress / arith-tan-on-various-types.js
1 //@ defaultNoEagerRun
2 "use strict";
3
4 let tanOfFour = Math.tan(4);
5
6 let validInputTestCases = [
7     // input as string, expected result as string.
8     ["undefined", "NaN"],
9     ["null", "0"],
10     ["0", "0"],
11     ["-0.", "-0"],
12     ["4", "" + tanOfFour],
13     ["Math.PI", "" + Math.tan(Math.PI)],
14     ["Infinity", "NaN"],
15     ["-Infinity", "NaN"],
16     ["NaN", "NaN"],
17     ["\"WebKit\"", "NaN"],
18     ["\"4\"", "" + tanOfFour],
19     ["{ valueOf: () => { return 4; } }", "" + tanOfFour],
20 ];
21
22 let validInputTypedTestCases = validInputTestCases.map((element) => { return [eval("(" + element[0] + ")"), eval(element[1])] });
23
24 function isIdentical(result, expected)
25 {
26     if (expected === expected) {
27         if (result !== expected)
28             return false;
29         if (!expected && 1 / expected === -Infinity && 1 / result !== -Infinity)
30             return false;
31
32         return true;
33     }
34     return result !== result;
35 }
36
37
38 // Test Math.tan() without arguments.
39 function opaqueTanNoArgument() {
40     return Math.tan();
41 }
42 noInline(opaqueTanNoArgument);
43 noOSRExitFuzzing(opaqueTanNoArgument);
44
45 function testNoArgument() {
46     for (let i = 0; i < 1e4; ++i) {
47         let output = opaqueTanNoArgument();
48         if (output === output) {
49             throw "Failed opaqueTanNoArgument";
50         }
51     }
52     if (numberOfDFGCompiles(opaqueTanNoArgument) > 1)
53         throw "The call without arguments should never exit.";
54 }
55 testNoArgument();
56
57
58 // Test Math.tan() with a very polymorphic input. All test cases are seen at each iteration.
59 function opaqueAllTypesTan(argument) {
60     return Math.tan(argument);
61 }
62 noInline(opaqueAllTypesTan);
63 noOSRExitFuzzing(opaqueAllTypesTan);
64
65 function testAllTypesCall() {
66     for (let i = 0; i < 1e3; ++i) {
67         for (let testCaseInput of validInputTypedTestCases) {
68             let output = opaqueAllTypesTan(testCaseInput[0]);
69             if (!isIdentical(output, testCaseInput[1]))
70                 throw "Failed testAllTypesCall for input " + testCaseInput[0] + " expected " + testCaseInput[1] + " got " + output;
71         }
72     }
73     if (numberOfDFGCompiles(opaqueAllTypesTan) > 2)
74         throw "We should have detected tan() was polymorphic and generated a generic version.";
75 }
76 testAllTypesCall();
77
78
79 // Test Math.tan() on a completely typed input. Every call see only one type.
80 function testTangleTypeCall() {
81     for (let testCaseInput of validInputTestCases) {
82         eval(`
83             function opaqueTan(argument) {
84                 return Math.tan(argument);
85             }
86             noInline(opaqueTan);
87             noOSRExitFuzzing(opaqueTan);
88
89             for (let i = 0; i < 1e4; ++i) {
90                 if (!isIdentical(opaqueTan(${testCaseInput[0]}), ${testCaseInput[1]})) {
91                     throw "Failed testTangleTypeCall()";
92                 }
93             }
94             if (numberOfDFGCompiles(opaqueTan) > 1)
95                 throw "We should have compiled a tangle tan for the expected type.";
96         `);
97     }
98 }
99 testTangleTypeCall();
100
101
102 // Test Math.tan() on constants
103 function testConstant() {
104     for (let testCaseInput of validInputTestCases) {
105         eval(`
106             function opaqueTanOnConstant() {
107                 return Math.tan(${testCaseInput[0]});
108             }
109             noInline(opaqueTanOnConstant);
110             noOSRExitFuzzing(opaqueTanOnConstant);
111
112             for (let i = 0; i < 1e4; ++i) {
113                 if (!isIdentical(opaqueTanOnConstant(), ${testCaseInput[1]})) {
114                     throw "Failed testConstant()";
115                 }
116             }
117             if (numberOfDFGCompiles(opaqueTanOnConstant) > 1)
118                 throw "We should have compiled a tangle tan for the expected type.";
119         `);
120     }
121 }
122 testConstant();
123
124
125 // Verify we call valueOf() exactly once per call.
126 function opaqueTanForSideEffects(argument) {
127     return Math.tan(argument);
128 }
129 noInline(opaqueTanForSideEffects);
130 noOSRExitFuzzing(opaqueTanForSideEffects);
131
132 function testSideEffect() {
133     let testObject = {
134         counter: 0,
135         valueOf: function() { ++this.counter; return 16; }
136     };
137     let tan16 = Math.tan(16);
138     for (let i = 0; i < 1e4; ++i) {
139         if (opaqueTanForSideEffects(testObject) !== tan16)
140             throw "Incorrect result in testSideEffect()";
141     }
142     if (testObject.counter !== 1e4)
143         throw "Failed testSideEffect()";
144     if (numberOfDFGCompiles(opaqueTanForSideEffects) > 1)
145         throw "opaqueTanForSideEffects() is predictable, it should only be compiled once.";
146 }
147 testSideEffect();
148
149
150 // Verify tan() is not subject to CSE if the argument has side effects.
151 function opaqueTanForCSE(argument) {
152     return Math.tan(argument) + Math.tan(argument) + Math.tan(argument);
153 }
154 noInline(opaqueTanForCSE);
155 noOSRExitFuzzing(opaqueTanForCSE);
156
157 function testCSE() {
158     let testObject = {
159         counter: 0,
160         valueOf: function() { ++this.counter; return 16; }
161     };
162     let tan16 = Math.tan(16);
163     let threeTan16 = tan16 + tan16 + tan16;
164     for (let i = 0; i < 1e4; ++i) {
165         if (opaqueTanForCSE(testObject) !== threeTan16)
166             throw "Incorrect result in testCSE()";
167     }
168     if (testObject.counter !== 3e4)
169         throw "Failed testCSE()";
170     if (numberOfDFGCompiles(opaqueTanForCSE) > 1)
171         throw "opaqueTanForCSE() is predictable, it should only be compiled once.";
172 }
173 testCSE();
174
175
176 // Verify tan() is not subject to DCE if the argument has side effects.
177 function opaqueTanForDCE(argument) {
178     Math.tan(argument);
179 }
180 noInline(opaqueTanForDCE);
181 noOSRExitFuzzing(opaqueTanForDCE);
182
183 function testDCE() {
184     let testObject = {
185         counter: 0,
186         valueOf: function() { ++this.counter; return 16; }
187     };
188     for (let i = 0; i < 1e4; ++i) {
189         opaqueTanForDCE(testObject);
190     }
191     if (testObject.counter !== 1e4)
192         throw "Failed testDCE()";
193     if (numberOfDFGCompiles(opaqueTanForDCE) > 1)
194         throw "opaqueTanForDCE() is predictable, it should only be compiled once.";
195 }
196 testDCE();
197
198
199 // Test exceptions in the argument.
200 function testException() {
201     let counter = 0;
202     function opaqueTanWithException(argument) {
203         let result = Math.tan(argument);
204         ++counter;
205         return result;
206     }
207     noInline(opaqueTanWithException);
208
209     let testObject = { valueOf: () => {  return 64; } };
210     let tan64 = Math.tan(64);
211
212     // Warm up without exception.
213     for (let i = 0; i < 1e3; ++i) {
214         if (opaqueTanWithException(testObject) !== tan64)
215             throw "Incorrect result in opaqueTanWithException()";
216     }
217
218     let testThrowObject = { valueOf: () => { throw testObject; return 64; } };
219
220     for (let i = 0; i < 1e2; ++i) {
221         try {
222             if (opaqueTanWithException(testThrowObject) !== 8)
223                 throw "This code should not be reached!!";
224         } catch (e) {
225             if (e !== testObject) {
226                 throw "Wrong object thrown from opaqueTanWithException."
227             }
228         }
229     }
230
231     if (counter !== 1e3) {
232         throw "Invalid count in testException()";
233     }
234 }
235 testException();