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