()
| 129 | #[test] |
| 130 | #[cfg_attr(miri, ignore)] |
| 131 | fn many_live_refs() -> Result<()> { |
| 132 | let mut wat = r#" |
| 133 | (module |
| 134 | ;; Make new `externref`s. |
| 135 | (import "" "make_ref" (func $make_ref (result externref))) |
| 136 | |
| 137 | ;; Observe an `externref` so it is kept live. |
| 138 | (import "" "observe_ref" (func $observe_ref (param externref))) |
| 139 | |
| 140 | (func (export "many_live_refs") |
| 141 | "# |
| 142 | .to_string(); |
| 143 | |
| 144 | // This is more than the initial `VMExternRefActivationsTable` capacity, so |
| 145 | // it will need to allocate additional bump chunks. |
| 146 | const NUM_LIVE_REFS: usize = 1024; |
| 147 | |
| 148 | // Push `externref`s onto the stack. |
| 149 | for _ in 0..NUM_LIVE_REFS { |
| 150 | wat.push_str("(call $make_ref)\n"); |
| 151 | } |
| 152 | |
| 153 | // Pop `externref`s from the stack. Because we pass each of them to a |
| 154 | // function call here, they are all live references for the duration of |
| 155 | // their lifetimes. |
| 156 | for _ in 0..NUM_LIVE_REFS { |
| 157 | wat.push_str("(call $observe_ref)\n"); |
| 158 | } |
| 159 | |
| 160 | wat.push_str( |
| 161 | " |
| 162 | ) ;; func |
| 163 | ) ;; module |
| 164 | ", |
| 165 | ); |
| 166 | |
| 167 | let (mut store, module) = ref_types_module(false, &wat)?; |
| 168 | |
| 169 | let live_refs = Arc::new(AtomicUsize::new(0)); |
| 170 | |
| 171 | let make_ref = Func::wrap(&mut store, { |
| 172 | let live_refs = live_refs.clone(); |
| 173 | move |mut caller: Caller<'_, _>| { |
| 174 | Ok(Some(ExternRef::new( |
| 175 | &mut caller, |
| 176 | CountLiveRefs::new(live_refs.clone()), |
| 177 | )?)) |
| 178 | } |
| 179 | }); |
| 180 | |
| 181 | let observe_ref = Func::wrap( |
| 182 | &mut store, |
| 183 | |caller: Caller<'_, _>, r: Option<Rooted<ExternRef>>| { |
| 184 | let r = r |
| 185 | .unwrap() |
| 186 | .data(&caller) |
| 187 | .unwrap() |
| 188 | .unwrap() |
nothing calls this directly
no test coverage detected