MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / array_call_trampoline

Method array_call_trampoline

crates/wasmtime/src/runtime/func.rs:2360–2428  ·  view source on GitHub ↗

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,
    )

Source from the content-addressed store, hash-verified

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

Callers

nothing calls this directly

Calls 11

slice_from_raw_partsFunction · 0.85
unchecked_context_mutMethod · 0.80
host_stateMethod · 0.80
exit_gc_lifo_scopeMethod · 0.80
call_hookMethod · 0.45
as_refMethod · 0.45
enter_lifo_scopeMethod · 0.45
gc_rootsMethod · 0.45
castMethod · 0.45
as_mutMethod · 0.45
as_context_mutMethod · 0.45

Tested by

no test coverage detected