Index: test/mjsunit/es6/tail-call-megatest.js |
diff --git a/test/mjsunit/es6/tail-call-megatest.js b/test/mjsunit/es6/tail-call-megatest.js |
index 005796195a84cdf319d71ee0bf1b3e145967c232..4f12ff4394b1f2aa843f90b2f1c98a5ff88bdd3c 100644 |
--- a/test/mjsunit/es6/tail-call-megatest.js |
+++ b/test/mjsunit/es6/tail-call-megatest.js |
@@ -3,6 +3,8 @@ |
// found in the LICENSE file. |
// Flags: --allow-natives-syntax --harmony-tailcalls --no-turbo-inlining |
+// TODO(v8:4698), TODO(ishell): support these cases. |
+// Flags: --no-turbo --nostress-opt |
Error.prepareStackTrace = (error,stack) => { |
@@ -11,23 +13,15 @@ Error.prepareStackTrace = (error,stack) => { |
} |
-function CheckStackTrace(expected) { |
+function checkStackTrace(expected) { |
var e = new Error(); |
e.stack; // prepare stack trace |
var stack = e.strace; |
- assertEquals("CheckStackTrace", stack[0].getFunctionName()); |
+ assertEquals("checkStackTrace", stack[0].getFunctionName()); |
for (var i = 0; i < expected.length; i++) { |
assertEquals(expected[i].name, stack[i + 1].getFunctionName()); |
} |
} |
-%NeverOptimizeFunction(CheckStackTrace); |
- |
- |
-function CheckArguments(expected, args) { |
- args = Array.prototype.slice.call(args); |
- assertEquals(expected, args); |
-} |
-%NeverOptimizeFunction(CheckArguments); |
var CAN_INLINE_COMMENT = "// Let it be inlined."; |
@@ -45,28 +39,44 @@ function ident_source(source, ident) { |
return ident + source.replace(/\n/gi, "\n" + ident); |
} |
-var global = Function('return this')(); |
-var the_receiver = {receiver: 1}; |
function run_tests() { |
function inlinable_comment(inlinable) { |
return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT; |
} |
+ // Check arguments manually to avoid bailing out with reason "bad value |
+ // context for arguments value". |
+ function check_arguments_template(expected_name) { |
+ var lines = [ |
+ ` assertEquals_(${expected_name}.length, arguments.length);`, |
+ ` for (var i = 0; i < ${expected_name}.length; i++) {`, |
+ ` assertEquals_(${expected_name}[i], arguments[i]);`, |
+ ` }`, |
+ ]; |
+ return lines.join("\n"); |
+ } |
+ var check_arguments = check_arguments_template("expected_args"); |
+ |
var f_cfg_sloppy = { |
func_name: 'f', |
source_template: function(cfg) { |
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
: "global"; |
+ var do_checks = [ |
+ ` assertEquals_(${receiver}, this);`, |
+ ` assertEquals_(undefined, new.target);`, |
+ check_arguments, |
+ ` checkStackTrace_([f, test]);`, |
+ ].join("\n"); |
+ |
var lines = [ |
`function f(a) {`, |
` ${inlinable_comment(cfg.f_inlinable)}`, |
- ` assertEquals(${receiver}, this);`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ ` var expected_args = [${cfg.f_args}];`, |
+ do_checks, |
` %DeoptimizeNow();`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ do_checks, |
` return 42;`, |
`}`, |
]; |
@@ -79,16 +89,21 @@ function run_tests() { |
source_template: function(cfg) { |
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
: "undefined"; |
+ var do_checks = [ |
+ ` assertEquals_(${receiver}, this);`, |
+ ` assertEquals_(undefined, new.target);`, |
+ check_arguments, |
+ ` checkStackTrace_([f, test]);`, |
+ ].join("\n"); |
+ |
var lines = [ |
`function f(a) {`, |
` "use strict";`, |
` ${inlinable_comment(cfg.f_inlinable)}`, |
- ` assertEquals(${receiver}, this);`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ ` var expected_args = [${cfg.f_args}];`, |
+ do_checks, |
` %DeoptimizeNow();`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ do_checks, |
` return 42;`, |
`}`, |
]; |
@@ -101,15 +116,20 @@ function run_tests() { |
source_template: function(cfg) { |
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
: "global"; |
+ var do_checks = [ |
+ ` assertEquals_(${receiver}, this);`, |
+ ` assertEquals_(undefined, new.target);`, |
+ check_arguments, |
+ ` checkStackTrace_([f, test]);`, |
+ ].join("\n"); |
+ |
var lines = [ |
`function f(a) {`, |
` ${inlinable_comment(cfg.f_inlinable)}`, |
- ` assertEquals(${receiver}, this);`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ ` var expected_args = [${cfg.f_args}];`, |
+ do_checks, |
` %DeoptimizeNow();`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ do_checks, |
` return 42;`, |
`}`, |
`var eval = f;`, |
@@ -121,16 +141,21 @@ function run_tests() { |
var f_cfg_bound = { |
func_name: 'bound', |
source_template: function(cfg) { |
+ var do_checks = [ |
+ ` assertEquals_(receiver, this);`, |
+ ` assertEquals_(undefined, new.target);`, |
+ check_arguments, |
+ ` checkStackTrace_([f, test]);`, |
+ ].join("\n"); |
+ |
var lines = [ |
`function f(a) {`, |
` "use strict";`, |
` ${inlinable_comment(cfg.f_inlinable)}`, |
- ` assertEquals(receiver, this);`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ ` var expected_args = [${cfg.f_args}];`, |
+ do_checks, |
` %DeoptimizeNow();`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ do_checks, |
` return 42;`, |
`}`, |
`var receiver = {a: 153};`, |
@@ -145,15 +170,20 @@ function run_tests() { |
source_template: function(cfg) { |
var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
: "global"; |
+ var do_checks = [ |
+ ` assertEquals_(${receiver}, this);`, |
+ ` assertEquals_(undefined, new.target);`, |
+ check_arguments, |
+ ` checkStackTrace_([f, test]);`, |
+ ].join("\n"); |
+ |
var lines = [ |
`function f(a) {`, |
` ${inlinable_comment(cfg.f_inlinable)}`, |
- ` assertEquals(${receiver}, this);`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ ` var expected_args = [${cfg.f_args}];`, |
+ do_checks, |
` %DeoptimizeNow();`, |
- ` CheckArguments([${cfg.f_args}], arguments);`, |
- ` CheckStackTrace([f, test]);`, |
+ do_checks, |
` return 42;`, |
`}`, |
`var p = new Proxy(f, {});`, |
@@ -169,7 +199,8 @@ function run_tests() { |
`function g(a) {`, |
` "use strict";`, |
` ${inlinable_comment(cfg.g_inlinable)}`, |
- ` CheckArguments([${cfg.g_args}], arguments);`, |
+ ` var expected_args = [${cfg.g_args}];`, |
+ check_arguments, |
` return ${cfg.f_name}(${cfg.f_args});`, |
`}`, |
]; |
@@ -185,7 +216,8 @@ function run_tests() { |
`function g(a) {`, |
` "use strict";`, |
` ${inlinable_comment(cfg.g_inlinable)}`, |
- ` CheckArguments([${cfg.g_args}], arguments);`, |
+ ` var expected_args = [${cfg.g_args}];`, |
+ check_arguments, |
` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`, |
`}`, |
]; |
@@ -194,6 +226,24 @@ function run_tests() { |
}; |
+ var g_cfg_function_apply_arguments_object = { |
+ receiver: "the_receiver", |
+ source_template: function(cfg) { |
+ cfg.f_args = cfg.g_args; |
+ var lines = [ |
+ `function g(a) {`, |
+ ` "use strict";`, |
+ ` ${inlinable_comment(cfg.g_inlinable)}`, |
+ ` var expected_args = [${cfg.g_args}];`, |
+ check_arguments, |
+ ` return ${cfg.f_name}.apply(the_receiver, arguments);`, |
+ `}`, |
+ ]; |
+ return lines.join("\n"); |
+ }, |
+ }; |
+ |
+ |
var g_cfg_function_call = { |
receiver: "the_receiver", |
source_template: function(cfg) { |
@@ -205,7 +255,8 @@ function run_tests() { |
`function g(a) {`, |
` "use strict";`, |
` ${inlinable_comment(cfg.g_inlinable)}`, |
- ` CheckArguments([${cfg.g_args}], arguments);`, |
+ ` var expected_args = [${cfg.g_args}];`, |
+ check_arguments, |
` return ${cfg.f_name}.call(${f_args});`, |
`}`, |
]; |
@@ -215,23 +266,35 @@ function run_tests() { |
function test_template(cfg) { |
- var f_source = cfg.f_source_template(cfg); |
+ // Note: g_source_template modifies cfg.f_args in some cases. |
var g_source = cfg.g_source_template(cfg); |
- f_source = ident_source(f_source, 2); |
g_source = ident_source(g_source, 2); |
+ var f_source = cfg.f_source_template(cfg); |
+ f_source = ident_source(f_source, 2); |
+ |
var lines = [ |
`(function() {`, |
+ ` // Avoid bailing out because of "Reference to a variable which requires dynamic lookup".`, |
+ ` var assertEquals_ = assertEquals;`, |
+ ` var checkStackTrace_ = checkStackTrace;`, |
+ ` var undefined = void 0;`, |
+ ` var global = Function('return this')();`, |
+ ` var the_receiver = {receiver: 1};`, |
+ ``, |
+ ` // Don't inline helper functions`, |
+ ` %NeverOptimizeFunction(assertEquals);`, |
+ ` %NeverOptimizeFunction(checkStackTrace);`, |
+ ``, |
f_source, |
g_source, |
` function test() {`, |
` "use strict";`, |
- ` assertEquals(42, g(${cfg.g_args}));`, |
+ ` assertEquals_(42, g(${cfg.g_args}));`, |
` }`, |
` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`, |
` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`, |
- ``, |
- ` test();`, |
+ ` ${"test();".repeat(cfg.test_warmup_count)}`, |
` %OptimizeFunctionOnNextCall(test);`, |
` %OptimizeFunctionOnNextCall(f);`, |
` %OptimizeFunctionOnNextCall(g);`, |
@@ -245,9 +308,9 @@ function run_tests() { |
// TODO(v8:4698), TODO(ishell): support all commented cases. |
var f_args_variants = ["", "1", "1, 2"]; |
- var g_args_variants = [/*"",*/ "10", /*"10, 20"*/]; |
+ var g_args_variants = ["", "10", "10, 20"]; |
var f_inlinable_variants = [/*true,*/ false]; |
- var g_inlinable_variants = [true, false]; |
+ var g_inlinable_variants = [/*true,*/ false]; |
var f_variants = [ |
f_cfg_sloppy, |
f_cfg_strict, |
@@ -259,7 +322,9 @@ function run_tests() { |
g_cfg_normal, |
g_cfg_function_call, |
g_cfg_function_apply, |
+ g_cfg_function_apply_arguments_object, |
]; |
+ var test_warmup_counts = [0, 1, 2]; |
f_variants.forEach((f_cfg) => { |
g_variants.forEach((g_cfg) => { |
@@ -267,20 +332,23 @@ function run_tests() { |
g_args_variants.forEach((g_args) => { |
f_inlinable_variants.forEach((f_inlinable) => { |
g_inlinable_variants.forEach((g_inlinable) => { |
- var cfg = { |
- f_source_template: f_cfg.source_template, |
- f_inlinable, |
- f_args, |
- f_name: f_cfg.func_name, |
- f_receiver: g_cfg.receiver, |
- g_source_template: g_cfg.source_template, |
- g_inlinable, |
- g_args, |
- }; |
- var source = test_template(cfg); |
- print("===================="); |
- print(source); |
- eval(source); |
+ test_warmup_counts.forEach((test_warmup_count) => { |
+ var cfg = { |
+ f_source_template: f_cfg.source_template, |
+ f_inlinable, |
+ f_args, |
+ f_name: f_cfg.func_name, |
+ f_receiver: g_cfg.receiver, |
+ g_source_template: g_cfg.source_template, |
+ g_inlinable, |
+ g_args, |
+ test_warmup_count, |
+ }; |
+ var source = test_template(cfg); |
+ print("===================="); |
+ print(source); |
+ eval(source); |
+ }); |
}); |
}); |
}); |