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

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

Issue 1760253003: [crankshaft] Support ES6 tail call elimination. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@tco-crank-2
Patch Set: Addressing comments Created 4 years, 9 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 | « test/mjsunit/es6/tail-call.js ('k') | test/mjsunit/es6/tail-call-simple.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 --no-turbo-inlining 5 // Flags: --allow-natives-syntax --harmony-tailcalls --no-turbo-inlining
6 // TODO(v8:4698), TODO(ishell): support these cases.
7 // Flags: --no-turbo --nostress-opt
6 8
7 9
8 Error.prepareStackTrace = (error,stack) => { 10 Error.prepareStackTrace = (error,stack) => {
9 error.strace = stack; 11 error.strace = stack;
10 return error.message + "\n at " + stack.join("\n at "); 12 return error.message + "\n at " + stack.join("\n at ");
11 } 13 }
12 14
13 15
14 function CheckStackTrace(expected) { 16 function checkStackTrace(expected) {
15 var e = new Error(); 17 var e = new Error();
16 e.stack; // prepare stack trace 18 e.stack; // prepare stack trace
17 var stack = e.strace; 19 var stack = e.strace;
18 assertEquals("CheckStackTrace", stack[0].getFunctionName()); 20 assertEquals("checkStackTrace", stack[0].getFunctionName());
19 for (var i = 0; i < expected.length; i++) { 21 for (var i = 0; i < expected.length; i++) {
20 assertEquals(expected[i].name, stack[i + 1].getFunctionName()); 22 assertEquals(expected[i].name, stack[i + 1].getFunctionName());
21 } 23 }
22 } 24 }
23 %NeverOptimizeFunction(CheckStackTrace);
24
25
26 function CheckArguments(expected, args) {
27 args = Array.prototype.slice.call(args);
28 assertEquals(expected, args);
29 }
30 %NeverOptimizeFunction(CheckArguments);
31 25
32 26
33 var CAN_INLINE_COMMENT = "// Let it be inlined."; 27 var CAN_INLINE_COMMENT = "// Let it be inlined.";
34 var DONT_INLINE_COMMENT = (function() { 28 var DONT_INLINE_COMMENT = (function() {
35 var line = "// Don't inline. Don't inline. Don't inline. Don't inline."; 29 var line = "// Don't inline. Don't inline. Don't inline. Don't inline.";
36 for (var i = 0; i < 4; i++) { 30 for (var i = 0; i < 4; i++) {
37 line += "\n " + line; 31 line += "\n " + line;
38 } 32 }
39 return line; 33 return line;
40 })(); 34 })();
41 35
42 36
43 function ident_source(source, ident) { 37 function ident_source(source, ident) {
44 ident = " ".repeat(ident); 38 ident = " ".repeat(ident);
45 return ident + source.replace(/\n/gi, "\n" + ident); 39 return ident + source.replace(/\n/gi, "\n" + ident);
46 } 40 }
47 41
48 var global = Function('return this')();
49 var the_receiver = {receiver: 1};
50 42
51 function run_tests() { 43 function run_tests() {
52 function inlinable_comment(inlinable) { 44 function inlinable_comment(inlinable) {
53 return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT; 45 return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
54 } 46 }
55 47
48 // Check arguments manually to avoid bailing out with reason "bad value
49 // context for arguments value".
50 function check_arguments_template(expected_name) {
51 var lines = [
52 ` assertEquals_(${expected_name}.length, arguments.length);`,
53 ` for (var i = 0; i < ${expected_name}.length; i++) {`,
54 ` assertEquals_(${expected_name}[i], arguments[i]);`,
55 ` }`,
56 ];
57 return lines.join("\n");
58 }
59 var check_arguments = check_arguments_template("expected_args");
60
56 var f_cfg_sloppy = { 61 var f_cfg_sloppy = {
57 func_name: 'f', 62 func_name: 'f',
58 source_template: function(cfg) { 63 source_template: function(cfg) {
59 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver 64 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
60 : "global"; 65 : "global";
66 var do_checks = [
67 ` assertEquals_(${receiver}, this);`,
68 ` assertEquals_(undefined, new.target);`,
69 check_arguments,
70 ` checkStackTrace_([f, test]);`,
71 ].join("\n");
72
61 var lines = [ 73 var lines = [
62 `function f(a) {`, 74 `function f(a) {`,
63 ` ${inlinable_comment(cfg.f_inlinable)}`, 75 ` ${inlinable_comment(cfg.f_inlinable)}`,
64 ` assertEquals(${receiver}, this);`, 76 ` var expected_args = [${cfg.f_args}];`,
65 ` CheckArguments([${cfg.f_args}], arguments);`, 77 do_checks,
66 ` CheckStackTrace([f, test]);`,
67 ` %DeoptimizeNow();`, 78 ` %DeoptimizeNow();`,
68 ` CheckArguments([${cfg.f_args}], arguments);`, 79 do_checks,
69 ` CheckStackTrace([f, test]);`,
70 ` return 42;`, 80 ` return 42;`,
71 `}`, 81 `}`,
72 ]; 82 ];
73 return lines.join("\n"); 83 return lines.join("\n");
74 }, 84 },
75 }; 85 };
76 86
77 var f_cfg_strict = { 87 var f_cfg_strict = {
78 func_name: 'f', 88 func_name: 'f',
79 source_template: function(cfg) { 89 source_template: function(cfg) {
80 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver 90 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
81 : "undefined"; 91 : "undefined";
92 var do_checks = [
93 ` assertEquals_(${receiver}, this);`,
94 ` assertEquals_(undefined, new.target);`,
95 check_arguments,
96 ` checkStackTrace_([f, test]);`,
97 ].join("\n");
98
82 var lines = [ 99 var lines = [
83 `function f(a) {`, 100 `function f(a) {`,
84 ` "use strict";`, 101 ` "use strict";`,
85 ` ${inlinable_comment(cfg.f_inlinable)}`, 102 ` ${inlinable_comment(cfg.f_inlinable)}`,
86 ` assertEquals(${receiver}, this);`, 103 ` var expected_args = [${cfg.f_args}];`,
87 ` CheckArguments([${cfg.f_args}], arguments);`, 104 do_checks,
88 ` CheckStackTrace([f, test]);`,
89 ` %DeoptimizeNow();`, 105 ` %DeoptimizeNow();`,
90 ` CheckArguments([${cfg.f_args}], arguments);`, 106 do_checks,
91 ` CheckStackTrace([f, test]);`,
92 ` return 42;`, 107 ` return 42;`,
93 `}`, 108 `}`,
94 ]; 109 ];
95 return lines.join("\n"); 110 return lines.join("\n");
96 }, 111 },
97 }; 112 };
98 113
99 var f_cfg_possibly_eval = { 114 var f_cfg_possibly_eval = {
100 func_name: 'eval', 115 func_name: 'eval',
101 source_template: function(cfg) { 116 source_template: function(cfg) {
102 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver 117 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
103 : "global"; 118 : "global";
119 var do_checks = [
120 ` assertEquals_(${receiver}, this);`,
121 ` assertEquals_(undefined, new.target);`,
122 check_arguments,
123 ` checkStackTrace_([f, test]);`,
124 ].join("\n");
125
104 var lines = [ 126 var lines = [
105 `function f(a) {`, 127 `function f(a) {`,
106 ` ${inlinable_comment(cfg.f_inlinable)}`, 128 ` ${inlinable_comment(cfg.f_inlinable)}`,
107 ` assertEquals(${receiver}, this);`, 129 ` var expected_args = [${cfg.f_args}];`,
108 ` CheckArguments([${cfg.f_args}], arguments);`, 130 do_checks,
109 ` CheckStackTrace([f, test]);`,
110 ` %DeoptimizeNow();`, 131 ` %DeoptimizeNow();`,
111 ` CheckArguments([${cfg.f_args}], arguments);`, 132 do_checks,
112 ` CheckStackTrace([f, test]);`,
113 ` return 42;`, 133 ` return 42;`,
114 `}`, 134 `}`,
115 `var eval = f;`, 135 `var eval = f;`,
116 ]; 136 ];
117 return lines.join("\n"); 137 return lines.join("\n");
118 }, 138 },
119 }; 139 };
120 140
121 var f_cfg_bound = { 141 var f_cfg_bound = {
122 func_name: 'bound', 142 func_name: 'bound',
123 source_template: function(cfg) { 143 source_template: function(cfg) {
144 var do_checks = [
145 ` assertEquals_(receiver, this);`,
146 ` assertEquals_(undefined, new.target);`,
147 check_arguments,
148 ` checkStackTrace_([f, test]);`,
149 ].join("\n");
150
124 var lines = [ 151 var lines = [
125 `function f(a) {`, 152 `function f(a) {`,
126 ` "use strict";`, 153 ` "use strict";`,
127 ` ${inlinable_comment(cfg.f_inlinable)}`, 154 ` ${inlinable_comment(cfg.f_inlinable)}`,
128 ` assertEquals(receiver, this);`, 155 ` var expected_args = [${cfg.f_args}];`,
129 ` CheckArguments([${cfg.f_args}], arguments);`, 156 do_checks,
130 ` CheckStackTrace([f, test]);`,
131 ` %DeoptimizeNow();`, 157 ` %DeoptimizeNow();`,
132 ` CheckArguments([${cfg.f_args}], arguments);`, 158 do_checks,
133 ` CheckStackTrace([f, test]);`,
134 ` return 42;`, 159 ` return 42;`,
135 `}`, 160 `}`,
136 `var receiver = {a: 153};`, 161 `var receiver = {a: 153};`,
137 `var bound = f.bind(receiver);`, 162 `var bound = f.bind(receiver);`,
138 ]; 163 ];
139 return lines.join("\n"); 164 return lines.join("\n");
140 }, 165 },
141 }; 166 };
142 167
143 var f_cfg_proxy = { 168 var f_cfg_proxy = {
144 func_name: 'p', 169 func_name: 'p',
145 source_template: function(cfg) { 170 source_template: function(cfg) {
146 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver 171 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
147 : "global"; 172 : "global";
173 var do_checks = [
174 ` assertEquals_(${receiver}, this);`,
175 ` assertEquals_(undefined, new.target);`,
176 check_arguments,
177 ` checkStackTrace_([f, test]);`,
178 ].join("\n");
179
148 var lines = [ 180 var lines = [
149 `function f(a) {`, 181 `function f(a) {`,
150 ` ${inlinable_comment(cfg.f_inlinable)}`, 182 ` ${inlinable_comment(cfg.f_inlinable)}`,
151 ` assertEquals(${receiver}, this);`, 183 ` var expected_args = [${cfg.f_args}];`,
152 ` CheckArguments([${cfg.f_args}], arguments);`, 184 do_checks,
153 ` CheckStackTrace([f, test]);`,
154 ` %DeoptimizeNow();`, 185 ` %DeoptimizeNow();`,
155 ` CheckArguments([${cfg.f_args}], arguments);`, 186 do_checks,
156 ` CheckStackTrace([f, test]);`,
157 ` return 42;`, 187 ` return 42;`,
158 `}`, 188 `}`,
159 `var p = new Proxy(f, {});`, 189 `var p = new Proxy(f, {});`,
160 ]; 190 ];
161 return lines.join("\n"); 191 return lines.join("\n");
162 }, 192 },
163 }; 193 };
164 194
165 var g_cfg_normal = { 195 var g_cfg_normal = {
166 receiver: undefined, 196 receiver: undefined,
167 source_template: function(cfg) { 197 source_template: function(cfg) {
168 var lines = [ 198 var lines = [
169 `function g(a) {`, 199 `function g(a) {`,
170 ` "use strict";`, 200 ` "use strict";`,
171 ` ${inlinable_comment(cfg.g_inlinable)}`, 201 ` ${inlinable_comment(cfg.g_inlinable)}`,
172 ` CheckArguments([${cfg.g_args}], arguments);`, 202 ` var expected_args = [${cfg.g_args}];`,
203 check_arguments,
173 ` return ${cfg.f_name}(${cfg.f_args});`, 204 ` return ${cfg.f_name}(${cfg.f_args});`,
174 `}`, 205 `}`,
175 ]; 206 ];
176 return lines.join("\n"); 207 return lines.join("\n");
177 }, 208 },
178 }; 209 };
179 210
180 211
181 var g_cfg_function_apply = { 212 var g_cfg_function_apply = {
182 receiver: "the_receiver", 213 receiver: "the_receiver",
183 source_template: function(cfg) { 214 source_template: function(cfg) {
184 var lines = [ 215 var lines = [
185 `function g(a) {`, 216 `function g(a) {`,
186 ` "use strict";`, 217 ` "use strict";`,
187 ` ${inlinable_comment(cfg.g_inlinable)}`, 218 ` ${inlinable_comment(cfg.g_inlinable)}`,
188 ` CheckArguments([${cfg.g_args}], arguments);`, 219 ` var expected_args = [${cfg.g_args}];`,
220 check_arguments,
189 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`, 221 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
190 `}`, 222 `}`,
191 ]; 223 ];
192 return lines.join("\n"); 224 return lines.join("\n");
193 }, 225 },
194 }; 226 };
195 227
196 228
229 var g_cfg_function_apply_arguments_object = {
230 receiver: "the_receiver",
231 source_template: function(cfg) {
232 cfg.f_args = cfg.g_args;
233 var lines = [
234 `function g(a) {`,
235 ` "use strict";`,
236 ` ${inlinable_comment(cfg.g_inlinable)}`,
237 ` var expected_args = [${cfg.g_args}];`,
238 check_arguments,
239 ` return ${cfg.f_name}.apply(the_receiver, arguments);`,
240 `}`,
241 ];
242 return lines.join("\n");
243 },
244 };
245
246
197 var g_cfg_function_call = { 247 var g_cfg_function_call = {
198 receiver: "the_receiver", 248 receiver: "the_receiver",
199 source_template: function(cfg) { 249 source_template: function(cfg) {
200 var f_args = "the_receiver"; 250 var f_args = "the_receiver";
201 if (cfg.f_args !== "") f_args += ", "; 251 if (cfg.f_args !== "") f_args += ", ";
202 f_args += cfg.f_args; 252 f_args += cfg.f_args;
203 253
204 var lines = [ 254 var lines = [
205 `function g(a) {`, 255 `function g(a) {`,
206 ` "use strict";`, 256 ` "use strict";`,
207 ` ${inlinable_comment(cfg.g_inlinable)}`, 257 ` ${inlinable_comment(cfg.g_inlinable)}`,
208 ` CheckArguments([${cfg.g_args}], arguments);`, 258 ` var expected_args = [${cfg.g_args}];`,
259 check_arguments,
209 ` return ${cfg.f_name}.call(${f_args});`, 260 ` return ${cfg.f_name}.call(${f_args});`,
210 `}`, 261 `}`,
211 ]; 262 ];
212 return lines.join("\n"); 263 return lines.join("\n");
213 }, 264 },
214 }; 265 };
215 266
216 267
217 function test_template(cfg) { 268 function test_template(cfg) {
269 // Note: g_source_template modifies cfg.f_args in some cases.
270 var g_source = cfg.g_source_template(cfg);
271 g_source = ident_source(g_source, 2);
272
218 var f_source = cfg.f_source_template(cfg); 273 var f_source = cfg.f_source_template(cfg);
219 var g_source = cfg.g_source_template(cfg);
220 f_source = ident_source(f_source, 2); 274 f_source = ident_source(f_source, 2);
221 g_source = ident_source(g_source, 2);
222 275
223 var lines = [ 276 var lines = [
224 `(function() {`, 277 `(function() {`,
278 ` // Avoid bailing out because of "Reference to a variable which requires dynamic lookup".`,
279 ` var assertEquals_ = assertEquals;`,
280 ` var checkStackTrace_ = checkStackTrace;`,
281 ` var undefined = void 0;`,
282 ` var global = Function('return this')();`,
283 ` var the_receiver = {receiver: 1};`,
284 ``,
285 ` // Don't inline helper functions`,
286 ` %NeverOptimizeFunction(assertEquals);`,
287 ` %NeverOptimizeFunction(checkStackTrace);`,
288 ``,
225 f_source, 289 f_source,
226 g_source, 290 g_source,
227 ` function test() {`, 291 ` function test() {`,
228 ` "use strict";`, 292 ` "use strict";`,
229 ` assertEquals(42, g(${cfg.g_args}));`, 293 ` assertEquals_(42, g(${cfg.g_args}));`,
230 ` }`, 294 ` }`,
231 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`, 295 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`,
232 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`, 296 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`,
233 ``, 297 ` ${"test();".repeat(cfg.test_warmup_count)}`,
234 ` test();`,
235 ` %OptimizeFunctionOnNextCall(test);`, 298 ` %OptimizeFunctionOnNextCall(test);`,
236 ` %OptimizeFunctionOnNextCall(f);`, 299 ` %OptimizeFunctionOnNextCall(f);`,
237 ` %OptimizeFunctionOnNextCall(g);`, 300 ` %OptimizeFunctionOnNextCall(g);`,
238 ` test();`, 301 ` test();`,
239 `})();`, 302 `})();`,
240 ``, 303 ``,
241 ]; 304 ];
242 var source = lines.join("\n"); 305 var source = lines.join("\n");
243 return source; 306 return source;
244 } 307 }
245 308
246 // TODO(v8:4698), TODO(ishell): support all commented cases. 309 // TODO(v8:4698), TODO(ishell): support all commented cases.
247 var f_args_variants = ["", "1", "1, 2"]; 310 var f_args_variants = ["", "1", "1, 2"];
248 var g_args_variants = [/*"",*/ "10", /*"10, 20"*/]; 311 var g_args_variants = ["", "10", "10, 20"];
249 var f_inlinable_variants = [/*true,*/ false]; 312 var f_inlinable_variants = [/*true,*/ false];
250 var g_inlinable_variants = [true, false]; 313 var g_inlinable_variants = [/*true,*/ false];
251 var f_variants = [ 314 var f_variants = [
252 f_cfg_sloppy, 315 f_cfg_sloppy,
253 f_cfg_strict, 316 f_cfg_strict,
254 f_cfg_bound, 317 f_cfg_bound,
255 f_cfg_proxy, 318 f_cfg_proxy,
256 f_cfg_possibly_eval, 319 f_cfg_possibly_eval,
257 ]; 320 ];
258 var g_variants = [ 321 var g_variants = [
259 g_cfg_normal, 322 g_cfg_normal,
260 g_cfg_function_call, 323 g_cfg_function_call,
261 g_cfg_function_apply, 324 g_cfg_function_apply,
325 g_cfg_function_apply_arguments_object,
262 ]; 326 ];
327 var test_warmup_counts = [0, 1, 2];
263 328
264 f_variants.forEach((f_cfg) => { 329 f_variants.forEach((f_cfg) => {
265 g_variants.forEach((g_cfg) => { 330 g_variants.forEach((g_cfg) => {
266 f_args_variants.forEach((f_args) => { 331 f_args_variants.forEach((f_args) => {
267 g_args_variants.forEach((g_args) => { 332 g_args_variants.forEach((g_args) => {
268 f_inlinable_variants.forEach((f_inlinable) => { 333 f_inlinable_variants.forEach((f_inlinable) => {
269 g_inlinable_variants.forEach((g_inlinable) => { 334 g_inlinable_variants.forEach((g_inlinable) => {
270 var cfg = { 335 test_warmup_counts.forEach((test_warmup_count) => {
271 f_source_template: f_cfg.source_template, 336 var cfg = {
272 f_inlinable, 337 f_source_template: f_cfg.source_template,
273 f_args, 338 f_inlinable,
274 f_name: f_cfg.func_name, 339 f_args,
275 f_receiver: g_cfg.receiver, 340 f_name: f_cfg.func_name,
276 g_source_template: g_cfg.source_template, 341 f_receiver: g_cfg.receiver,
277 g_inlinable, 342 g_source_template: g_cfg.source_template,
278 g_args, 343 g_inlinable,
279 }; 344 g_args,
280 var source = test_template(cfg); 345 test_warmup_count,
281 print("===================="); 346 };
282 print(source); 347 var source = test_template(cfg);
283 eval(source); 348 print("====================");
349 print(source);
350 eval(source);
351 });
284 }); 352 });
285 }); 353 });
286 }); 354 });
287 }); 355 });
288 }); 356 });
289 }); 357 });
290 } 358 }
291 359
292 run_tests(); 360 run_tests();
OLDNEW
« no previous file with comments | « test/mjsunit/es6/tail-call.js ('k') | test/mjsunit/es6/tail-call-simple.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698