5252# utilities
5353
5454
55+ def in_binaryen (* args ):
56+ return os .path .join (options .binaryen_root , * args )
57+
58+
5559def in_bin (tool ):
5660 return os .path .join (options .binaryen_root , 'bin' , tool )
5761
@@ -139,8 +143,17 @@ def run_vm(cmd):
139143 raise
140144
141145
142- def run_bynterp (wasm ):
143- return fix_output (run_vm ([in_bin ('wasm-opt' ), wasm , '--fuzz-exec-before' ] + FEATURE_OPTS ))
146+ def run_bynterp (wasm , args ):
147+ # increase the interpreter stack depth, to test more things
148+ os .environ ['BINARYEN_MAX_INTERPRETER_DEPTH' ] = '1000'
149+ try :
150+ return run_vm ([in_bin ('wasm-opt' ), wasm ] + FEATURE_OPTS + args )
151+ finally :
152+ del os .environ ['BINARYEN_MAX_INTERPRETER_DEPTH' ]
153+
154+
155+ def run_d8 (wasm ):
156+ return run_vm (['d8' , in_binaryen ('scripts' , 'fuzz_shell.js' ), '--' , wasm ])
144157
145158
146159# Each test case handler receives two wasm files, one before and one after some changes
@@ -166,7 +179,7 @@ def handle_pair(self, before_wasm, after_wasm, opts):
166179
167180 def run_vms (self , js , wasm ):
168181 results = []
169- results .append (run_bynterp (wasm ))
182+ results .append (fix_output ( run_bynterp (wasm , [ '--fuzz-exec-before' ]) ))
170183 results .append (fix_output (run_vm (['d8' , js ] + V8_OPTS + ['--' , wasm ])))
171184
172185 # append to add results from VMs
@@ -200,7 +213,7 @@ def compare_vs(self, before, after):
200213class FuzzExec (TestCaseHandler ):
201214 def handle_pair (self , before_wasm , after_wasm , opts ):
202215 # fuzz binaryen interpreter itself. separate invocation so result is easily fuzzable
203- run ([ in_bin ( 'wasm-opt' ), before_wasm , '--fuzz-exec' , '--fuzz-binary' ] + opts )
216+ run_bynterp ( before_wasm , [ '--fuzz-exec' , '--fuzz-binary' ])
204217
205218
206219# Check for determinism - the same command must have the same output
@@ -241,19 +254,44 @@ def run(self, wasm):
241254
242255
243256class Bysyncify (TestCaseHandler ):
244- def handle (self , wasm ):
245- # run normally and run in an async manner, and compare
246- before = run ([in_bin ('wasm-opt' ), wasm , '--fuzz-exec' ])
257+ def handle_pair (self , before_wasm , after_wasm , opts ):
258+ # we must legalize in order to run in JS
259+ run ([in_bin ('wasm-opt' ), before_wasm , '--legalize-js-interface' , '-o' , before_wasm ])
260+ run ([in_bin ('wasm-opt' ), after_wasm , '--legalize-js-interface' , '-o' , after_wasm ])
261+ before = fix_output (run_d8 (before_wasm ))
262+ after = fix_output (run_d8 (after_wasm ))
263+
247264 # TODO: also something that actually does async sleeps in the code, say
248265 # on the logging commands?
249266 # --remove-unused-module-elements removes the bysyncify intrinsics, which are not valid to call
250- cmd = [in_bin ('wasm-opt' ), wasm , '--bysyncify' , '--remove-unused-module-elements' , '-o' , 'by.wasm' ]
251- if random .random () < 0.5 :
252- cmd += ['--optimize-level=3' ] # TODO: more
253- run (cmd )
254- after = run ([in_bin ('wasm-opt' ), 'by.wasm' , '--fuzz-exec' ])
255- after = '\n ' .join ([line for line in after .splitlines () if '[fuzz-exec] calling $bysyncify' not in line ])
256- compare (before , after , 'Bysyncify' )
267+
268+ def do_bysyncify (wasm ):
269+ cmd = [in_bin ('wasm-opt' ), wasm , '--bysyncify' , '-o' , 't.wasm' ]
270+ if random .random () < 0.5 :
271+ cmd += ['--optimize-level=%d' % random .randint (1 , 3 )]
272+ if random .random () < 0.5 :
273+ cmd += ['--shrink-level=%d' % random .randint (1 , 2 )]
274+ run (cmd )
275+ out = run_d8 ('t.wasm' )
276+ # emit some status logging from bysyncify
277+ print (out .splitlines ()[- 1 ])
278+ # ignore the output from the new bysyncify API calls - the ones with asserts will trap, too
279+ for ignore in ['[fuzz-exec] calling $bysyncify_start_unwind\n exception!\n ' ,
280+ '[fuzz-exec] calling $bysyncify_start_unwind\n ' ,
281+ '[fuzz-exec] calling $bysyncify_start_rewind\n exception!\n ' ,
282+ '[fuzz-exec] calling $bysyncify_start_rewind\n ' ,
283+ '[fuzz-exec] calling $bysyncify_stop_rewind\n ' ,
284+ '[fuzz-exec] calling $bysyncify_stop_unwind\n ' ]:
285+ out = out .replace (ignore , '' )
286+ out = '\n ' .join ([l for l in out .splitlines () if 'bysyncify: ' not in l ])
287+ return fix_output (out )
288+
289+ before_bysyncify = do_bysyncify (before_wasm )
290+ after_bysyncify = do_bysyncify (after_wasm )
291+
292+ compare (before , after , 'Bysyncify (before/after)' )
293+ compare (before , before_bysyncify , 'Bysyncify (before/before_bysyncify)' )
294+ compare (before , after_bysyncify , 'Bysyncify (before/after_bysyncify)' )
257295
258296
259297# The global list of all test case handlers
@@ -262,19 +300,19 @@ def handle(self, wasm):
262300 FuzzExec (),
263301 CheckDeterminism (),
264302 Wasm2JS (),
265- # TODO Bysyncify(),
303+ Bysyncify (),
266304]
267305
268306
269307# Do one test, given an input file for -ttf and some optimizations to run
270- def test_one (infile , opts ):
308+ def test_one (random_input , opts ):
271309 randomize_pass_debug ()
272310
273311 bytes = 0
274312
275313 # fuzz vms
276314 # gather VM outputs on input file
277- run ([in_bin ('wasm-opt' ), infile , '-ttf' , '-o' , 'a.wasm' ] + FUZZ_OPTS + FEATURE_OPTS )
315+ run ([in_bin ('wasm-opt' ), random_input , '-ttf' , '-o' , 'a.wasm' ] + FUZZ_OPTS + FEATURE_OPTS )
278316 wasm_size = os .stat ('a.wasm' ).st_size
279317 bytes += wasm_size
280318 print ('pre js size :' , os .stat ('a.js' ).st_size , ' wasm size:' , wasm_size )
0 commit comments