Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: tools/gen-inlining-tests.py

Issue 2285743002: [turbofan] Improve inline-exception tests. (Closed)
Patch Set: Rename noopt function. Generate some type feedback for noopt functions. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/mjsunit/compiler/inline-exception-2.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python3 1 #!/usr/bin/env python3
2 2
3 # Copyright 2016 the V8 project authors. All rights reserved. 3 # Copyright 2016 the V8 project authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 7
8 from collections import namedtuple 8 from collections import namedtuple
9 import textwrap 9 import textwrap
10 import sys 10 import sys
11 11
12 SHARD_FILENAME_TEMPLATE = "test/mjsunit/compiler/inline-exception-{shard}.js" 12 SHARD_FILENAME_TEMPLATE = "test/mjsunit/compiler/inline-exception-{shard}.js"
13 # Generates 2 files. Found by trial and error. 13 # Generates 2 files. Found by trial and error.
14 SHARD_SIZE = 94 14 SHARD_SIZE = 97
15 15
16 PREAMBLE = """ 16 PREAMBLE = """
17 17
18 // Copyright 2016 the V8 project authors. All rights reserved. 18 // Copyright 2016 the V8 project authors. All rights reserved.
19 // Use of this source code is governed by a BSD-style license that can be 19 // Use of this source code is governed by a BSD-style license that can be
20 // found in the LICENSE file. 20 // found in the LICENSE file.
21 21
22 // Flags: --allow-natives-syntax --turbo --no-always-opt 22 // Flags: --allow-natives-syntax --turbo --no-always-opt
23 23
24 // This test file was generated by tools/gen-inlining-tests.py . 24 // This test file was generated by tools/gen-inlining-tests.py .
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 counter++; 74 counter++;
75 return 15; 75 return 15;
76 } 76 }
77 77
78 function increaseAndThrow42() { 78 function increaseAndThrow42() {
79 if (deopt) %DeoptimizeFunction(f); 79 if (deopt) %DeoptimizeFunction(f);
80 counter++; 80 counter++;
81 throw 42; 81 throw 42;
82 } 82 }
83 83
84 function increaseAndReturn15_noopt_inner() {
85 if (deopt) %DeoptimizeFunction(f);
86 counter++;
87 return 15;
88 }
89
90 %NeverOptimizeFunction(increaseAndReturn15_noopt_inner);
91
92 function increaseAndThrow42_noopt_inner() {
93 if (deopt) %DeoptimizeFunction(f);
94 counter++;
95 throw 42;
96 }
97
98 %NeverOptimizeFunction(increaseAndThrow42_noopt_inner);
99
100 // Alternative 1
101
84 function returnOrThrow(doReturn) { 102 function returnOrThrow(doReturn) {
85 if (doReturn) { 103 if (doReturn) {
86 return increaseAndReturn15(); 104 return increaseAndReturn15();
87 } else { 105 } else {
88 return increaseAndThrow42(); 106 return increaseAndThrow42();
89 } 107 }
90 } 108 }
91 109
110 // Alternative 2
111
112 function increaseAndReturn15_calls_noopt() {
113 return increaseAndReturn15_noopt_inner();
114 }
115
116 function increaseAndThrow42_calls_noopt() {
117 return increaseAndThrow42_noopt_inner();
118 }
119
120 // Alternative 3.
92 // When passed either {increaseAndReturn15} or {increaseAndThrow42}, it acts 121 // When passed either {increaseAndReturn15} or {increaseAndThrow42}, it acts
93 // as the other one. 122 // as the other one.
94 function invertFunctionCall(f) { 123 function invertFunctionCall(f) {
95 var result; 124 var result;
96 try { 125 try {
97 result = f(); 126 result = f();
98 } catch (ex) { 127 } catch (ex) {
99 return ex - 27; 128 return ex - 27;
100 } 129 }
101 throw result + 27; 130 throw result + 27;
102 } 131 }
103 132
133 // Alternative 4: constructor
104 function increaseAndStore15Constructor() { 134 function increaseAndStore15Constructor() {
105 if (deopt) %DeoptimizeFunction(f); 135 if (deopt) %DeoptimizeFunction(f);
106 ++counter; 136 ++counter;
107 this.x = 15; 137 this.x = 15;
108 } 138 }
109 139
110 function increaseAndThrow42Constructor() { 140 function increaseAndThrow42Constructor() {
111 if (deopt) %DeoptimizeFunction(f); 141 if (deopt) %DeoptimizeFunction(f);
112 ++counter; 142 ++counter;
113 this.x = 42; 143 this.x = 42;
114 throw this.x; 144 throw this.x;
115 } 145 }
116 146
147 // Alternative 5: property
117 var magic = {}; 148 var magic = {};
118 Object.defineProperty(magic, 'prop', { 149 Object.defineProperty(magic, 'prop', {
119 get: function () { 150 get: function () {
120 if (deopt) %DeoptimizeFunction(f); 151 if (deopt) %DeoptimizeFunction(f);
121 return 15 + 0 * ++counter; 152 return 15 + 0 * ++counter;
122 }, 153 },
123 154
124 set: function(x) { 155 set: function(x) {
125 // argument should be 37 156 // argument should be 37
126 if (deopt) %DeoptimizeFunction(f); 157 if (deopt) %DeoptimizeFunction(f);
127 counter -= 36 - x; // increments counter 158 counter -= 36 - x; // increments counter
128 throw 42; 159 throw 42;
129 } 160 }
130 }) 161 })
131 162
132 // Generate type feedback. 163 // Generate type feedback.
133 164
165 assertEquals(15, increaseAndReturn15_calls_noopt());
166 assertThrowsEquals(function() { return increaseAndThrow42_noopt_inner() }, 42);
167
134 assertEquals(15, (new increaseAndStore15Constructor()).x); 168 assertEquals(15, (new increaseAndStore15Constructor()).x);
135 assertThrowsEquals(function() { 169 assertThrowsEquals(function() {
136 return (new increaseAndThrow42Constructor()).x; 170 return (new increaseAndThrow42Constructor()).x;
137 }, 171 },
138 42); 172 42);
139 173
140 function runThisShard() { 174 function runThisShard() {
141 175
142 """.strip() 176 """.strip()
143 177
144 def booltuples(n): 178 def booltuples(n):
145 """booltuples(2) yields 4 tuples: (False, False), (False, True), 179 """booltuples(2) yields 4 tuples: (False, False), (False, True),
146 (True, False), (True, True).""" 180 (True, False), (True, True)."""
147 181
148 assert isinstance(n, int) 182 assert isinstance(n, int)
149 if n <= 0: 183 if n <= 0:
150 yield () 184 yield ()
151 else: 185 else:
152 for initial in booltuples(n-1): 186 for initial in booltuples(n-1):
153 yield initial + (False,) 187 yield initial + (False,)
154 yield initial + (True,) 188 yield initial + (True,)
155 189
156 FLAGLETTERS="4321trflcrltfrtld"
157
158 def fnname(flags): 190 def fnname(flags):
159 assert len(FLAGLETTERS) == len(flags) 191 assert len(FLAGLETTERS) == len(flags)
160 192
161 return "f_" + ''.join( 193 return "f_" + ''.join(
162 FLAGLETTERS[i] if b else '_' 194 FLAGLETTERS[i] if b else '_'
163 for (i, b) in enumerate(flags)) 195 for (i, b) in enumerate(flags))
164 196
165 NUM_TESTS_PRINTED = 0 197 NUM_TESTS_PRINTED = 0
166 NUM_TESTS_IN_SHARD = 0 198 NUM_TESTS_IN_SHARD = 0
167 199
168 def printtest(flags): 200 def printtest(flags):
169 """Print a test case. Takes a couple of boolean flags, on which the 201 """Print a test case. Takes a couple of boolean flags, on which the
170 printed Javascript code depends.""" 202 printed Javascript code depends."""
171 203
172 assert all(isinstance(flag, bool) for flag in flags) 204 assert all(isinstance(flag, bool) for flag in flags)
173 205
174 # The alternative flags are in reverse order so that if we take all possible 206 # The alternative flags are in reverse order so that if we take all possible
175 # tuples, ordered lexicographically from false to true, we get first the 207 # tuples, ordered lexicographically from false to true, we get first the
176 # default, then alternative 1, then 2, etc. 208 # default, then alternative 1, then 2, etc.
177 ( 209 (
178 alternativeFn4, # use alternative #4 for returning/throwing. 210 alternativeFn5, # use alternative #5 for returning/throwing:
179 alternativeFn3, # use alternative #3 for returning/throwing. 211 # return/throw using property
180 alternativeFn2, # use alternative #2 for returning/throwing. 212 alternativeFn4, # use alternative #4 for returning/throwing:
181 alternativeFn1, # use alternative #1 for returning/throwing. 213 # return/throw using constructor
214 alternativeFn3, # use alternative #3 for returning/throwing:
215 # return/throw indirectly, based on function argument
216 alternativeFn2, # use alternative #2 for returning/throwing:
217 # return/throw indirectly in unoptimized code,
218 # no branching
219 alternativeFn1, # use alternative #1 for returning/throwing:
220 # return/throw indirectly, based on boolean arg
182 tryThrows, # in try block, call throwing function 221 tryThrows, # in try block, call throwing function
183 tryReturns, # in try block, call returning function 222 tryReturns, # in try block, call returning function
184 tryFirstReturns, # in try block, returning goes before throwing 223 tryFirstReturns, # in try block, returning goes before throwing
185 tryResultToLocal, # in try block, result goes to local variable 224 tryResultToLocal, # in try block, result goes to local variable
186 doCatch, # include catch block 225 doCatch, # include catch block
187 catchReturns, # in catch block, return 226 catchReturns, # in catch block, return
188 catchWithLocal, # in catch block, modify or return the local variable 227 catchWithLocal, # in catch block, modify or return the local variable
189 catchThrows, # in catch block, throw 228 catchThrows, # in catch block, throw
190 doFinally, # include finally block 229 doFinally, # include finally block
191 finallyReturns, # in finally block, return local variable 230 finallyReturns, # in finally block, return local variable
192 finallyThrows, # in finally block, throw 231 finallyThrows, # in finally block, throw
193 endReturnLocal, # at very end, return variable local 232 endReturnLocal, # at very end, return variable local
194 deopt, # deopt inside inlined function 233 deopt, # deopt inside inlined function
195 ) = flags 234 ) = flags
196 235
197 # BASIC RULES 236 # BASIC RULES
198 237
199 # Only one alternative can be applied at any time. 238 # Only one alternative can be applied at any time.
200 if alternativeFn1 + alternativeFn2 + alternativeFn3 + alternativeFn4 > 1: 239 if (alternativeFn1 + alternativeFn2 + alternativeFn3 + alternativeFn4
240 + alternativeFn5 > 1):
201 return 241 return
202 242
203 # In try, return or throw, or both. 243 # In try, return or throw, or both.
204 if not (tryReturns or tryThrows): return 244 if not (tryReturns or tryThrows): return
205 245
206 # Either doCatch or doFinally. 246 # Either doCatch or doFinally.
207 if not doCatch and not doFinally: return 247 if not doCatch and not doFinally: return
208 248
209 # Catch flags only make sense when catching 249 # Catch flags only make sense when catching
210 if not doCatch and (catchReturns or catchWithLocal or catchThrows): 250 if not doCatch and (catchReturns or catchWithLocal or catchThrows):
(...skipping 10 matching lines...) Expand all
221 # From the try and finally block, we can return or throw, but not both. 261 # From the try and finally block, we can return or throw, but not both.
222 if catchReturns and catchThrows: return 262 if catchReturns and catchThrows: return
223 if finallyReturns and finallyThrows: return 263 if finallyReturns and finallyThrows: return
224 264
225 # If at the end we return the local, we need to have touched it. 265 # If at the end we return the local, we need to have touched it.
226 if endReturnLocal and not (tryResultToLocal or catchWithLocal): return 266 if endReturnLocal and not (tryResultToLocal or catchWithLocal): return
227 267
228 # PRUNING 268 # PRUNING
229 269
230 anyAlternative = any([alternativeFn1, alternativeFn2, alternativeFn3, 270 anyAlternative = any([alternativeFn1, alternativeFn2, alternativeFn3,
231 alternativeFn4]) 271 alternativeFn4, alternativeFn5])
232 rareAlternative = any([alternativeFn1, alternativeFn3, alternativeFn4]) 272 specificAlternative = any([alternativeFn2, alternativeFn3])
273 rareAlternative = not specificAlternative
233 274
234 # If try returns and throws, then don't catchWithLocal, endReturnLocal, or 275 # If try returns and throws, then don't catchWithLocal, endReturnLocal, or
235 # deopt, or do any alternative. 276 # deopt, or do any alternative.
236 if (tryReturns and tryThrows and 277 if (tryReturns and tryThrows and
237 (catchWithLocal or endReturnLocal or deopt or anyAlternative)): 278 (catchWithLocal or endReturnLocal or deopt or anyAlternative)):
238 return 279 return
239 # We don't do any alternative if we do a finally. 280 # We don't do any alternative if we do a finally.
240 if doFinally and anyAlternative: return 281 if doFinally and anyAlternative: return
241 # We only use the local variable if we do alternative #2. 282 # We only use the local variable if we do alternative #2 or #3.
242 if ((tryResultToLocal or catchWithLocal or endReturnLocal) and 283 if ((tryResultToLocal or catchWithLocal or endReturnLocal) and
243 not alternativeFn2): 284 not specificAlternative):
244 return 285 return
245 # We don't need to test deopting into a finally. 286 # We don't need to test deopting into a finally.
246 if doFinally and deopt: return 287 if doFinally and deopt: return
247 288
289 # We're only interested in alternative #2 if we have endReturnLocal, no
290 # catchReturns, and no catchThrows, and deopt.
291 if (alternativeFn2 and
292 (not endReturnLocal or catchReturns or catchThrows or not deopt)):
293 return
248 294
249 295
250 # Flag check succeeded. 296 # Flag check succeeded.
251 297
252 trueFlagNames = [name for (name, value) in flags._asdict().items() if value] 298 trueFlagNames = [name for (name, value) in flags._asdict().items() if value]
253 flagsMsgLine = " // Variant flags: [{}]".format(', '.join(trueFlagNames)) 299 flagsMsgLine = " // Variant flags: [{}]".format(', '.join(trueFlagNames))
254 write(textwrap.fill(flagsMsgLine, subsequent_indent=' // ')) 300 write(textwrap.fill(flagsMsgLine, subsequent_indent=' // '))
255 write("") 301 write("")
256 302
257 if not anyAlternative: 303 if not anyAlternative:
258 fragments = { 304 fragments = {
259 'increaseAndReturn15': 'increaseAndReturn15()', 305 'increaseAndReturn15': 'increaseAndReturn15()',
260 'increaseAndThrow42': 'increaseAndThrow42()', 306 'increaseAndThrow42': 'increaseAndThrow42()',
261 } 307 }
262 elif alternativeFn1: 308 elif alternativeFn1:
263 fragments = { 309 fragments = {
264 'increaseAndReturn15': 'returnOrThrow(true)', 310 'increaseAndReturn15': 'returnOrThrow(true)',
265 'increaseAndThrow42': 'returnOrThrow(false)', 311 'increaseAndThrow42': 'returnOrThrow(false)',
266 } 312 }
267 elif alternativeFn2: 313 elif alternativeFn2:
268 fragments = { 314 fragments = {
315 'increaseAndReturn15': 'increaseAndReturn15_calls_noopt()',
316 'increaseAndThrow42': 'increaseAndThrow42_calls_noopt()',
317 }
318 elif alternativeFn3:
319 fragments = {
269 'increaseAndReturn15': 'invertFunctionCall(increaseAndThrow42)', 320 'increaseAndReturn15': 'invertFunctionCall(increaseAndThrow42)',
270 'increaseAndThrow42': 'invertFunctionCall(increaseAndReturn15)', 321 'increaseAndThrow42': 'invertFunctionCall(increaseAndReturn15)',
271 } 322 }
272 elif alternativeFn3: 323 elif alternativeFn4:
273 fragments = { 324 fragments = {
274 'increaseAndReturn15': '(new increaseAndStore15Constructor()).x', 325 'increaseAndReturn15': '(new increaseAndStore15Constructor()).x',
275 'increaseAndThrow42': '(new increaseAndThrow42Constructor()).x', 326 'increaseAndThrow42': '(new increaseAndThrow42Constructor()).x',
276 } 327 }
277 else: 328 else:
278 assert alternativeFn4 329 assert alternativeFn5
279 fragments = { 330 fragments = {
280 'increaseAndReturn15': 'magic.prop /* returns 15 */', 331 'increaseAndReturn15': 'magic.prop /* returns 15 */',
281 'increaseAndThrow42': '(magic.prop = 37 /* throws 42 */)', 332 'increaseAndThrow42': '(magic.prop = 37 /* throws 42 */)',
282 } 333 }
283 334
284 # As we print code, we also maintain what the result should be. Variable 335 # As we print code, we also maintain what the result should be. Variable
285 # {result} can be one of three things: 336 # {result} can be one of three things:
286 # 337 #
287 # - None, indicating returning JS null 338 # - None, indicating returning JS null
288 # - ("return", n) with n an integer 339 # - ("return", n) with n an integer
289 # - ("throw", n), with n an integer 340 # - ("throw", n), with n an integer
290 341
291 result = None 342 result = None
292 # We also maintain what the counter should be at the end. 343 # We also maintain what the counter should be at the end.
293 # The counter is reset just before f is called. 344 # The counter is reset just before f is called.
294 counter = 0 345 counter = 0
295 346
296 write( " f = function {} () {{".format(fnname(flags))) 347 write( " f = function {} () {{".format(fnname(flags)))
297 write( " var local = 3;") 348 write( " var local = 888;")
298 write( " deopt = {};".format("true" if deopt else "false")) 349 write( " deopt = {};".format("true" if deopt else "false"))
299 local = 3 350 local = 888
300 write( " try {") 351 write( " try {")
301 write( " counter++;") 352 write( " counter++;")
302 counter += 1 353 counter += 1
303 resultTo = "local +=" if tryResultToLocal else "return" 354 resultTo = "local +=" if tryResultToLocal else "return"
304 if tryReturns and not (tryThrows and not tryFirstReturns): 355 if tryReturns and not (tryThrows and not tryFirstReturns):
305 write( " {} {increaseAndReturn15};".format(resultTo, **fragments)) 356 write( " {} 4 + {increaseAndReturn15};".format(resultTo, **fragments))
306 if result == None: 357 if result == None:
307 counter += 1 358 counter += 1
308 if tryResultToLocal: 359 if tryResultToLocal:
309 local += 15 360 local += 19
310 else: 361 else:
311 result = ("return", 15) 362 result = ("return", 19)
312 if tryThrows: 363 if tryThrows:
313 write( " {} {increaseAndThrow42};".format(resultTo, **fragments)) 364 write( " {} 4 + {increaseAndThrow42};".format(resultTo, **fragments))
314 if result == None: 365 if result == None:
315 counter += 1 366 counter += 1
316 result = ("throw", 42) 367 result = ("throw", 42)
317 if tryReturns and tryThrows and not tryFirstReturns: 368 if tryReturns and tryThrows and not tryFirstReturns:
318 write( " {} {increaseAndReturn15};".format(resultTo, **fragments)) 369 write( " {} 4 + {increaseAndReturn15};".format(resultTo, **fragments))
319 if result == None: 370 if result == None:
320 counter += 1 371 counter += 1
321 if tryResultToLocal: 372 if tryResultToLocal:
322 local += 15 373 local += 19
323 else: 374 else:
324 result = ("return", 15) 375 result = ("return", 19)
325 write( " counter++;") 376 write( " counter++;")
326 if result == None: 377 if result == None:
327 counter += 1 378 counter += 1
328 379
329 if doCatch: 380 if doCatch:
330 write( " } catch (ex) {") 381 write( " } catch (ex) {")
331 write( " counter++;") 382 write( " counter++;")
332 if isinstance(result, tuple) and result[0] == 'throw': 383 if isinstance(result, tuple) and result[0] == 'throw':
333 counter += 1 384 counter += 1
334 if catchThrows: 385 if catchThrows:
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 491
441 def write_shard_footer(): 492 def write_shard_footer():
442 write("}") 493 write("}")
443 write("%NeverOptimizeFunction(runThisShard);") 494 write("%NeverOptimizeFunction(runThisShard);")
444 write("") 495 write("")
445 write("// {} tests in this shard.".format(NUM_TESTS_IN_SHARD)) 496 write("// {} tests in this shard.".format(NUM_TESTS_IN_SHARD))
446 write("// {} tests up to here.".format(NUM_TESTS_PRINTED)) 497 write("// {} tests up to here.".format(NUM_TESTS_PRINTED))
447 write("") 498 write("")
448 write("runThisShard();") 499 write("runThisShard();")
449 500
501 FLAGLETTERS="54321trflcrltfrtld"
450 502
451 flagtuple = namedtuple('flagtuple', ( 503 flagtuple = namedtuple('flagtuple', (
504 "alternativeFn5",
452 "alternativeFn4", 505 "alternativeFn4",
453 "alternativeFn3", 506 "alternativeFn3",
454 "alternativeFn2", 507 "alternativeFn2",
455 "alternativeFn1", 508 "alternativeFn1",
456 "tryThrows", 509 "tryThrows",
457 "tryReturns", 510 "tryReturns",
458 "tryFirstReturns", 511 "tryFirstReturns",
459 "tryResultToLocal", 512 "tryResultToLocal",
460 "doCatch", 513 "doCatch",
461 "catchReturns", 514 "catchReturns",
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 print("") 554 print("")
502 sys.exit(1) 555 sys.exit(1)
503 556
504 rotateshard() 557 rotateshard()
505 558
506 for flags in allFlagCombinations: 559 for flags in allFlagCombinations:
507 printtest(flags) 560 printtest(flags)
508 rotateshard() 561 rotateshard()
509 562
510 finishshard() 563 finishshard()
564
565 if MODE == 'shard':
566 print("Total: {} tests.".format(NUM_TESTS_PRINTED))
OLDNEW
« no previous file with comments | « test/mjsunit/compiler/inline-exception-2.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698