blob: 005796195a84cdf319d71ee0bf1b3e145967c232 [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
5// Flags: --allow-natives-syntax --harmony-tailcalls --no-turbo-inlining
6
7
8Error.prepareStackTrace = (error,stack) => {
9 error.strace = stack;
10 return error.message + "\n at " + stack.join("\n at ");
11}
12
13
14function CheckStackTrace(expected) {
15 var e = new Error();
16 e.stack; // prepare stack trace
17 var stack = e.strace;
18 assertEquals("CheckStackTrace", stack[0].getFunctionName());
19 for (var i = 0; i < expected.length; i++) {
20 assertEquals(expected[i].name, stack[i + 1].getFunctionName());
21 }
22}
23%NeverOptimizeFunction(CheckStackTrace);
24
25
26function CheckArguments(expected, args) {
27 args = Array.prototype.slice.call(args);
28 assertEquals(expected, args);
29}
30%NeverOptimizeFunction(CheckArguments);
31
32
33var CAN_INLINE_COMMENT = "// Let it be inlined.";
34var DONT_INLINE_COMMENT = (function() {
35 var line = "// Don't inline. Don't inline. Don't inline. Don't inline.";
36 for (var i = 0; i < 4; i++) {
37 line += "\n " + line;
38 }
39 return line;
40})();
41
42
43function ident_source(source, ident) {
44 ident = " ".repeat(ident);
45 return ident + source.replace(/\n/gi, "\n" + ident);
46}
47
48var global = Function('return this')();
49var the_receiver = {receiver: 1};
50
51function run_tests() {
52 function inlinable_comment(inlinable) {
53 return inlinable ? CAN_INLINE_COMMENT : DONT_INLINE_COMMENT;
54 }
55
56 var f_cfg_sloppy = {
57 func_name: 'f',
58 source_template: function(cfg) {
59 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
60 : "global";
61 var lines = [
62 `function f(a) {`,
63 ` ${inlinable_comment(cfg.f_inlinable)}`,
64 ` assertEquals(${receiver}, this);`,
65 ` CheckArguments([${cfg.f_args}], arguments);`,
66 ` CheckStackTrace([f, test]);`,
67 ` %DeoptimizeNow();`,
68 ` CheckArguments([${cfg.f_args}], arguments);`,
69 ` CheckStackTrace([f, test]);`,
70 ` return 42;`,
71 `}`,
72 ];
73 return lines.join("\n");
74 },
75 };
76
77 var f_cfg_strict = {
78 func_name: 'f',
79 source_template: function(cfg) {
80 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
81 : "undefined";
82 var lines = [
83 `function f(a) {`,
84 ` "use strict";`,
85 ` ${inlinable_comment(cfg.f_inlinable)}`,
86 ` assertEquals(${receiver}, this);`,
87 ` CheckArguments([${cfg.f_args}], arguments);`,
88 ` CheckStackTrace([f, test]);`,
89 ` %DeoptimizeNow();`,
90 ` CheckArguments([${cfg.f_args}], arguments);`,
91 ` CheckStackTrace([f, test]);`,
92 ` return 42;`,
93 `}`,
94 ];
95 return lines.join("\n");
96 },
97 };
98
99 var f_cfg_possibly_eval = {
100 func_name: 'eval',
101 source_template: function(cfg) {
102 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
103 : "global";
104 var lines = [
105 `function f(a) {`,
106 ` ${inlinable_comment(cfg.f_inlinable)}`,
107 ` assertEquals(${receiver}, this);`,
108 ` CheckArguments([${cfg.f_args}], arguments);`,
109 ` CheckStackTrace([f, test]);`,
110 ` %DeoptimizeNow();`,
111 ` CheckArguments([${cfg.f_args}], arguments);`,
112 ` CheckStackTrace([f, test]);`,
113 ` return 42;`,
114 `}`,
115 `var eval = f;`,
116 ];
117 return lines.join("\n");
118 },
119 };
120
121 var f_cfg_bound = {
122 func_name: 'bound',
123 source_template: function(cfg) {
124 var lines = [
125 `function f(a) {`,
126 ` "use strict";`,
127 ` ${inlinable_comment(cfg.f_inlinable)}`,
128 ` assertEquals(receiver, this);`,
129 ` CheckArguments([${cfg.f_args}], arguments);`,
130 ` CheckStackTrace([f, test]);`,
131 ` %DeoptimizeNow();`,
132 ` CheckArguments([${cfg.f_args}], arguments);`,
133 ` CheckStackTrace([f, test]);`,
134 ` return 42;`,
135 `}`,
136 `var receiver = {a: 153};`,
137 `var bound = f.bind(receiver);`,
138 ];
139 return lines.join("\n");
140 },
141 };
142
143 var f_cfg_proxy = {
144 func_name: 'p',
145 source_template: function(cfg) {
146 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver
147 : "global";
148 var lines = [
149 `function f(a) {`,
150 ` ${inlinable_comment(cfg.f_inlinable)}`,
151 ` assertEquals(${receiver}, this);`,
152 ` CheckArguments([${cfg.f_args}], arguments);`,
153 ` CheckStackTrace([f, test]);`,
154 ` %DeoptimizeNow();`,
155 ` CheckArguments([${cfg.f_args}], arguments);`,
156 ` CheckStackTrace([f, test]);`,
157 ` return 42;`,
158 `}`,
159 `var p = new Proxy(f, {});`,
160 ];
161 return lines.join("\n");
162 },
163 };
164
165 var g_cfg_normal = {
166 receiver: undefined,
167 source_template: function(cfg) {
168 var lines = [
169 `function g(a) {`,
170 ` "use strict";`,
171 ` ${inlinable_comment(cfg.g_inlinable)}`,
172 ` CheckArguments([${cfg.g_args}], arguments);`,
173 ` return ${cfg.f_name}(${cfg.f_args});`,
174 `}`,
175 ];
176 return lines.join("\n");
177 },
178 };
179
180
181 var g_cfg_function_apply = {
182 receiver: "the_receiver",
183 source_template: function(cfg) {
184 var lines = [
185 `function g(a) {`,
186 ` "use strict";`,
187 ` ${inlinable_comment(cfg.g_inlinable)}`,
188 ` CheckArguments([${cfg.g_args}], arguments);`,
189 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`,
190 `}`,
191 ];
192 return lines.join("\n");
193 },
194 };
195
196
197 var g_cfg_function_call = {
198 receiver: "the_receiver",
199 source_template: function(cfg) {
200 var f_args = "the_receiver";
201 if (cfg.f_args !== "") f_args += ", ";
202 f_args += cfg.f_args;
203
204 var lines = [
205 `function g(a) {`,
206 ` "use strict";`,
207 ` ${inlinable_comment(cfg.g_inlinable)}`,
208 ` CheckArguments([${cfg.g_args}], arguments);`,
209 ` return ${cfg.f_name}.call(${f_args});`,
210 `}`,
211 ];
212 return lines.join("\n");
213 },
214 };
215
216
217 function test_template(cfg) {
218 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);
221 g_source = ident_source(g_source, 2);
222
223 var lines = [
224 `(function() {`,
225 f_source,
226 g_source,
227 ` function test() {`,
228 ` "use strict";`,
229 ` assertEquals(42, g(${cfg.g_args}));`,
230 ` }`,
231 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`,
232 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`,
233 ``,
234 ` test();`,
235 ` %OptimizeFunctionOnNextCall(test);`,
236 ` %OptimizeFunctionOnNextCall(f);`,
237 ` %OptimizeFunctionOnNextCall(g);`,
238 ` test();`,
239 `})();`,
240 ``,
241 ];
242 var source = lines.join("\n");
243 return source;
244 }
245
246 // TODO(v8:4698), TODO(ishell): support all commented cases.
247 var f_args_variants = ["", "1", "1, 2"];
248 var g_args_variants = [/*"",*/ "10", /*"10, 20"*/];
249 var f_inlinable_variants = [/*true,*/ false];
250 var g_inlinable_variants = [true, false];
251 var f_variants = [
252 f_cfg_sloppy,
253 f_cfg_strict,
254 f_cfg_bound,
255 f_cfg_proxy,
256 f_cfg_possibly_eval,
257 ];
258 var g_variants = [
259 g_cfg_normal,
260 g_cfg_function_call,
261 g_cfg_function_apply,
262 ];
263
264 f_variants.forEach((f_cfg) => {
265 g_variants.forEach((g_cfg) => {
266 f_args_variants.forEach((f_args) => {
267 g_args_variants.forEach((g_args) => {
268 f_inlinable_variants.forEach((f_inlinable) => {
269 g_inlinable_variants.forEach((g_inlinable) => {
270 var cfg = {
271 f_source_template: f_cfg.source_template,
272 f_inlinable,
273 f_args,
274 f_name: f_cfg.func_name,
275 f_receiver: g_cfg.receiver,
276 g_source_template: g_cfg.source_template,
277 g_inlinable,
278 g_args,
279 };
280 var source = test_template(cfg);
281 print("====================");
282 print(source);
283 eval(source);
284 });
285 });
286 });
287 });
288 });
289 });
290}
291
292run_tests();