blob: 1de8ec6c8e9b54a6ec69024ba1879589c03aba8c [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001// 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
3// found in the LICENSE file.
4
Ben Murdochda12d292016-06-02 14:46:10 +01005// Flags: --allow-natives-syntax --harmony-tailcalls
Ben Murdoch097c5b22016-05-18 11:27:45 +01006
7
8Error.prepareStackTrace = (error,stack) => {
9 error.strace = stack;
10 return error.message + "\n at " + stack.join("\n at ");
11}
12
13
Ben Murdochda12d292016-06-02 14:46:10 +010014function checkStackTrace(expected) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010015 var e = new Error();
16 e.stack; // prepare stack trace
17 var stack = e.strace;
Ben Murdochda12d292016-06-02 14:46:10 +010018 assertEquals("checkStackTrace", stack[0].getFunctionName());
Ben Murdoch097c5b22016-05-18 11:27:45 +010019 for (var i = 0; i < expected.length; i++) {
20 assertEquals(expected[i].name, stack[i + 1].getFunctionName());
21 }
22}
Ben Murdoch097c5b22016-05-18 11:27:45 +010023
24
25var CAN_INLINE_COMMENT = "// Let it be inlined.";
26var DONT_INLINE_COMMENT = (function() {
27 var line = "// Don't inline. Don't inline. Don't inline. Don't inline.";
28 for (var i = 0; i < 4; i++) {
29 line += "\n " + line;
30 }
31 return line;
32})();
33
34
35function ident_source(source, ident) {
36 ident = " ".repeat(ident);
37 return ident + source.replace(/\n/gi, "\n" + ident);
38}
39
Ben Murdochda12d292016-06-02 14:46:10 +010040var SHARDS_COUNT = 10;
Ben Murdoch097c5b22016-05-18 11:27:45 +010041
Ben Murdochda12d292016-06-02 14:46:10 +010042function run_tests(shard) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010043 function inlinable_comment(inlinable) {
44 return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
45 }
46
Ben Murdochda12d292016-06-02 14:46:10 +010047 // Check arguments manually to avoid bailing out with reason "bad value
48 // context for arguments value".
49 function check_arguments_template(expected_name) {
50 var lines = [
51 ` assertEquals_(${expected_name}.length, arguments.length);`,
52 ` for (var i = 0; i < ${expected_name}.length; i++) {`,
53 ` assertEquals_(${expected_name}[i], arguments[i]);`,
54 ` }`,
55 ];
56 return lines.join("\n");
57 }
58 var check_arguments = check_arguments_template("expected_args");
59
60 function deopt_template(deopt_mode) {
61 switch(deopt_mode) {
62 case "none":
63 return " // Don't deoptimize";
64 case "f":
65 case "g":
66 case "test":
67 return ` %DeoptimizeFunction(${deopt_mode});`;
68 default:
69 assertUnreachable();
70 }
71 }
72
Ben Murdoch097c5b22016-05-18 11:27:45 +010073 var f_cfg_sloppy = {
74 func_name: 'f',
75 source_template: function(cfg) {
76 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
77 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +010078 var do_checks = [
79 ` assertEquals_(${receiver}, this);`,
80 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
81 check_arguments,
82 ` checkStackTrace_([f, test]);`,
83 ].join("\n");
84
Ben Murdoch097c5b22016-05-18 11:27:45 +010085 var lines = [
86 `function f(a) {`,
87 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +010088 ` counter++;`,
89 ` var expected_args = [${cfg.f_args}];`,
90 do_checks,
91 deopt_template(cfg.deopt_mode),
92 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +010093 ` return 42;`,
94 `}`,
95 ];
96 return lines.join("\n");
97 },
98 };
99
100 var f_cfg_strict = {
101 func_name: 'f',
102 source_template: function(cfg) {
103 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
104 : "undefined";
Ben Murdochda12d292016-06-02 14:46:10 +0100105 var do_checks = [
106 ` assertEquals_(${receiver}, this);`,
107 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
108 check_arguments,
109 ` checkStackTrace_([f, test]);`,
110 ].join("\n");
111
Ben Murdoch097c5b22016-05-18 11:27:45 +0100112 var lines = [
113 `function f(a) {`,
114 ` "use strict";`,
115 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100116 ` counter++;`,
117 ` var expected_args = [${cfg.f_args}];`,
118 do_checks,
119 deopt_template(cfg.deopt_mode),
120 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100121 ` return 42;`,
122 `}`,
123 ];
124 return lines.join("\n");
125 },
126 };
127
128 var f_cfg_possibly_eval = {
129 func_name: 'eval',
130 source_template: function(cfg) {
131 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
132 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +0100133 var do_checks = [
134 ` assertEquals_(${receiver}, this);`,
135 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
136 check_arguments,
137 ` checkStackTrace_([f, test]);`,
138 ].join("\n");
139
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 var lines = [
141 `function f(a) {`,
142 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100143 ` counter++;`,
144 ` var expected_args = [${cfg.f_args}];`,
145 do_checks,
146 deopt_template(cfg.deopt_mode),
147 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100148 ` return 42;`,
149 `}`,
150 `var eval = f;`,
151 ];
152 return lines.join("\n");
153 },
154 };
155
156 var f_cfg_bound = {
157 func_name: 'bound',
158 source_template: function(cfg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100159 var do_checks = [
160 ` assertEquals_(receiver, this);`,
161 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
162 check_arguments,
163 ` checkStackTrace_([f, test]);`,
164 ].join("\n");
165
Ben Murdoch097c5b22016-05-18 11:27:45 +0100166 var lines = [
167 `function f(a) {`,
168 ` "use strict";`,
169 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100170 ` counter++;`,
171 ` var expected_args = [${cfg.f_args}];`,
172 do_checks,
173 deopt_template(cfg.deopt_mode),
174 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100175 ` return 42;`,
176 `}`,
177 `var receiver = {a: 153};`,
178 `var bound = f.bind(receiver);`,
179 ];
180 return lines.join("\n");
181 },
182 };
183
184 var f_cfg_proxy = {
185 func_name: 'p',
186 source_template: function(cfg) {
187 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
188 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +0100189 var do_checks = [
190 ` assertEquals_(${receiver}, this);`,
191 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
192 check_arguments,
193 ` checkStackTrace_([f, test]);`,
194 ].join("\n");
195
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 var lines = [
197 `function f(a) {`,
198 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100199 ` counter++;`,
200 ` var expected_args = [${cfg.f_args}];`,
201 do_checks,
202 deopt_template(cfg.deopt_mode),
203 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 ` return 42;`,
205 `}`,
206 `var p = new Proxy(f, {});`,
207 ];
208 return lines.join("\n");
209 },
210 };
211
212 var g_cfg_normal = {
213 receiver: undefined,
214 source_template: function(cfg) {
215 var lines = [
216 `function g(a) {`,
217 ` "use strict";`,
218 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100219 ` var expected_args = [${cfg.g_args}];`,
220 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100221 ` return ${cfg.f_name}(${cfg.f_args});`,
222 `}`,
223 ];
224 return lines.join("\n");
225 },
226 };
227
228
Ben Murdochda12d292016-06-02 14:46:10 +0100229 var g_cfg_reflect_apply = {
230 receiver: "the_receiver",
231 source_template: function(cfg) {
232 var lines = [
233 `function g(a) {`,
234 ` "use strict";`,
235 ` ${inlinable_comment(cfg.g_inlinable)}`,
236 ` var expected_args = [${cfg.g_args}];`,
237 check_arguments,
238 ` return Reflect.apply(${cfg.f_name}, the_receiver, [${cfg.f_args}]);`,
239 `}`,
240 ];
241 return lines.join("\n");
242 },
243 };
244
245
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 var g_cfg_function_apply = {
247 receiver: "the_receiver",
248 source_template: function(cfg) {
249 var lines = [
250 `function g(a) {`,
251 ` "use strict";`,
252 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100253 ` var expected_args = [${cfg.g_args}];`,
254 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100255 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
256 `}`,
257 ];
258 return lines.join("\n");
259 },
260 };
261
262
Ben Murdochda12d292016-06-02 14:46:10 +0100263 var g_cfg_function_apply_arguments_object = {
264 receiver: "the_receiver",
265 source_template: function(cfg) {
266 cfg.f_args = cfg.g_args;
267 var lines = [
268 `function g(a) {`,
269 ` "use strict";`,
270 ` ${inlinable_comment(cfg.g_inlinable)}`,
271 ` var expected_args = [${cfg.g_args}];`,
272 check_arguments,
273 ` return ${cfg.f_name}.apply(the_receiver, arguments);`,
274 `}`,
275 ];
276 return lines.join("\n");
277 },
278 };
279
280
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 var g_cfg_function_call = {
282 receiver: "the_receiver",
283 source_template: function(cfg) {
284 var f_args = "the_receiver";
285 if (cfg.f_args !== "") f_args += ", ";
286 f_args += cfg.f_args;
287
288 var lines = [
289 `function g(a) {`,
290 ` "use strict";`,
291 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100292 ` var expected_args = [${cfg.g_args}];`,
293 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100294 ` return ${cfg.f_name}.call(${f_args});`,
295 `}`,
296 ];
297 return lines.join("\n");
298 },
299 };
300
301
302 function test_template(cfg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100303 // Note: g_source_template modifies cfg.f_args in some cases.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100304 var g_source = cfg.g_source_template(cfg);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 g_source = ident_source(g_source, 2);
306
Ben Murdochda12d292016-06-02 14:46:10 +0100307 var f_source = cfg.f_source_template(cfg);
308 f_source = ident_source(f_source, 2);
309
Ben Murdoch097c5b22016-05-18 11:27:45 +0100310 var lines = [
311 `(function() {`,
Ben Murdochda12d292016-06-02 14:46:10 +0100312 ` // Avoid bailing out because of "Reference to a variable which requires dynamic lookup".`,
313 ` var assertEquals_ = assertEquals;`,
314 ` var checkStackTrace_ = checkStackTrace;`,
315 ` var undefined = void 0;`,
316 ` var global = Function('return this')();`,
317 ` var the_receiver = {receiver: 1};`,
318 ` var counter = 0;`,
319 ``,
320 ` // Don't inline helper functions`,
321 ` %NeverOptimizeFunction(assertEquals);`,
322 ` %NeverOptimizeFunction(checkStackTrace);`,
323 ``,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100324 f_source,
325 g_source,
326 ` function test() {`,
327 ` "use strict";`,
Ben Murdochda12d292016-06-02 14:46:10 +0100328 ` assertEquals_(42, g(${cfg.g_args}));`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100329 ` }`,
Ben Murdochda12d292016-06-02 14:46:10 +0100330 ` ${"test();".repeat(cfg.test_warmup_count)}`,
331 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : "%OptimizeFunctionOnNextCall(f)"};`,
332 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : "%OptimizeFunctionOnNextCall(g)"};`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100333 ` %OptimizeFunctionOnNextCall(test);`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100334 ` test();`,
Ben Murdochda12d292016-06-02 14:46:10 +0100335 ` assertEquals(${1 + cfg.test_warmup_count}, counter);`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100336 `})();`,
337 ``,
338 ];
339 var source = lines.join("\n");
340 return source;
341 }
342
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 var f_args_variants = ["", "1", "1, 2"];
Ben Murdochda12d292016-06-02 14:46:10 +0100344 var g_args_variants = ["", "10", "10, 20"];
345 var f_inlinable_variants = [true, false];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100346 var g_inlinable_variants = [true, false];
Ben Murdochda12d292016-06-02 14:46:10 +0100347 // This is to avoid bailing out because of referencing new.target.
348 var check_new_target_variants = [true, false];
349 var deopt_mode_variants = ["none", "f", "g", "test"];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100350 var f_variants = [
351 f_cfg_sloppy,
352 f_cfg_strict,
353 f_cfg_bound,
354 f_cfg_proxy,
355 f_cfg_possibly_eval,
356 ];
357 var g_variants = [
358 g_cfg_normal,
Ben Murdochda12d292016-06-02 14:46:10 +0100359 g_cfg_reflect_apply,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100360 g_cfg_function_apply,
Ben Murdochda12d292016-06-02 14:46:10 +0100361 g_cfg_function_apply_arguments_object,
362 g_cfg_function_call,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100363 ];
Ben Murdochda12d292016-06-02 14:46:10 +0100364 var test_warmup_counts = [0, 1, 2];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100365
Ben Murdochda12d292016-06-02 14:46:10 +0100366 var iter = 0;
367 var tests_executed = 0;
368 if (shard !== undefined) {
369 print("Running shard #" + shard);
370 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100371 f_variants.forEach((f_cfg) => {
Ben Murdochda12d292016-06-02 14:46:10 +0100372 check_new_target_variants.forEach((check_new_target) => {
373 deopt_mode_variants.forEach((deopt_mode) => {
374 g_variants.forEach((g_cfg) => {
375 f_args_variants.forEach((f_args) => {
376 g_args_variants.forEach((g_args) => {
377 f_inlinable_variants.forEach((f_inlinable) => {
378 g_inlinable_variants.forEach((g_inlinable) => {
379 test_warmup_counts.forEach((test_warmup_count) => {
380 if (shard !== undefined && (iter++) % SHARDS_COUNT != shard) {
381 print("skipping...");
382 return;
383 }
384 tests_executed++;
385 var cfg = {
386 f_source_template: f_cfg.source_template,
387 f_inlinable,
388 f_args,
389 f_name: f_cfg.func_name,
390 f_receiver: g_cfg.receiver,
391 g_source_template: g_cfg.source_template,
392 g_inlinable,
393 g_args,
394 test_warmup_count,
395 check_new_target,
396 deopt_mode,
397 };
398 var source = test_template(cfg);
399 print("====================");
400 print(source);
401 eval(source);
402 });
403 });
404 });
Ben Murdoch097c5b22016-05-18 11:27:45 +0100405 });
406 });
407 });
408 });
409 });
410 });
Ben Murdochda12d292016-06-02 14:46:10 +0100411 print("Number of tests executed: " + tests_executed);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100412}
413
Ben Murdochda12d292016-06-02 14:46:10 +0100414// Uncomment to run all the tests at once or use shard runners.
415//run_tests();