OLD | NEW |
| (Empty) |
1 // Copyright 2013 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | |
28 // Flags: --allow-natives-syntax | |
29 | |
30 // Test the correct placement of the simulates after HCompareGenericAndBranch: | |
31 function Checker() { | |
32 this.str = "1"; | |
33 var toStringCalled = 0; | |
34 var toStringExpected = 0; | |
35 this.toString = function() { | |
36 toStringCalled++; | |
37 return this.str; | |
38 }; | |
39 this.check = function() { | |
40 toStringExpected++; | |
41 assertEquals(toStringExpected, toStringCalled); | |
42 }; | |
43 }; | |
44 var left = new Checker(); | |
45 var right = new Checker(); | |
46 | |
47 // This test compares a < b against x < y where | |
48 // x/y are objects providing a/b as toString. In the end we | |
49 // check if the observable side effects match our | |
50 // expectations, thus we make sure that we deopted to a | |
51 // simulate after the comparison was done. | |
52 function test(a,b) { | |
53 left.str = a; | |
54 right.str = b; | |
55 if (left >= right) { | |
56 assertTrue(a >= b); | |
57 } else { | |
58 assertFalse(a >= b); | |
59 } | |
60 left.check(); | |
61 right.check(); | |
62 } | |
63 | |
64 test("ab","abc"); | |
65 test("ab","a"); | |
66 %OptimizeFunctionOnNextCall(test); | |
67 test("a","ab"); | |
68 test(1,"a"); | |
69 test("a","ab"); | |
70 %OptimizeFunctionOnNextCall(test); | |
71 test("a","ab"); | |
72 test("a",1); | |
73 test("ab","a"); | |
74 | |
75 | |
76 // Use generic compare in value, effect and test contexts | |
77 | |
78 function Checker2() { | |
79 var valueOfCalled = 0; | |
80 this.valueOf = function() { | |
81 return valueOfCalled++; | |
82 } | |
83 this.valueOfCalled = function() { | |
84 return valueOfCalled; | |
85 } | |
86 } | |
87 | |
88 var x = new Checker2(); | |
89 var y = new Checker2(); | |
90 | |
91 if (x < y || y < x || x <= y) { | |
92 assertEquals(3, x.valueOfCalled()); | |
93 assertEquals(3, y.valueOfCalled()); | |
94 assertEquals(1, (x < y) + (y < x) + (x <= y)) | |
95 assertEquals(6, x.valueOfCalled()); | |
96 assertEquals(6, y.valueOfCalled()); | |
97 x < y; | |
98 assertEquals(7, x.valueOfCalled()); | |
99 assertEquals(7, y.valueOfCalled()); | |
100 x < y; | |
101 assertEquals(8, x.valueOfCalled()); | |
102 assertEquals(8, y.valueOfCalled()); | |
103 var res; | |
104 if (x <= y) { | |
105 res = 1+(x > {}); | |
106 } else { | |
107 assertTrue(false); | |
108 res = y <= {}; | |
109 } | |
110 assertEquals(10, x.valueOfCalled()); | |
111 assertEquals(9, y.valueOfCalled()); | |
112 assertEquals(1, res); | |
113 assertFalse(x < y); | |
114 | |
115 var tb = 0, fb = 0; | |
116 var val = 0; | |
117 for (var i = 1; i < 10; i++) { | |
118 var res = 0; | |
119 // uses x,y in control context | |
120 if (x <= y) { | |
121 res += val; | |
122 assertTrue(x <= y); | |
123 // adds 1 + 0, uses x in value context | |
124 res += 1+(x > {}); | |
125 tb++; | |
126 assertEquals(fb, tb); | |
127 } else { | |
128 res += val; | |
129 assertFalse(x < y); | |
130 // adds 1, uses y in value context, increments 2 | |
131 res += (y <= y); | |
132 // use x in value context, increments x once to make it equal to y again | |
133 x + 2; | |
134 assertEquals(fb, tb); | |
135 fb++; | |
136 } | |
137 assertEquals(11+(2*i)+tb+fb, x.valueOfCalled()); | |
138 assertEquals(10+(2*i)+(2*fb), y.valueOfCalled()); | |
139 assertEquals(1 + val, res); | |
140 // Triggers deopt inside branch. | |
141 if (i%5 == 0) val += 0.5; | |
142 } | |
143 } else { | |
144 assertTrue(false); | |
145 } | |
146 | |
147 | |
148 function t(a,b) { return (b < a) - (a < b); }; | |
149 function f() { | |
150 x = new Checker2(); | |
151 y = new Checker2(); | |
152 var tb = 0, fb = 0; | |
153 var val = 0; | |
154 for (var i = 1; i < 10; i++) { | |
155 var res = 0; | |
156 if ((x < y) + (y < x)) { | |
157 res += val; | |
158 res += x<0; | |
159 fb++; | |
160 } else { | |
161 res += val; | |
162 res += y<0; | |
163 tb++; | |
164 } | |
165 assertEquals(0, res + 1 - res - 1); | |
166 assertEquals((2*i)+fb, x.valueOfCalled()); | |
167 assertEquals((2*i)+tb, y.valueOfCalled()); | |
168 assertEquals(val, res); | |
169 if (i%4 == 0) val += 0.5; | |
170 } | |
171 } | |
172 | |
173 f(); | |
174 %OptimizeFunctionOnNextCall(f); | |
175 f(); | |
176 | |
177 var a = {valueOf: function(){this.conv++; return 1;}}; | |
178 var b = {valueOf: function(){this.conv++; return 2;}}; | |
179 | |
180 a.conv = 0; | |
181 b.conv = 0; | |
182 | |
183 function f2(a,b,d1,d2) { | |
184 var runs = 0; | |
185 if ((a < b) + (a < b)) { | |
186 if (d2) { d2 += 0.2; } | |
187 runs++; | |
188 } else { | |
189 assertUnreachable(); | |
190 } | |
191 assertEquals(1, runs); | |
192 if (a > b) { | |
193 assertUnreachable(); | |
194 } else { | |
195 if (d1) { d1 += 0.2; } | |
196 runs++; | |
197 } | |
198 assertEquals(2, runs); | |
199 } | |
200 | |
201 f2(a,b); | |
202 f2(a,b); | |
203 | |
204 %OptimizeFunctionOnNextCall(f2); | |
205 f2(a,b); | |
206 f2(a,b); | |
207 | |
208 f2(a,b,true); | |
209 f2(a,b); | |
210 | |
211 %OptimizeFunctionOnNextCall(f2); | |
212 f2(a,b); | |
213 f2(a,b); | |
214 | |
215 f2(a,b,false,true); | |
216 f2(a,b); | |
217 | |
218 assertEquals(30, a.conv); | |
219 assertEquals(30, b.conv); | |
220 | |
221 b.valueOf = function(){ return {}; } | |
222 try { | |
223 f2(a,b); | |
224 } catch(e) { | |
225 res = e.stack; | |
226 } | |
OLD | NEW |