blob: 3d2ecb8daa3884a02287bac12b2e25e53d289fdd [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
Ben Murdoch61f157c2016-09-16 13:49:30 +010013var verbose = typeof(arguments) !== "undefined" && arguments.indexOf("-v") >= 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010014
Ben Murdochda12d292016-06-02 14:46:10 +010015function checkStackTrace(expected) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010016 var e = new Error();
17 e.stack; // prepare stack trace
18 var stack = e.strace;
Ben Murdochda12d292016-06-02 14:46:10 +010019 assertEquals("checkStackTrace", stack[0].getFunctionName());
Ben Murdoch097c5b22016-05-18 11:27:45 +010020 for (var i = 0; i < expected.length; i++) {
21 assertEquals(expected[i].name, stack[i + 1].getFunctionName());
22 }
23}
Ben Murdoch097c5b22016-05-18 11:27:45 +010024
25
26var CAN_INLINE_COMMENT = "// Let it be inlined.";
27var DONT_INLINE_COMMENT = (function() {
28 var line = "// Don't inline. Don't inline. Don't inline. Don't inline.";
29 for (var i = 0; i < 4; i++) {
30 line += "\n " + line;
31 }
32 return line;
33})();
34
35
36function ident_source(source, ident) {
37 ident = " ".repeat(ident);
38 return ident + source.replace(/\n/gi, "\n" + ident);
39}
40
Ben Murdochda12d292016-06-02 14:46:10 +010041var SHARDS_COUNT = 10;
Ben Murdoch097c5b22016-05-18 11:27:45 +010042
Ben Murdochda12d292016-06-02 14:46:10 +010043function run_tests(shard) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010044 function inlinable_comment(inlinable) {
45 return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
46 }
47
Ben Murdochda12d292016-06-02 14:46:10 +010048 // 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
61 function deopt_template(deopt_mode) {
62 switch(deopt_mode) {
63 case "none":
64 return " // Don't deoptimize";
65 case "f":
66 case "g":
67 case "test":
68 return ` %DeoptimizeFunction(${deopt_mode});`;
69 default:
70 assertUnreachable();
71 }
72 }
73
Ben Murdoch097c5b22016-05-18 11:27:45 +010074 var f_cfg_sloppy = {
75 func_name: 'f',
76 source_template: function(cfg) {
77 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
78 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +010079 var do_checks = [
80 ` assertEquals_(${receiver}, this);`,
81 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
82 check_arguments,
83 ` checkStackTrace_([f, test]);`,
84 ].join("\n");
85
Ben Murdoch097c5b22016-05-18 11:27:45 +010086 var lines = [
87 `function f(a) {`,
88 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +010089 ` counter++;`,
90 ` var expected_args = [${cfg.f_args}];`,
91 do_checks,
92 deopt_template(cfg.deopt_mode),
93 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +010094 ` return 42;`,
95 `}`,
96 ];
97 return lines.join("\n");
98 },
99 };
100
101 var f_cfg_strict = {
102 func_name: 'f',
103 source_template: function(cfg) {
104 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
105 : "undefined";
Ben Murdochda12d292016-06-02 14:46:10 +0100106 var do_checks = [
107 ` assertEquals_(${receiver}, this);`,
108 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
109 check_arguments,
110 ` checkStackTrace_([f, test]);`,
111 ].join("\n");
112
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 var lines = [
114 `function f(a) {`,
115 ` "use strict";`,
116 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100117 ` counter++;`,
118 ` var expected_args = [${cfg.f_args}];`,
119 do_checks,
120 deopt_template(cfg.deopt_mode),
121 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 ` return 42;`,
123 `}`,
124 ];
125 return lines.join("\n");
126 },
127 };
128
129 var f_cfg_possibly_eval = {
130 func_name: 'eval',
131 source_template: function(cfg) {
132 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
133 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +0100134 var do_checks = [
135 ` assertEquals_(${receiver}, this);`,
136 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
137 check_arguments,
138 ` checkStackTrace_([f, test]);`,
139 ].join("\n");
140
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141 var lines = [
142 `function f(a) {`,
143 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100144 ` counter++;`,
145 ` var expected_args = [${cfg.f_args}];`,
146 do_checks,
147 deopt_template(cfg.deopt_mode),
148 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 ` return 42;`,
150 `}`,
151 `var eval = f;`,
152 ];
153 return lines.join("\n");
154 },
155 };
156
157 var f_cfg_bound = {
158 func_name: 'bound',
159 source_template: function(cfg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100160 var do_checks = [
161 ` assertEquals_(receiver, this);`,
162 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
163 check_arguments,
164 ` checkStackTrace_([f, test]);`,
165 ].join("\n");
166
Ben Murdoch097c5b22016-05-18 11:27:45 +0100167 var lines = [
168 `function f(a) {`,
169 ` "use strict";`,
170 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100171 ` counter++;`,
172 ` var expected_args = [${cfg.f_args}];`,
173 do_checks,
174 deopt_template(cfg.deopt_mode),
175 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100176 ` return 42;`,
177 `}`,
178 `var receiver = {a: 153};`,
179 `var bound = f.bind(receiver);`,
180 ];
181 return lines.join("\n");
182 },
183 };
184
185 var f_cfg_proxy = {
186 func_name: 'p',
187 source_template: function(cfg) {
188 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
189 : "global";
Ben Murdochda12d292016-06-02 14:46:10 +0100190 var do_checks = [
191 ` assertEquals_(${receiver}, this);`,
192 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.target);`,
193 check_arguments,
194 ` checkStackTrace_([f, test]);`,
195 ].join("\n");
196
Ben Murdoch097c5b22016-05-18 11:27:45 +0100197 var lines = [
198 `function f(a) {`,
199 ` ${inlinable_comment(cfg.f_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100200 ` counter++;`,
201 ` var expected_args = [${cfg.f_args}];`,
202 do_checks,
203 deopt_template(cfg.deopt_mode),
204 do_checks,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100205 ` return 42;`,
206 `}`,
207 `var p = new Proxy(f, {});`,
208 ];
209 return lines.join("\n");
210 },
211 };
212
213 var g_cfg_normal = {
214 receiver: undefined,
215 source_template: function(cfg) {
216 var lines = [
217 `function g(a) {`,
218 ` "use strict";`,
219 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100220 ` var expected_args = [${cfg.g_args}];`,
221 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100222 ` return ${cfg.f_name}(${cfg.f_args});`,
223 `}`,
224 ];
225 return lines.join("\n");
226 },
227 };
228
229
Ben Murdochda12d292016-06-02 14:46:10 +0100230 var g_cfg_reflect_apply = {
231 receiver: "the_receiver",
232 source_template: function(cfg) {
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 Reflect.apply(${cfg.f_name}, the_receiver, [${cfg.f_args}]);`,
240 `}`,
241 ];
242 return lines.join("\n");
243 },
244 };
245
246
Ben Murdoch097c5b22016-05-18 11:27:45 +0100247 var g_cfg_function_apply = {
248 receiver: "the_receiver",
249 source_template: function(cfg) {
250 var lines = [
251 `function g(a) {`,
252 ` "use strict";`,
253 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100254 ` var expected_args = [${cfg.g_args}];`,
255 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
257 `}`,
258 ];
259 return lines.join("\n");
260 },
261 };
262
263
Ben Murdochda12d292016-06-02 14:46:10 +0100264 var g_cfg_function_apply_arguments_object = {
265 receiver: "the_receiver",
266 source_template: function(cfg) {
267 cfg.f_args = cfg.g_args;
268 var lines = [
269 `function g(a) {`,
270 ` "use strict";`,
271 ` ${inlinable_comment(cfg.g_inlinable)}`,
272 ` var expected_args = [${cfg.g_args}];`,
273 check_arguments,
274 ` return ${cfg.f_name}.apply(the_receiver, arguments);`,
275 `}`,
276 ];
277 return lines.join("\n");
278 },
279 };
280
281
Ben Murdoch097c5b22016-05-18 11:27:45 +0100282 var g_cfg_function_call = {
283 receiver: "the_receiver",
284 source_template: function(cfg) {
285 var f_args = "the_receiver";
286 if (cfg.f_args !== "") f_args += ", ";
287 f_args += cfg.f_args;
288
289 var lines = [
290 `function g(a) {`,
291 ` "use strict";`,
292 ` ${inlinable_comment(cfg.g_inlinable)}`,
Ben Murdochda12d292016-06-02 14:46:10 +0100293 ` var expected_args = [${cfg.g_args}];`,
294 check_arguments,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 ` return ${cfg.f_name}.call(${f_args});`,
296 `}`,
297 ];
298 return lines.join("\n");
299 },
300 };
301
302
303 function test_template(cfg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100304 // Note: g_source_template modifies cfg.f_args in some cases.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 var g_source = cfg.g_source_template(cfg);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100306 g_source = ident_source(g_source, 2);
307
Ben Murdochda12d292016-06-02 14:46:10 +0100308 var f_source = cfg.f_source_template(cfg);
309 f_source = ident_source(f_source, 2);
310
Ben Murdoch097c5b22016-05-18 11:27:45 +0100311 var lines = [
312 `(function() {`,
Ben Murdochda12d292016-06-02 14:46:10 +0100313 ` // Avoid bailing out because of "Reference to a variable which requires dynamic lookup".`,
314 ` var assertEquals_ = assertEquals;`,
315 ` var checkStackTrace_ = checkStackTrace;`,
316 ` var undefined = void 0;`,
317 ` var global = Function('return this')();`,
318 ` var the_receiver = {receiver: 1};`,
319 ` var counter = 0;`,
320 ``,
321 ` // Don't inline helper functions`,
322 ` %NeverOptimizeFunction(assertEquals);`,
323 ` %NeverOptimizeFunction(checkStackTrace);`,
324 ``,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 f_source,
326 g_source,
327 ` function test() {`,
328 ` "use strict";`,
Ben Murdochda12d292016-06-02 14:46:10 +0100329 ` assertEquals_(42, g(${cfg.g_args}));`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100330 ` }`,
Ben Murdochda12d292016-06-02 14:46:10 +0100331 ` ${"test();".repeat(cfg.test_warmup_count)}`,
332 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : "%OptimizeFunctionOnNextCall(f)"};`,
333 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : "%OptimizeFunctionOnNextCall(g)"};`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100334 ` %OptimizeFunctionOnNextCall(test);`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100335 ` test();`,
Ben Murdochda12d292016-06-02 14:46:10 +0100336 ` assertEquals(${1 + cfg.test_warmup_count}, counter);`,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100337 `})();`,
338 ``,
339 ];
340 var source = lines.join("\n");
341 return source;
342 }
343
Ben Murdoch61f157c2016-09-16 13:49:30 +0100344 var f_args_variants = [/*"", "1",*/ "1, 2"];
345 var g_args_variants = [/*"", "10",*/ "10, 20"];
Ben Murdochda12d292016-06-02 14:46:10 +0100346 var f_inlinable_variants = [true, false];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100347 var g_inlinable_variants = [true, false];
Ben Murdochda12d292016-06-02 14:46:10 +0100348 // This is to avoid bailing out because of referencing new.target.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100349 var check_new_target_variants = [/*true,*/ false];
Ben Murdochda12d292016-06-02 14:46:10 +0100350 var deopt_mode_variants = ["none", "f", "g", "test"];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351 var f_variants = [
352 f_cfg_sloppy,
353 f_cfg_strict,
354 f_cfg_bound,
355 f_cfg_proxy,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100356// f_cfg_possibly_eval,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100357 ];
358 var g_variants = [
359 g_cfg_normal,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100360// g_cfg_reflect_apply,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 g_cfg_function_apply,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100362// g_cfg_function_apply_arguments_object,
Ben Murdochda12d292016-06-02 14:46:10 +0100363 g_cfg_function_call,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100364 ];
Ben Murdochda12d292016-06-02 14:46:10 +0100365 var test_warmup_counts = [0, 1, 2];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366
Ben Murdochda12d292016-06-02 14:46:10 +0100367 var iter = 0;
368 var tests_executed = 0;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100369 if (verbose && shard !== undefined) {
Ben Murdochda12d292016-06-02 14:46:10 +0100370 print("Running shard #" + shard);
371 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100372 f_variants.forEach((f_cfg) => {
Ben Murdochda12d292016-06-02 14:46:10 +0100373 check_new_target_variants.forEach((check_new_target) => {
374 deopt_mode_variants.forEach((deopt_mode) => {
375 g_variants.forEach((g_cfg) => {
376 f_args_variants.forEach((f_args) => {
377 g_args_variants.forEach((g_args) => {
378 f_inlinable_variants.forEach((f_inlinable) => {
379 g_inlinable_variants.forEach((g_inlinable) => {
380 test_warmup_counts.forEach((test_warmup_count) => {
381 if (shard !== undefined && (iter++) % SHARDS_COUNT != shard) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100382 if (verbose) {
383 print("skipping...");
384 }
Ben Murdochda12d292016-06-02 14:46:10 +0100385 return;
386 }
387 tests_executed++;
388 var cfg = {
389 f_source_template: f_cfg.source_template,
390 f_inlinable,
391 f_args,
392 f_name: f_cfg.func_name,
393 f_receiver: g_cfg.receiver,
394 g_source_template: g_cfg.source_template,
395 g_inlinable,
396 g_args,
397 test_warmup_count,
398 check_new_target,
399 deopt_mode,
400 };
401 var source = test_template(cfg);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100402 if (verbose) {
403 // print("====================");
404 // print(source);
405 }
Ben Murdochda12d292016-06-02 14:46:10 +0100406 eval(source);
407 });
408 });
409 });
Ben Murdoch097c5b22016-05-18 11:27:45 +0100410 });
411 });
412 });
413 });
414 });
415 });
Ben Murdoch61f157c2016-09-16 13:49:30 +0100416 if (verbose) {
417 print("Number of tests executed: " + tests_executed);
418 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100419}
420
Ben Murdochda12d292016-06-02 14:46:10 +0100421// Uncomment to run all the tests at once or use shard runners.
422//run_tests();