Execute a series of `gc` operations. Returns the number of `gc` operations which occurred throughout the test case -- used to test below that gc happens reasonably soon and eventually.
(mut fuzz_config: generators::Config, mut ops: GcOps)
| 695 | /// Returns the number of `gc` operations which occurred throughout the test |
| 696 | /// case -- used to test below that gc happens reasonably soon and eventually. |
| 697 | pub fn gc_ops(mut fuzz_config: generators::Config, mut ops: GcOps) -> Result<usize> { |
| 698 | let expected_drops = Arc::new(AtomicUsize::new(0)); |
| 699 | let num_dropped = Arc::new(AtomicUsize::new(0)); |
| 700 | |
| 701 | let num_gcs = Arc::new(AtomicUsize::new(0)); |
| 702 | { |
| 703 | fuzz_config.wasmtime.consume_fuel = true; |
| 704 | let mut store = fuzz_config.to_store(); |
| 705 | store.set_fuel(1_000).unwrap(); |
| 706 | |
| 707 | let wasm = ops.to_wasm_binary(); |
| 708 | log_wasm(&wasm); |
| 709 | let module = match compile_module(store.engine(), &wasm, KnownValid::No, &fuzz_config) { |
| 710 | Some(m) => m, |
| 711 | None => return Ok(0), |
| 712 | }; |
| 713 | |
| 714 | let mut linker = Linker::new(store.engine()); |
| 715 | |
| 716 | // To avoid timeouts, limit the number of explicit GCs we perform per |
| 717 | // test case. |
| 718 | const MAX_GCS: usize = 5; |
| 719 | |
| 720 | let func_ty = FuncType::new( |
| 721 | store.engine(), |
| 722 | vec![], |
| 723 | vec![ValType::EXTERNREF, ValType::EXTERNREF, ValType::EXTERNREF], |
| 724 | ); |
| 725 | let func = Func::new(&mut store, func_ty, { |
| 726 | let num_dropped = num_dropped.clone(); |
| 727 | let expected_drops = expected_drops.clone(); |
| 728 | let num_gcs = num_gcs.clone(); |
| 729 | move |mut caller: Caller<'_, StoreLimits>, _params, results| { |
| 730 | log::info!("gc_ops: GC"); |
| 731 | if num_gcs.fetch_add(1, SeqCst) < MAX_GCS { |
| 732 | caller.gc(None)?; |
| 733 | } |
| 734 | |
| 735 | let a = ExternRef::new( |
| 736 | &mut caller, |
| 737 | CountDrops::new(&expected_drops, num_dropped.clone()), |
| 738 | )?; |
| 739 | let b = ExternRef::new( |
| 740 | &mut caller, |
| 741 | CountDrops::new(&expected_drops, num_dropped.clone()), |
| 742 | )?; |
| 743 | let c = ExternRef::new( |
| 744 | &mut caller, |
| 745 | CountDrops::new(&expected_drops, num_dropped.clone()), |
| 746 | )?; |
| 747 | |
| 748 | log::info!("gc_ops: gc() -> ({a:?}, {b:?}, {c:?})"); |
| 749 | results[0] = Some(a).into(); |
| 750 | results[1] = Some(b).into(); |
| 751 | results[2] = Some(c).into(); |
| 752 | Ok(()) |
| 753 | } |
| 754 | }); |