|
1 | 1 | use crate::prelude::*; |
2 | 2 | use crate::runtime::Uninhabited; |
3 | 3 | use crate::runtime::vm::{ |
4 | | - InterpreterRef, SendSyncPtr, StoreBox, VMArrayCallHostFuncContext, VMCommonStackInformation, |
5 | | - VMContext, VMFuncRef, VMFunctionImport, VMOpaqueContext, VMStoreContext, |
| 4 | + self, InterpreterRef, SendSyncPtr, StoreBox, VMArrayCallHostFuncContext, |
| 5 | + VMCommonStackInformation, VMContext, VMFuncRef, VMFunctionImport, VMOpaqueContext, |
| 6 | + VMStoreContext, |
6 | 7 | }; |
7 | | -use crate::store::{AutoAssertNoGc, StoreId, StoreOpaque}; |
| 8 | +use crate::store::{AutoAssertNoGc, InstanceId, StoreId, StoreOpaque}; |
8 | 9 | use crate::type_registry::RegisteredType; |
9 | 10 | use crate::{ |
10 | 11 | AsContext, AsContextMut, CallHook, Engine, Extern, FuncType, Instance, ModuleExport, Ref, |
@@ -2041,46 +2042,31 @@ impl<T> Caller<'_, T> { |
2041 | 2042 |
|
2042 | 2043 | /// Executes `f` with an appropriate `Caller`. |
2043 | 2044 | /// |
2044 | | - /// This is the entrypoint for host functions in core wasm and converts from |
2045 | | - /// `VMContext` to `Caller` |
2046 | | - /// |
2047 | | - /// # Safety |
2048 | | - /// |
2049 | | - /// This requires that `caller` is safe to wrap up as a `Caller`, |
2050 | | - /// effectively meaning that we just entered the host from wasm. |
2051 | | - /// Additionally this `Caller`'s `T` parameter must match the actual `T` in |
2052 | | - /// the store of the vmctx of `caller`. |
2053 | | - unsafe fn with<F, R>(caller: NonNull<VMContext>, f: F) -> R |
| 2045 | + /// This is the entrypoint for host functions in core wasm. The `store` and |
| 2046 | + /// `instance` are created from `Instance::enter_host_from_wasm` and this |
| 2047 | + /// will further invoke the host function that `f` refers to. |
| 2048 | + fn with<F, R>(mut store: StoreContextMut<T>, caller: InstanceId, f: F) -> R |
2054 | 2049 | where |
2055 | 2050 | F: FnOnce(Caller<'_, T>) -> R, |
2056 | 2051 | { |
2057 | | - // SAFETY: it's a contract of this function itself that `from_vmctx` is |
2058 | | - // safe to call. Additionally it's a contract of this function itself |
2059 | | - // that the `T` of `Caller` matches the store. |
2060 | | - unsafe { |
2061 | | - crate::runtime::vm::InstanceAndStore::from_vmctx(caller, |pair| { |
2062 | | - let (instance, store) = pair.unpack_mut(); |
2063 | | - let mut store = store.unchecked_context_mut::<T>(); |
2064 | | - let caller = Instance::from_wasmtime(instance.id(), store.0); |
| 2052 | + let caller = Instance::from_wasmtime(caller, store.0); |
2065 | 2053 |
|
2066 | | - let (gc_lifo_scope, ret) = { |
2067 | | - let gc_lifo_scope = store.0.gc_roots().enter_lifo_scope(); |
| 2054 | + let (gc_lifo_scope, ret) = { |
| 2055 | + let gc_lifo_scope = store.0.gc_roots().enter_lifo_scope(); |
2068 | 2056 |
|
2069 | | - let ret = f(Caller { |
2070 | | - store: store.as_context_mut(), |
2071 | | - caller, |
2072 | | - }); |
| 2057 | + let ret = f(Caller { |
| 2058 | + store: store.as_context_mut(), |
| 2059 | + caller, |
| 2060 | + }); |
2073 | 2061 |
|
2074 | | - (gc_lifo_scope, ret) |
2075 | | - }; |
| 2062 | + (gc_lifo_scope, ret) |
| 2063 | + }; |
2076 | 2064 |
|
2077 | | - // Safe to recreate a mutable borrow of the store because `ret` |
2078 | | - // cannot be borrowing from the store. |
2079 | | - store.0.exit_gc_lifo_scope(gc_lifo_scope); |
| 2065 | + // Safe to recreate a mutable borrow of the store because `ret` |
| 2066 | + // cannot be borrowing from the store. |
| 2067 | + store.0.exit_gc_lifo_scope(gc_lifo_scope); |
2080 | 2068 |
|
2081 | | - ret |
2082 | | - }) |
2083 | | - } |
| 2069 | + ret |
2084 | 2070 | } |
2085 | 2071 |
|
2086 | 2072 | fn sub_caller(&mut self) -> Caller<'_, T> { |
@@ -2409,10 +2395,14 @@ impl HostContext { |
2409 | 2395 | // closure and then run it as part of `Caller::with`. |
2410 | 2396 | // |
2411 | 2397 | // SAFETY: this is an entrypoint of wasm which requires correct type |
2412 | | - // ascription of `T` itself, meaning that this should be safe to call. |
2413 | | - crate::runtime::vm::catch_unwind_and_record_trap(move || unsafe { |
2414 | | - Caller::with(caller_vmctx, run) |
2415 | | - }) |
| 2398 | + // ascription of `T` itself, meaning that this should be safe to call |
| 2399 | + // both `enter_host_from_wasm` as well as `unchecked_context_mut`. |
| 2400 | + unsafe { |
| 2401 | + vm::Instance::enter_host_from_wasm(caller_vmctx, |store, instance| { |
| 2402 | + let store = store.unchecked_context_mut(); |
| 2403 | + Caller::with(store, instance.id(), run) |
| 2404 | + }) |
| 2405 | + } |
2416 | 2406 | } |
2417 | 2407 | } |
2418 | 2408 |
|
@@ -2485,20 +2475,23 @@ impl HostFunc { |
2485 | 2475 | T: 'static, |
2486 | 2476 | { |
2487 | 2477 | assert!(ty.comes_from_same_engine(engine)); |
2488 | | - // SAFETY: This is only only called in the raw entrypoint of wasm |
2489 | | - // meaning that `caller_vmctx` is appropriate to read, and additionally |
2490 | | - // the later usage of `{,in}to_func` will connect `T` to an actual |
2491 | | - // store's `T` to ensure it's the same. |
2492 | | - let func = move |caller_vmctx, values: &mut [ValRaw]| unsafe { |
2493 | | - Caller::<T>::with(caller_vmctx, |mut caller| { |
2494 | | - caller.store.0.call_hook(CallHook::CallingHost)?; |
2495 | | - let result = func(caller.sub_caller(), values)?; |
2496 | | - caller.store.0.call_hook(CallHook::ReturningFromHost)?; |
2497 | | - Ok(result) |
2498 | | - }) |
2499 | | - }; |
2500 | | - let ctx = crate::trampoline::create_array_call_function(&ty, func) |
2501 | | - .expect("failed to create function"); |
| 2478 | + let ctx = crate::trampoline::create_array_call_function( |
| 2479 | + &ty, |
| 2480 | + move |store, instance, values: &mut [ValRaw]| { |
| 2481 | + // SAFETY: the later usage of `{,in}to_func` will connect `T` to |
| 2482 | + // an actual store's `T` to ensure it's the same. This means |
| 2483 | + // that the store this is invoked with always has `T` as a type |
| 2484 | + // parameter which should make this cast safe. |
| 2485 | + let store = unsafe { store.unchecked_context_mut::<T>() }; |
| 2486 | + Caller::with(store, instance, |mut caller| { |
| 2487 | + caller.store.0.call_hook(CallHook::CallingHost)?; |
| 2488 | + let result = func(caller.sub_caller(), values)?; |
| 2489 | + caller.store.0.call_hook(CallHook::ReturningFromHost)?; |
| 2490 | + Ok(result) |
| 2491 | + }) |
| 2492 | + }, |
| 2493 | + ) |
| 2494 | + .expect("failed to create function"); |
2502 | 2495 | HostFunc::_new(engine, ctx.into()) |
2503 | 2496 | } |
2504 | 2497 |
|
|
0 commit comments