Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1157)

Side by Side Diff: test/mjsunit/es6/tail-call.js

Issue 1709583002: [turbofan] Fixing ES6 tail calls in Turbofan. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressing comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/instruction-selector.cc ('k') | test/mjsunit/es6/tail-call-megatest.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Flags: --allow-natives-syntax --harmony-tailcalls 5 // Flags: --allow-natives-syntax --harmony-tailcalls
6 "use strict"; 6 "use strict";
7 7
8 Error.prepareStackTrace = (e,s) => s; 8 Error.prepareStackTrace = (error,stack) => {
9 error.strace = stack;
10 return error.message + "\n at " + stack.join("\n at ");
11 }
12
9 13
10 function CheckStackTrace(expected) { 14 function CheckStackTrace(expected) {
11 var stack = (new Error()).stack; 15 var e = new Error();
16 e.stack; // prepare stack trace
17 var stack = e.strace;
12 assertEquals("CheckStackTrace", stack[0].getFunctionName()); 18 assertEquals("CheckStackTrace", stack[0].getFunctionName());
13 for (var i = 0; i < expected.length; i++) { 19 for (var i = 0; i < expected.length; i++) {
14 assertEquals(expected[i].name, stack[i + 1].getFunctionName()); 20 assertEquals(expected[i].name, stack[i + 1].getFunctionName());
15 } 21 }
16 } 22 }
17 23
18 function f(expected_call_stack, a, b) { 24 function f(expected_call_stack, a, b) {
19 CheckStackTrace(expected_call_stack); 25 CheckStackTrace(expected_call_stack);
20 return a; 26 return a;
21 } 27 }
22 28
23 function f_153(expected_call_stack, a) { 29 function f_153(expected_call_stack, a) {
24 CheckStackTrace(expected_call_stack); 30 CheckStackTrace(expected_call_stack);
25 return 153; 31 return 153;
26 } 32 }
27 33
28 34
29 // Tail call when caller does not have an arguments adaptor frame. 35 // Tail call when caller does not have an arguments adaptor frame.
30 (function test() { 36 (function() {
31 // Caller and callee have same number of arguments. 37 // Caller and callee have same number of arguments.
32 function f1(a) { 38 function f1(a) {
33 CheckStackTrace([f1, test]); 39 CheckStackTrace([f1, test]);
34 return 10 + a; 40 return 10 + a;
35 } 41 }
36 function g1(a) { return f1(2); } 42 function g1(a) { return f1(2); }
37 assertEquals(12, g1(1));
38 43
39 // Caller has more arguments than callee. 44 // Caller has more arguments than callee.
40 function f2(a) { 45 function f2(a) {
41 CheckStackTrace([f2, test]); 46 CheckStackTrace([f2, test]);
42 return 10 + a; 47 return 10 + a;
43 } 48 }
44 function g2(a, b, c) { return f2(2); } 49 function g2(a, b, c) { return f2(2); }
45 assertEquals(12, g2(1, 2, 3));
46 50
47 // Caller has less arguments than callee. 51 // Caller has less arguments than callee.
48 function f3(a, b, c) { 52 function f3(a, b, c) {
49 CheckStackTrace([f3, test]); 53 CheckStackTrace([f3, test]);
50 return 10 + a + b + c; 54 return 10 + a + b + c;
51 } 55 }
52 function g3(a) { return f3(2, 3, 4); } 56 function g3(a) { return f3(2, 3, 4); }
53 assertEquals(19, g3(1));
54 57
55 // Callee has arguments adaptor frame. 58 // Callee has arguments adaptor frame.
56 function f4(a, b, c) { 59 function f4(a, b, c) {
57 CheckStackTrace([f4, test]); 60 CheckStackTrace([f4, test]);
58 return 10 + a; 61 return 10 + a;
59 } 62 }
60 function g4(a) { return f4(2); } 63 function g4(a) { return f4(2); }
61 assertEquals(12, g4(1)); 64
65 function test() {
66 assertEquals(12, g1(1));
67 assertEquals(12, g2(1, 2, 3));
68 assertEquals(19, g3(1));
69 assertEquals(12, g4(1));
70 }
71 test();
72 %OptimizeFunctionOnNextCall(test);
73 test();
62 })(); 74 })();
63 75
64 76
65 // Tail call when caller has an arguments adaptor frame. 77 // Tail call when caller has an arguments adaptor frame.
66 (function test() { 78 (function() {
67 // Caller and callee have same number of arguments. 79 // Caller and callee have same number of arguments.
68 function f1(a) { 80 function f1(a) {
69 CheckStackTrace([f1, test]); 81 CheckStackTrace([f1, test]);
70 return 10 + a; 82 return 10 + a;
71 } 83 }
72 function g1(a) { return f1(2); } 84 function g1(a) { return f1(2); }
73 assertEquals(12, g1());
74 85
75 // Caller has more arguments than callee. 86 // Caller has more arguments than callee.
76 function f2(a) { 87 function f2(a) {
77 CheckStackTrace([f2, test]); 88 CheckStackTrace([f2, test]);
78 return 10 + a; 89 return 10 + a;
79 } 90 }
80 function g2(a, b, c) { return f2(2); } 91 function g2(a, b, c) { return f2(2); }
81 assertEquals(12, g2());
82 92
83 // Caller has less arguments than callee. 93 // Caller has less arguments than callee.
84 function f3(a, b, c) { 94 function f3(a, b, c) {
85 CheckStackTrace([f3, test]); 95 CheckStackTrace([f3, test]);
86 return 10 + a + b + c; 96 return 10 + a + b + c;
87 } 97 }
88 function g3(a) { return f3(2, 3, 4); } 98 function g3(a) { return f3(2, 3, 4); }
89 assertEquals(19, g3());
90 99
91 // Callee has arguments adaptor frame. 100 // Callee has arguments adaptor frame.
92 function f4(a, b, c) { 101 function f4(a, b, c) {
93 CheckStackTrace([f4, test]); 102 CheckStackTrace([f4, test]);
94 return 10 + a; 103 return 10 + a;
95 } 104 }
96 function g4(a) { return f4(2); } 105 function g4(a) { return f4(2); }
97 assertEquals(12, g4()); 106
107 function test() {
108 assertEquals(12, g1());
109 assertEquals(12, g2());
110 assertEquals(19, g3());
111 assertEquals(12, g4());
112 }
113 test();
114 %OptimizeFunctionOnNextCall(test);
115 test();
98 })(); 116 })();
99 117
100 118
101 // Tail call bound function when caller does not have an arguments 119 // Tail call bound function when caller does not have an arguments
102 // adaptor frame. 120 // adaptor frame.
103 (function test() { 121 (function() {
104 // Caller and callee have same number of arguments. 122 // Caller and callee have same number of arguments.
105 function f1(a) { 123 function f1(a) {
106 assertEquals(153, this.a); 124 assertEquals(153, this.a);
107 CheckStackTrace([f1, test]); 125 CheckStackTrace([f1, test]);
108 return 10 + a; 126 return 10 + a;
109 } 127 }
110 var b1 = f1.bind({a: 153}); 128 var b1 = f1.bind({a: 153});
111 function g1(a) { return b1(2); } 129 function g1(a) { return b1(2); }
112 assertEquals(12, g1(1));
113 130
114 // Caller has more arguments than callee. 131 // Caller has more arguments than callee.
115 function f2(a) { 132 function f2(a) {
116 assertEquals(153, this.a); 133 assertEquals(153, this.a);
117 CheckStackTrace([f2, test]); 134 CheckStackTrace([f2, test]);
118 return 10 + a; 135 return 10 + a;
119 } 136 }
120 var b2 = f2.bind({a: 153}); 137 var b2 = f2.bind({a: 153});
121 function g2(a, b, c) { return b2(2); } 138 function g2(a, b, c) { return b2(2); }
122 assertEquals(12, g2(1, 2, 3));
123 139
124 // Caller has less arguments than callee. 140 // Caller has less arguments than callee.
125 function f3(a, b, c) { 141 function f3(a, b, c) {
126 assertEquals(153, this.a); 142 assertEquals(153, this.a);
127 CheckStackTrace([f3, test]); 143 CheckStackTrace([f3, test]);
128 return 10 + a + b + c; 144 return 10 + a + b + c;
129 } 145 }
130 var b3 = f3.bind({a: 153}); 146 var b3 = f3.bind({a: 153});
131 function g3(a) { return b3(2, 3, 4); } 147 function g3(a) { return b3(2, 3, 4); }
132 assertEquals(19, g3(1));
133 148
134 // Callee has arguments adaptor frame. 149 // Callee has arguments adaptor frame.
135 function f4(a, b, c) { 150 function f4(a, b, c) {
136 assertEquals(153, this.a); 151 assertEquals(153, this.a);
137 CheckStackTrace([f4, test]); 152 CheckStackTrace([f4, test]);
138 return 10 + a; 153 return 10 + a;
139 } 154 }
140 var b4 = f4.bind({a: 153}); 155 var b4 = f4.bind({a: 153});
141 function g4(a) { return b4(2); } 156 function g4(a) { return b4(2); }
142 assertEquals(12, g4(1)); 157
158 function test() {
159 assertEquals(12, g1(1));
160 assertEquals(12, g2(1, 2, 3));
161 assertEquals(19, g3(1));
162 assertEquals(12, g4(1));
163 }
164 test();
165 %OptimizeFunctionOnNextCall(test);
166 test();
143 })(); 167 })();
144 168
145 169
146 // Tail call bound function when caller has an arguments adaptor frame. 170 // Tail call bound function when caller has an arguments adaptor frame.
147 (function test() { 171 (function() {
148 // Caller and callee have same number of arguments. 172 // Caller and callee have same number of arguments.
149 function f1(a) { 173 function f1(a) {
150 assertEquals(153, this.a); 174 assertEquals(153, this.a);
151 CheckStackTrace([f1, test]); 175 CheckStackTrace([f1, test]);
152 return 10 + a; 176 return 10 + a;
153 } 177 }
154 var b1 = f1.bind({a: 153}); 178 var b1 = f1.bind({a: 153});
155 function g1(a) { return b1(2); } 179 function g1(a) { return b1(2); }
156 assertEquals(12, g1());
157 180
158 // Caller has more arguments than callee. 181 // Caller has more arguments than callee.
159 function f2(a) { 182 function f2(a) {
160 assertEquals(153, this.a); 183 assertEquals(153, this.a);
161 CheckStackTrace([f2, test]); 184 CheckStackTrace([f2, test]);
162 return 10 + a; 185 return 10 + a;
163 } 186 }
164 var b2 = f2.bind({a: 153}); 187 var b2 = f2.bind({a: 153});
165 function g2(a, b, c) { return b2(2); } 188 function g2(a, b, c) { return b2(2); }
166 assertEquals(12, g2());
167 189
168 // Caller has less arguments than callee. 190 // Caller has less arguments than callee.
169 function f3(a, b, c) { 191 function f3(a, b, c) {
170 assertEquals(153, this.a); 192 assertEquals(153, this.a);
171 CheckStackTrace([f3, test]); 193 CheckStackTrace([f3, test]);
172 return 10 + a + b + c; 194 return 10 + a + b + c;
173 } 195 }
174 var b3 = f3.bind({a: 153}); 196 var b3 = f3.bind({a: 153});
175 function g3(a) { return b3(2, 3, 4); } 197 function g3(a) { return b3(2, 3, 4); }
176 assertEquals(19, g3());
177 198
178 // Callee has arguments adaptor frame. 199 // Callee has arguments adaptor frame.
179 function f4(a, b, c) { 200 function f4(a, b, c) {
180 assertEquals(153, this.a); 201 assertEquals(153, this.a);
181 CheckStackTrace([f4, test]); 202 CheckStackTrace([f4, test]);
182 return 10 + a; 203 return 10 + a;
183 } 204 }
184 var b4 = f4.bind({a: 153}); 205 var b4 = f4.bind({a: 153});
185 function g4(a) { return b4(2); } 206 function g4(a) { return b4(2); }
186 assertEquals(12, g4()); 207
208 function test() {
209 assertEquals(12, g1());
210 assertEquals(12, g2());
211 assertEquals(19, g3());
212 assertEquals(12, g4());
213 }
214 test();
215 %OptimizeFunctionOnNextCall(test);
216 test();
187 })(); 217 })();
188 218
189 219
190 // Tail calling via various expressions. 220 // Tail calling via various expressions.
191 (function test() { 221 (function() {
192 function g1(a) { 222 function g1(a) {
193 return f([f, g1, test], false) || f([f, test], true); 223 return f([f, g1, test], false) || f([f, test], true);
194 } 224 }
195 assertEquals(true, g1());
196 225
197 function g2(a) { 226 function g2(a) {
198 return f([f, g2, test], true) && f([f, test], true); 227 return f([f, g2, test], true) && f([f, test], true);
199 } 228 }
200 assertEquals(true, g2());
201 229
202 function g3(a) { 230 function g3(a) {
203 return f([f, g3, test], 13), f([f, test], 153); 231 return f([f, g3, test], 13), f([f, test], 153);
204 } 232 }
205 assertEquals(153, g3()); 233
234 function test() {
235 assertEquals(true, g1());
236 assertEquals(true, g2());
237 assertEquals(153, g3());
238 }
239 test();
240 %OptimizeFunctionOnNextCall(test);
241 test();
206 })(); 242 })();
207 243
208 244
209 // Test tail calls from try-catch-finally constructs. 245 // Test tail calls from try-catch constructs.
210 (function test() { 246 (function() {
211 //
212 // try-catch
213 //
214 function tc1(a) { 247 function tc1(a) {
215 try { 248 try {
216 f_153([f_153, tc1, test]); 249 f_153([f_153, tc1, test]);
217 return f_153([f_153, tc1, test]); 250 return f_153([f_153, tc1, test]);
218 } catch(e) { 251 } catch(e) {
219 f_153([f_153, tc1, test]); 252 f_153([f_153, tc1, test]);
220 } 253 }
221 } 254 }
222 assertEquals(153, tc1());
223 255
224 function tc2(a) { 256 function tc2(a) {
225 try { 257 try {
226 f_153([f_153, tc2, test]); 258 f_153([f_153, tc2, test]);
227 throw new Error("boom"); 259 throw new Error("boom");
228 } catch(e) { 260 } catch(e) {
229 f_153([f_153, tc2, test]); 261 f_153([f_153, tc2, test]);
230 return f_153([f_153, test]); 262 return f_153([f_153, test]);
231 } 263 }
232 } 264 }
233 assertEquals(153, tc2());
234 265
235 function tc3(a) { 266 function tc3(a) {
236 try { 267 try {
237 f_153([f_153, tc3, test]); 268 f_153([f_153, tc3, test]);
238 throw new Error("boom"); 269 throw new Error("boom");
239 } catch(e) { 270 } catch(e) {
240 f_153([f_153, tc3, test]); 271 f_153([f_153, tc3, test]);
241 } 272 }
242 f_153([f_153, tc3, test]); 273 f_153([f_153, tc3, test]);
243 return f_153([f_153, test]); 274 return f_153([f_153, test]);
244 } 275 }
245 assertEquals(153, tc3());
246 276
247 // 277 function test() {
248 // try-finally 278 assertEquals(153, tc1());
249 // 279 assertEquals(153, tc2());
280 assertEquals(153, tc3());
281 }
282 test();
283 %OptimizeFunctionOnNextCall(test);
284 test();
285 })();
286
287
288 // Test tail calls from try-finally constructs.
289 (function() {
250 function tf1(a) { 290 function tf1(a) {
251 try { 291 try {
252 f_153([f_153, tf1, test]); 292 f_153([f_153, tf1, test]);
253 return f_153([f_153, tf1, test]); 293 return f_153([f_153, tf1, test]);
254 } finally { 294 } finally {
255 f_153([f_153, tf1, test]); 295 f_153([f_153, tf1, test]);
256 } 296 }
257 } 297 }
258 assertEquals(153, tf1());
259 298
260 function tf2(a) { 299 function tf2(a) {
261 try { 300 try {
262 f_153([f_153, tf2, test]); 301 f_153([f_153, tf2, test]);
263 throw new Error("boom"); 302 throw new Error("boom");
264 } finally { 303 } finally {
265 f_153([f_153, tf2, test]); 304 f_153([f_153, tf2, test]);
266 return f_153([f_153, test]); 305 return f_153([f_153, test]);
267 } 306 }
268 } 307 }
269 assertEquals(153, tf2());
270 308
271 function tf3(a) { 309 function tf3(a) {
272 try { 310 try {
273 f_153([f_153, tf3, test]); 311 f_153([f_153, tf3, test]);
274 } finally { 312 } finally {
275 f_153([f_153, tf3, test]); 313 f_153([f_153, tf3, test]);
276 } 314 }
277 return f_153([f_153, test]); 315 return f_153([f_153, test]);
278 } 316 }
279 assertEquals(153, tf3());
280 317
281 // 318 function test() {
282 // try-catch-finally 319 assertEquals(153, tf1());
283 // 320 assertEquals(153, tf2());
321 assertEquals(153, tf3());
322 }
323 test();
324 %OptimizeFunctionOnNextCall(test);
325 test();
326 })();
327
328
329 // Test tail calls from try-catch-finally constructs.
330 (function() {
284 function tcf1(a) { 331 function tcf1(a) {
285 try { 332 try {
286 f_153([f_153, tcf1, test]); 333 f_153([f_153, tcf1, test]);
287 return f_153([f_153, tcf1, test]); 334 return f_153([f_153, tcf1, test]);
288 } catch(e) { 335 } catch(e) {
289 } finally { 336 } finally {
290 f_153([f_153, tcf1, test]); 337 f_153([f_153, tcf1, test]);
291 } 338 }
292 } 339 }
293 assertEquals(153, tcf1());
294 340
295 function tcf2(a) { 341 function tcf2(a) {
296 try { 342 try {
297 f_153([f_153, tcf2, test]); 343 f_153([f_153, tcf2, test]);
298 throw new Error("boom"); 344 throw new Error("boom");
299 } catch(e) { 345 } catch(e) {
300 f_153([f_153, tcf2, test]); 346 f_153([f_153, tcf2, test]);
301 return f_153([f_153, tcf2, test]); 347 return f_153([f_153, tcf2, test]);
302 } finally { 348 } finally {
303 f_153([f_153, tcf2, test]); 349 f_153([f_153, tcf2, test]);
304 } 350 }
305 } 351 }
306 assertEquals(153, tcf2());
307 352
308 function tcf3(a) { 353 function tcf3(a) {
309 try { 354 try {
310 f_153([f_153, tcf3, test]); 355 f_153([f_153, tcf3, test]);
311 throw new Error("boom"); 356 throw new Error("boom");
312 } catch(e) { 357 } catch(e) {
313 f_153([f_153, tcf3, test]); 358 f_153([f_153, tcf3, test]);
314 } finally { 359 } finally {
315 f_153([f_153, tcf3, test]); 360 f_153([f_153, tcf3, test]);
316 return f_153([f_153, test]); 361 return f_153([f_153, test]);
317 } 362 }
318 } 363 }
319 assertEquals(153, tcf3());
320 364
321 function tcf4(a) { 365 function tcf4(a) {
322 try { 366 try {
323 f_153([f_153, tcf4, test]); 367 f_153([f_153, tcf4, test]);
324 throw new Error("boom"); 368 throw new Error("boom");
325 } catch(e) { 369 } catch(e) {
326 f_153([f_153, tcf4, test]); 370 f_153([f_153, tcf4, test]);
327 } finally { 371 } finally {
328 f_153([f_153, tcf4, test]); 372 f_153([f_153, tcf4, test]);
329 } 373 }
330 return f_153([f_153, test]); 374 return f_153([f_153, test]);
331 } 375 }
332 assertEquals(153, tcf4()); 376
377 function test() {
378 assertEquals(153, tcf1());
379 assertEquals(153, tcf2());
380 assertEquals(153, tcf3());
381 assertEquals(153, tcf4());
382 }
383 test();
384 %OptimizeFunctionOnNextCall(test);
385 test();
333 })(); 386 })();
OLDNEW
« no previous file with comments | « src/compiler/instruction-selector.cc ('k') | test/mjsunit/es6/tail-call-megatest.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698