OLD | NEW |
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 | 5 // Flags: --allow-natives-syntax --harmony-tailcalls |
6 // TODO(v8:4698), TODO(ishell): support these cases. | |
7 // Flags: --turbo --nostress-opt | |
8 | 6 |
9 | 7 |
10 Error.prepareStackTrace = (error,stack) => { | 8 Error.prepareStackTrace = (error,stack) => { |
11 error.strace = stack; | 9 error.strace = stack; |
12 return error.message + "\n at " + stack.join("\n at "); | 10 return error.message + "\n at " + stack.join("\n at "); |
13 } | 11 } |
14 | 12 |
15 | 13 |
16 function checkStackTrace(expected) { | 14 function checkStackTrace(expected) { |
17 var e = new Error(); | 15 var e = new Error(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 var lines = [ | 50 var lines = [ |
53 ` assertEquals_(${expected_name}.length, arguments.length);`, | 51 ` assertEquals_(${expected_name}.length, arguments.length);`, |
54 ` for (var i = 0; i < ${expected_name}.length; i++) {`, | 52 ` for (var i = 0; i < ${expected_name}.length; i++) {`, |
55 ` assertEquals_(${expected_name}[i], arguments[i]);`, | 53 ` assertEquals_(${expected_name}[i], arguments[i]);`, |
56 ` }`, | 54 ` }`, |
57 ]; | 55 ]; |
58 return lines.join("\n"); | 56 return lines.join("\n"); |
59 } | 57 } |
60 var check_arguments = check_arguments_template("expected_args"); | 58 var check_arguments = check_arguments_template("expected_args"); |
61 | 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 |
62 var f_cfg_sloppy = { | 73 var f_cfg_sloppy = { |
63 func_name: 'f', | 74 func_name: 'f', |
64 source_template: function(cfg) { | 75 source_template: function(cfg) { |
65 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver | 76 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
66 : "global"; | 77 : "global"; |
67 var do_checks = [ | 78 var do_checks = [ |
68 ` assertEquals_(${receiver}, this);`, | 79 ` assertEquals_(${receiver}, this);`, |
69 ` assertEquals_(undefined, new.target);`, | 80 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.tar
get);`, |
70 check_arguments, | 81 check_arguments, |
71 ` checkStackTrace_([f, test]);`, | 82 ` checkStackTrace_([f, test]);`, |
72 ].join("\n"); | 83 ].join("\n"); |
73 | 84 |
74 var lines = [ | 85 var lines = [ |
75 `function f(a) {`, | 86 `function f(a) {`, |
76 ` ${inlinable_comment(cfg.f_inlinable)}`, | 87 ` ${inlinable_comment(cfg.f_inlinable)}`, |
| 88 ` counter++;`, |
77 ` var expected_args = [${cfg.f_args}];`, | 89 ` var expected_args = [${cfg.f_args}];`, |
78 do_checks, | 90 do_checks, |
79 ` %DeoptimizeNow();`, | 91 deopt_template(cfg.deopt_mode), |
80 do_checks, | 92 do_checks, |
81 ` return 42;`, | 93 ` return 42;`, |
82 `}`, | 94 `}`, |
83 ]; | 95 ]; |
84 return lines.join("\n"); | 96 return lines.join("\n"); |
85 }, | 97 }, |
86 }; | 98 }; |
87 | 99 |
88 var f_cfg_strict = { | 100 var f_cfg_strict = { |
89 func_name: 'f', | 101 func_name: 'f', |
90 source_template: function(cfg) { | 102 source_template: function(cfg) { |
91 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver | 103 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
92 : "undefined"; | 104 : "undefined"; |
93 var do_checks = [ | 105 var do_checks = [ |
94 ` assertEquals_(${receiver}, this);`, | 106 ` assertEquals_(${receiver}, this);`, |
95 ` assertEquals_(undefined, new.target);`, | 107 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.tar
get);`, |
96 check_arguments, | 108 check_arguments, |
97 ` checkStackTrace_([f, test]);`, | 109 ` checkStackTrace_([f, test]);`, |
98 ].join("\n"); | 110 ].join("\n"); |
99 | 111 |
100 var lines = [ | 112 var lines = [ |
101 `function f(a) {`, | 113 `function f(a) {`, |
102 ` "use strict";`, | 114 ` "use strict";`, |
103 ` ${inlinable_comment(cfg.f_inlinable)}`, | 115 ` ${inlinable_comment(cfg.f_inlinable)}`, |
| 116 ` counter++;`, |
104 ` var expected_args = [${cfg.f_args}];`, | 117 ` var expected_args = [${cfg.f_args}];`, |
105 do_checks, | 118 do_checks, |
106 ` %DeoptimizeNow();`, | 119 deopt_template(cfg.deopt_mode), |
107 do_checks, | 120 do_checks, |
108 ` return 42;`, | 121 ` return 42;`, |
109 `}`, | 122 `}`, |
110 ]; | 123 ]; |
111 return lines.join("\n"); | 124 return lines.join("\n"); |
112 }, | 125 }, |
113 }; | 126 }; |
114 | 127 |
115 var f_cfg_possibly_eval = { | 128 var f_cfg_possibly_eval = { |
116 func_name: 'eval', | 129 func_name: 'eval', |
117 source_template: function(cfg) { | 130 source_template: function(cfg) { |
118 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver | 131 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
119 : "global"; | 132 : "global"; |
120 var do_checks = [ | 133 var do_checks = [ |
121 ` assertEquals_(${receiver}, this);`, | 134 ` assertEquals_(${receiver}, this);`, |
122 ` assertEquals_(undefined, new.target);`, | 135 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.tar
get);`, |
123 check_arguments, | 136 check_arguments, |
124 ` checkStackTrace_([f, test]);`, | 137 ` checkStackTrace_([f, test]);`, |
125 ].join("\n"); | 138 ].join("\n"); |
126 | 139 |
127 var lines = [ | 140 var lines = [ |
128 `function f(a) {`, | 141 `function f(a) {`, |
129 ` ${inlinable_comment(cfg.f_inlinable)}`, | 142 ` ${inlinable_comment(cfg.f_inlinable)}`, |
| 143 ` counter++;`, |
130 ` var expected_args = [${cfg.f_args}];`, | 144 ` var expected_args = [${cfg.f_args}];`, |
131 do_checks, | 145 do_checks, |
132 ` %DeoptimizeNow();`, | 146 deopt_template(cfg.deopt_mode), |
133 do_checks, | 147 do_checks, |
134 ` return 42;`, | 148 ` return 42;`, |
135 `}`, | 149 `}`, |
136 `var eval = f;`, | 150 `var eval = f;`, |
137 ]; | 151 ]; |
138 return lines.join("\n"); | 152 return lines.join("\n"); |
139 }, | 153 }, |
140 }; | 154 }; |
141 | 155 |
142 var f_cfg_bound = { | 156 var f_cfg_bound = { |
143 func_name: 'bound', | 157 func_name: 'bound', |
144 source_template: function(cfg) { | 158 source_template: function(cfg) { |
145 var do_checks = [ | 159 var do_checks = [ |
146 ` assertEquals_(receiver, this);`, | 160 ` assertEquals_(receiver, this);`, |
147 ` assertEquals_(undefined, new.target);`, | 161 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.tar
get);`, |
148 check_arguments, | 162 check_arguments, |
149 ` checkStackTrace_([f, test]);`, | 163 ` checkStackTrace_([f, test]);`, |
150 ].join("\n"); | 164 ].join("\n"); |
151 | 165 |
152 var lines = [ | 166 var lines = [ |
153 `function f(a) {`, | 167 `function f(a) {`, |
154 ` "use strict";`, | 168 ` "use strict";`, |
155 ` ${inlinable_comment(cfg.f_inlinable)}`, | 169 ` ${inlinable_comment(cfg.f_inlinable)}`, |
| 170 ` counter++;`, |
156 ` var expected_args = [${cfg.f_args}];`, | 171 ` var expected_args = [${cfg.f_args}];`, |
157 do_checks, | 172 do_checks, |
158 ` %DeoptimizeNow();`, | 173 deopt_template(cfg.deopt_mode), |
159 do_checks, | 174 do_checks, |
160 ` return 42;`, | 175 ` return 42;`, |
161 `}`, | 176 `}`, |
162 `var receiver = {a: 153};`, | 177 `var receiver = {a: 153};`, |
163 `var bound = f.bind(receiver);`, | 178 `var bound = f.bind(receiver);`, |
164 ]; | 179 ]; |
165 return lines.join("\n"); | 180 return lines.join("\n"); |
166 }, | 181 }, |
167 }; | 182 }; |
168 | 183 |
169 var f_cfg_proxy = { | 184 var f_cfg_proxy = { |
170 func_name: 'p', | 185 func_name: 'p', |
171 source_template: function(cfg) { | 186 source_template: function(cfg) { |
172 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver | 187 var receiver = cfg.f_receiver != undefined ? cfg.f_receiver |
173 : "global"; | 188 : "global"; |
174 var do_checks = [ | 189 var do_checks = [ |
175 ` assertEquals_(${receiver}, this);`, | 190 ` assertEquals_(${receiver}, this);`, |
176 ` assertEquals_(undefined, new.target);`, | 191 ` ${!cfg.check_new_target ? "// " : ""}assertEquals_(undefined, new.tar
get);`, |
177 check_arguments, | 192 check_arguments, |
178 ` checkStackTrace_([f, test]);`, | 193 ` checkStackTrace_([f, test]);`, |
179 ].join("\n"); | 194 ].join("\n"); |
180 | 195 |
181 var lines = [ | 196 var lines = [ |
182 `function f(a) {`, | 197 `function f(a) {`, |
183 ` ${inlinable_comment(cfg.f_inlinable)}`, | 198 ` ${inlinable_comment(cfg.f_inlinable)}`, |
| 199 ` counter++;`, |
184 ` var expected_args = [${cfg.f_args}];`, | 200 ` var expected_args = [${cfg.f_args}];`, |
185 do_checks, | 201 do_checks, |
186 ` %DeoptimizeNow();`, | 202 deopt_template(cfg.deopt_mode), |
187 do_checks, | 203 do_checks, |
188 ` return 42;`, | 204 ` return 42;`, |
189 `}`, | 205 `}`, |
190 `var p = new Proxy(f, {});`, | 206 `var p = new Proxy(f, {});`, |
191 ]; | 207 ]; |
192 return lines.join("\n"); | 208 return lines.join("\n"); |
193 }, | 209 }, |
194 }; | 210 }; |
195 | 211 |
196 var g_cfg_normal = { | 212 var g_cfg_normal = { |
197 receiver: undefined, | 213 receiver: undefined, |
198 source_template: function(cfg) { | 214 source_template: function(cfg) { |
199 var lines = [ | 215 var lines = [ |
200 `function g(a) {`, | 216 `function g(a) {`, |
201 ` "use strict";`, | 217 ` "use strict";`, |
202 ` ${inlinable_comment(cfg.g_inlinable)}`, | 218 ` ${inlinable_comment(cfg.g_inlinable)}`, |
203 ` var expected_args = [${cfg.g_args}];`, | 219 ` var expected_args = [${cfg.g_args}];`, |
204 check_arguments, | 220 check_arguments, |
205 ` return ${cfg.f_name}(${cfg.f_args});`, | 221 ` return ${cfg.f_name}(${cfg.f_args});`, |
206 `}`, | 222 `}`, |
207 ]; | 223 ]; |
208 return lines.join("\n"); | 224 return lines.join("\n"); |
209 }, | 225 }, |
210 }; | 226 }; |
211 | 227 |
212 | 228 |
| 229 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 |
213 var g_cfg_function_apply = { | 246 var g_cfg_function_apply = { |
214 receiver: "the_receiver", | 247 receiver: "the_receiver", |
215 source_template: function(cfg) { | 248 source_template: function(cfg) { |
216 var lines = [ | 249 var lines = [ |
217 `function g(a) {`, | 250 `function g(a) {`, |
218 ` "use strict";`, | 251 ` "use strict";`, |
219 ` ${inlinable_comment(cfg.g_inlinable)}`, | 252 ` ${inlinable_comment(cfg.g_inlinable)}`, |
220 ` var expected_args = [${cfg.g_args}];`, | 253 ` var expected_args = [${cfg.g_args}];`, |
221 check_arguments, | 254 check_arguments, |
222 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`, | 255 ` return ${cfg.f_name}.apply(the_receiver, [${cfg.f_args}]);`, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 f_source = ident_source(f_source, 2); | 308 f_source = ident_source(f_source, 2); |
276 | 309 |
277 var lines = [ | 310 var lines = [ |
278 `(function() {`, | 311 `(function() {`, |
279 ` // Avoid bailing out because of "Reference to a variable which requires
dynamic lookup".`, | 312 ` // Avoid bailing out because of "Reference to a variable which requires
dynamic lookup".`, |
280 ` var assertEquals_ = assertEquals;`, | 313 ` var assertEquals_ = assertEquals;`, |
281 ` var checkStackTrace_ = checkStackTrace;`, | 314 ` var checkStackTrace_ = checkStackTrace;`, |
282 ` var undefined = void 0;`, | 315 ` var undefined = void 0;`, |
283 ` var global = Function('return this')();`, | 316 ` var global = Function('return this')();`, |
284 ` var the_receiver = {receiver: 1};`, | 317 ` var the_receiver = {receiver: 1};`, |
| 318 ` var counter = 0;`, |
285 ``, | 319 ``, |
286 ` // Don't inline helper functions`, | 320 ` // Don't inline helper functions`, |
287 ` %NeverOptimizeFunction(assertEquals);`, | 321 ` %NeverOptimizeFunction(assertEquals);`, |
288 ` %NeverOptimizeFunction(checkStackTrace);`, | 322 ` %NeverOptimizeFunction(checkStackTrace);`, |
289 ``, | 323 ``, |
290 f_source, | 324 f_source, |
291 g_source, | 325 g_source, |
292 ` function test() {`, | 326 ` function test() {`, |
293 ` "use strict";`, | 327 ` "use strict";`, |
294 ` assertEquals_(42, g(${cfg.g_args}));`, | 328 ` assertEquals_(42, g(${cfg.g_args}));`, |
295 ` }`, | 329 ` }`, |
296 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : ""};`, | |
297 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : ""};`, | |
298 ` ${"test();".repeat(cfg.test_warmup_count)}`, | 330 ` ${"test();".repeat(cfg.test_warmup_count)}`, |
| 331 ` ${cfg.f_inlinable ? "%SetForceInlineFlag(f)" : "%OptimizeFunctionOnNext
Call(f)"};`, |
| 332 ` ${cfg.g_inlinable ? "%SetForceInlineFlag(g)" : "%OptimizeFunctionOnNext
Call(g)"};`, |
299 ` %OptimizeFunctionOnNextCall(test);`, | 333 ` %OptimizeFunctionOnNextCall(test);`, |
300 ` %OptimizeFunctionOnNextCall(f);`, | |
301 ` %OptimizeFunctionOnNextCall(g);`, | |
302 ` test();`, | 334 ` test();`, |
| 335 ` assertEquals(${1 + cfg.test_warmup_count}, counter);`, |
303 `})();`, | 336 `})();`, |
304 ``, | 337 ``, |
305 ]; | 338 ]; |
306 var source = lines.join("\n"); | 339 var source = lines.join("\n"); |
307 return source; | 340 return source; |
308 } | 341 } |
309 | 342 |
310 var f_args_variants = ["", "1", "1, 2"]; | 343 var f_args_variants = ["", "1", "1, 2"]; |
311 var g_args_variants = ["", "10", "10, 20"]; | 344 var g_args_variants = ["", "10", "10, 20"]; |
312 var f_inlinable_variants = [true, false]; | 345 var f_inlinable_variants = [true, false]; |
313 var g_inlinable_variants = [true, false]; | 346 var g_inlinable_variants = [true, false]; |
| 347 // 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"]; |
314 var f_variants = [ | 350 var f_variants = [ |
315 f_cfg_sloppy, | 351 f_cfg_sloppy, |
316 f_cfg_strict, | 352 f_cfg_strict, |
317 f_cfg_bound, | 353 f_cfg_bound, |
318 f_cfg_proxy, | 354 f_cfg_proxy, |
319 f_cfg_possibly_eval, | 355 f_cfg_possibly_eval, |
320 ]; | 356 ]; |
321 var g_variants = [ | 357 var g_variants = [ |
322 g_cfg_normal, | 358 g_cfg_normal, |
323 g_cfg_function_call, | 359 g_cfg_reflect_apply, |
324 g_cfg_function_apply, | 360 g_cfg_function_apply, |
325 g_cfg_function_apply_arguments_object, | 361 g_cfg_function_apply_arguments_object, |
| 362 g_cfg_function_call, |
326 ]; | 363 ]; |
327 var test_warmup_counts = [0, 1, 2]; | 364 var test_warmup_counts = [0, 1, 2]; |
328 | 365 |
329 var iter = 0; | 366 var iter = 0; |
| 367 var tests_executed = 0; |
330 if (shard !== undefined) { | 368 if (shard !== undefined) { |
331 print("Running shard #" + shard); | 369 print("Running shard #" + shard); |
332 } | 370 } |
333 f_variants.forEach((f_cfg) => { | 371 f_variants.forEach((f_cfg) => { |
334 g_variants.forEach((g_cfg) => { | 372 check_new_target_variants.forEach((check_new_target) => { |
335 f_args_variants.forEach((f_args) => { | 373 deopt_mode_variants.forEach((deopt_mode) => { |
336 g_args_variants.forEach((g_args) => { | 374 g_variants.forEach((g_cfg) => { |
337 f_inlinable_variants.forEach((f_inlinable) => { | 375 f_args_variants.forEach((f_args) => { |
338 g_inlinable_variants.forEach((g_inlinable) => { | 376 g_args_variants.forEach((g_args) => { |
339 test_warmup_counts.forEach((test_warmup_count) => { | 377 f_inlinable_variants.forEach((f_inlinable) => { |
340 if (shard !== undefined && (iter++) % SHARDS_COUNT != shard) { | 378 g_inlinable_variants.forEach((g_inlinable) => { |
341 print("skipping..."); | 379 test_warmup_counts.forEach((test_warmup_count) => { |
342 return; | 380 if (shard !== undefined && (iter++) % SHARDS_COUNT != shard)
{ |
343 } | 381 print("skipping..."); |
344 var cfg = { | 382 return; |
345 f_source_template: f_cfg.source_template, | 383 } |
346 f_inlinable, | 384 tests_executed++; |
347 f_args, | 385 var cfg = { |
348 f_name: f_cfg.func_name, | 386 f_source_template: f_cfg.source_template, |
349 f_receiver: g_cfg.receiver, | 387 f_inlinable, |
350 g_source_template: g_cfg.source_template, | 388 f_args, |
351 g_inlinable, | 389 f_name: f_cfg.func_name, |
352 g_args, | 390 f_receiver: g_cfg.receiver, |
353 test_warmup_count, | 391 g_source_template: g_cfg.source_template, |
354 }; | 392 g_inlinable, |
355 var source = test_template(cfg); | 393 g_args, |
356 print("===================="); | 394 test_warmup_count, |
357 print(source); | 395 check_new_target, |
358 eval(source); | 396 deopt_mode, |
| 397 }; |
| 398 var source = test_template(cfg); |
| 399 print("===================="); |
| 400 print(source); |
| 401 eval(source); |
| 402 }); |
| 403 }); |
359 }); | 404 }); |
360 }); | 405 }); |
361 }); | 406 }); |
362 }); | 407 }); |
363 }); | 408 }); |
364 }); | 409 }); |
365 }); | 410 }); |
| 411 print("Number of tests executed: " + tests_executed); |
366 } | 412 } |
367 | 413 |
368 // Uncomment to run all the tests at once or use shard runners. | 414 // Uncomment to run all the tests at once or use shard runners. |
369 //run_tests(); | 415 //run_tests(); |
OLD | NEW |