Entrypoint of WebAssembly back into the host. This is the standard wasmtime "array call signature" which then delegates internally to the host. This assumes that `callee_vmctx` is a `VMArrayCallHostFuncContext` which was built above with `HostFuncState ` internally. This internal function is then used to dispatch based on the arguments. Details handled by this wrapper are: Host panics are han
(
callee_vmctx: NonNull<VMOpaqueContext>,
caller_vmctx: NonNull<VMContext>,
args: NonNull<ValRaw>,
args_len: usize,
)
| 2358 | /// * A GC LIFO scope is maintained around the execution of `F`. |
| 2359 | /// * Call hooks for entering/leaving the host are maintained. |
| 2360 | unsafe extern "C" fn array_call_trampoline<T, F>( |
| 2361 | callee_vmctx: NonNull<VMOpaqueContext>, |
| 2362 | caller_vmctx: NonNull<VMContext>, |
| 2363 | args: NonNull<ValRaw>, |
| 2364 | args_len: usize, |
| 2365 | ) -> bool |
| 2366 | where |
| 2367 | F: Fn(Caller<'_, T>, &mut [MaybeUninit<ValRaw>]) -> Result<()> + 'static, |
| 2368 | T: 'static, |
| 2369 | { |
| 2370 | let run = |store: &mut dyn crate::vm::VMStore, instance: InstanceId| { |
| 2371 | // SAFETY: correct usage of this trampoline requires correct |
| 2372 | // ascription of `T`, so it's the caller's responsibility to line |
| 2373 | // this up. |
| 2374 | let mut store = unsafe { store.unchecked_context_mut() }; |
| 2375 | |
| 2376 | // Handle the entry call hook, with a corresponding exit call hook |
| 2377 | // below. |
| 2378 | store.0.call_hook(CallHook::CallingHost)?; |
| 2379 | |
| 2380 | // SAFETY: this function itself requires that the `vmctx` is |
| 2381 | // valid to use here. |
| 2382 | let state = unsafe { |
| 2383 | let vmctx = VMArrayCallHostFuncContext::from_opaque(callee_vmctx); |
| 2384 | vmctx.as_ref().host_state() |
| 2385 | }; |
| 2386 | |
| 2387 | // Double-check ourselves in debug mode, but we control the |
| 2388 | // `Any` here so an unsafe downcast should also work. |
| 2389 | // |
| 2390 | // SAFETY: this function is only usable with `F`. |
| 2391 | let state = unsafe { |
| 2392 | debug_assert!(state.is::<HostFuncState<F>>()); |
| 2393 | &*(state as *const _ as *const HostFuncState<F>) |
| 2394 | }; |
| 2395 | |
| 2396 | let (gc_lifo_scope, ret) = { |
| 2397 | let gc_lifo_scope = store.0.gc_roots().enter_lifo_scope(); |
| 2398 | |
| 2399 | let mut args = NonNull::slice_from_raw_parts(args.cast(), args_len); |
| 2400 | // SAFETY: it's a contract of this function itself that the values |
| 2401 | // provided are valid to view as a slice. |
| 2402 | let args = unsafe { args.as_mut() }; |
| 2403 | |
| 2404 | let ret = (state.func)( |
| 2405 | Caller { |
| 2406 | caller: Instance::from_wasmtime(instance, store.0), |
| 2407 | store: store.as_context_mut(), |
| 2408 | }, |
| 2409 | args, |
| 2410 | ); |
| 2411 | |
| 2412 | (gc_lifo_scope, ret) |
| 2413 | }; |
| 2414 | |
| 2415 | store.0.exit_gc_lifo_scope(gc_lifo_scope); |
| 2416 | |
| 2417 | // Note that if this returns a trap then `ret` is discarded |
nothing calls this directly
no test coverage detected