@@ -93,8 +93,7 @@ use crate::runtime::vm::mpk::ProtectionKey;
9393use crate :: runtime:: vm:: {
9494 self , GcStore , Imports , InstanceAllocationRequest , InstanceAllocator , InstanceHandle ,
9595 Interpreter , InterpreterRef , ModuleRuntimeInfo , OnDemandInstanceAllocator , SendSyncPtr ,
96- SignalHandler , StoreBox , StorePtr , Unwind , VMContext , VMFuncRef , VMGcRef , VMStore ,
97- VMStoreContext ,
96+ SignalHandler , StoreBox , Unwind , VMContext , VMFuncRef , VMGcRef , VMStore , VMStoreContext ,
9897} ;
9998use crate :: trampoline:: VMHostGlobalContext ;
10099use crate :: { Engine , Module , Trap , Val , ValRaw , module:: ModuleRegistry } ;
@@ -470,6 +469,20 @@ pub struct StoreOpaque {
470469 executor : Executor ,
471470}
472471
472+ /// Self-pointer to `StoreInner<T>` from within a `StoreOpaque` which is chiefly
473+ /// used to copy into instances during instantiation.
474+ ///
475+ /// FIXME: ideally this type would get deleted and Wasmtime's reliance on it
476+ /// would go away.
477+ struct StorePtr ( Option < NonNull < dyn VMStore > > ) ;
478+
479+ // We can't make `VMStore: Send + Sync` because that requires making all of
480+ // Wastime's internals generic over the `Store`'s `T`. So instead, we take care
481+ // in the whole VM layer to only use the `VMStore` in ways that are `Send`- and
482+ // `Sync`-safe and we have to have these unsafe impls.
483+ unsafe impl Send for StorePtr { }
484+ unsafe impl Sync for StorePtr { }
485+
473486/// Executor state within `StoreOpaque`.
474487///
475488/// Effectively stores Pulley interpreter state and handles conditional support
@@ -646,7 +659,7 @@ impl<T> Store<T> {
646659 fuel_reserve : 0 ,
647660 fuel_yield_interval : None ,
648661 store_data,
649- traitobj : StorePtr :: empty ( ) ,
662+ traitobj : StorePtr ( None ) ,
650663 default_caller_vmctx : SendSyncPtr :: new ( NonNull :: dangling ( ) ) ,
651664 hostcall_val_storage : Vec :: new ( ) ,
652665 wasm_val_raw_storage : Vec :: new ( ) ,
@@ -670,7 +683,7 @@ impl<T> Store<T> {
670683 data : ManuallyDrop :: new ( data) ,
671684 } ) ;
672685
673- inner. traitobj = StorePtr :: new ( NonNull :: from ( & mut * inner) ) ;
686+ inner. traitobj = StorePtr ( Some ( NonNull :: from ( & mut * inner) ) ) ;
674687
675688 // Wasmtime uses the callee argument to host functions to learn about
676689 // the original pointer to the `Store` itself, allowing it to
@@ -1489,15 +1502,15 @@ impl StoreOpaque {
14891502 /// `ResourceLimiterAsync` which means that this should only be executed
14901503 /// in a fiber context at this time.
14911504 #[ inline]
1492- pub ( crate ) fn ensure_gc_store ( & mut self ) -> Result < & mut GcStore > {
1505+ pub ( crate ) async fn ensure_gc_store ( & mut self ) -> Result < & mut GcStore > {
14931506 if self . gc_store . is_some ( ) {
14941507 return Ok ( self . gc_store . as_mut ( ) . unwrap ( ) ) ;
14951508 }
1496- self . allocate_gc_store ( )
1509+ self . allocate_gc_store ( ) . await
14971510 }
14981511
14991512 #[ inline( never) ]
1500- fn allocate_gc_store ( & mut self ) -> Result < & mut GcStore > {
1513+ async fn allocate_gc_store ( & mut self ) -> Result < & mut GcStore > {
15011514 log:: trace!( "allocating GC heap for store {:?}" , self . id( ) ) ;
15021515
15031516 assert ! ( self . gc_store. is_none( ) ) ;
@@ -1507,19 +1520,24 @@ impl StoreOpaque {
15071520 ) ;
15081521 assert_eq ! ( self . vm_store_context. gc_heap. current_length( ) , 0 ) ;
15091522
1510- let vmstore = self . traitobj ( ) ;
1511- let gc_store = allocate_gc_store ( self . engine ( ) , vmstore, self . get_pkey ( ) ) ?;
1523+ let gc_store = allocate_gc_store ( self ) . await ?;
15121524 self . vm_store_context . gc_heap = gc_store. vmmemory_definition ( ) ;
15131525 return Ok ( self . gc_store . insert ( gc_store) ) ;
15141526
15151527 #[ cfg( feature = "gc" ) ]
1516- fn allocate_gc_store (
1517- engine : & Engine ,
1518- vmstore : NonNull < dyn VMStore > ,
1519- pkey : Option < ProtectionKey > ,
1520- ) -> Result < GcStore > {
1528+ async fn allocate_gc_store ( store : & mut StoreOpaque ) -> Result < GcStore > {
15211529 use wasmtime_environ:: packed_option:: ReservedValue ;
15221530
1531+ // FIXME(#11409) this is not a sound widening borrow
1532+ let ( mut limiter, store) = unsafe {
1533+ store
1534+ . traitobj ( )
1535+ . as_mut ( )
1536+ . resource_limiter_and_store_opaque ( )
1537+ } ;
1538+
1539+ let engine = store. engine ( ) ;
1540+ let mem_ty = engine. tunables ( ) . gc_heap_memory_type ( ) ;
15231541 ensure ! (
15241542 engine. features( ) . gc_types( ) ,
15251543 "cannot allocate a GC store when GC is disabled at configuration time"
@@ -1532,19 +1550,14 @@ impl StoreOpaque {
15321550 wasmtime_environ:: Module :: default ( ) ,
15331551 ) ) ,
15341552 imports : vm:: Imports :: default ( ) ,
1535- store : StorePtr :: new ( vmstore) ,
1536- #[ cfg( feature = "wmemcheck" ) ]
1537- wmemcheck : false ,
1538- pkey,
1539- tunables : engine. tunables ( ) ,
1553+ store,
1554+ limiter : limiter. as_mut ( ) ,
15401555 } ;
1541- let mem_ty = engine. tunables ( ) . gc_heap_memory_type ( ) ;
1542- let tunables = engine. tunables ( ) ;
15431556
1544- let ( mem_alloc_index, mem) =
1545- engine
1546- . allocator ( )
1547- . allocate_memory ( & mut request , & mem_ty , tunables , None ) ?;
1557+ let ( mem_alloc_index, mem) = engine
1558+ . allocator ( )
1559+ . allocate_memory ( & mut request , & mem_ty , None )
1560+ . await ?;
15481561
15491562 // Then, allocate the actual GC heap, passing in that memory
15501563 // storage.
@@ -1560,11 +1573,7 @@ impl StoreOpaque {
15601573 }
15611574
15621575 #[ cfg( not( feature = "gc" ) ) ]
1563- fn allocate_gc_store (
1564- _engine : & Engine ,
1565- _vmstore : NonNull < dyn VMStore > ,
1566- _pkey : Option < ProtectionKey > ,
1567- ) -> Result < GcStore > {
1576+ async fn allocate_gc_store ( _: & mut StoreOpaque ) -> Result < GcStore > {
15681577 bail ! ( "cannot allocate a GC store: the `gc` feature was disabled at compile time" )
15691578 }
15701579 }
@@ -1944,7 +1953,7 @@ impl StoreOpaque {
19441953
19451954 #[ inline]
19461955 pub fn traitobj ( & self ) -> NonNull < dyn VMStore > {
1947- self . traitobj . as_raw ( ) . unwrap ( )
1956+ self . traitobj . 0 . unwrap ( )
19481957 }
19491958
19501959 /// Takes the cached `Vec<Val>` stored internally across hostcalls to get
@@ -2091,6 +2100,7 @@ at https://bytecodealliance.org/security.
20912100
20922101 /// Retrieve the store's protection key.
20932102 #[ inline]
2103+ #[ cfg( feature = "pooling-allocator" ) ]
20942104 pub ( crate ) fn get_pkey ( & self ) -> Option < ProtectionKey > {
20952105 self . pkey
20962106 }
@@ -2225,16 +2235,17 @@ at https://bytecodealliance.org/security.
22252235 // SAFETY: this function's own contract is the same as
22262236 // `allocate_module`, namely the imports provided are valid.
22272237 let handle = unsafe {
2228- allocator. allocate_module ( InstanceAllocationRequest {
2229- id,
2230- runtime_info,
2231- imports,
2232- store : StorePtr :: new ( self . traitobj ( ) ) ,
2233- #[ cfg( feature = "wmemcheck" ) ]
2234- wmemcheck : self . engine ( ) . config ( ) . wmemcheck ,
2235- pkey : self . get_pkey ( ) ,
2236- tunables : self . engine ( ) . tunables ( ) ,
2237- } ) ?
2238+ // FIXME(#11409) this is not a sound widening borrow
2239+ let ( mut limiter, store) = self . traitobj ( ) . as_mut ( ) . resource_limiter_and_store_opaque ( ) ;
2240+ allocator
2241+ . allocate_module ( InstanceAllocationRequest {
2242+ id,
2243+ runtime_info,
2244+ imports,
2245+ store,
2246+ limiter : limiter. as_mut ( ) ,
2247+ } )
2248+ . await ?
22382249 } ;
22392250
22402251 let actual = match kind {
@@ -2316,82 +2327,6 @@ unsafe impl<T> VMStore for StoreInner<T> {
23162327 )
23172328 }
23182329
2319- fn memory_growing (
2320- & mut self ,
2321- current : usize ,
2322- desired : usize ,
2323- maximum : Option < usize > ,
2324- ) -> Result < bool , anyhow:: Error > {
2325- match self . limiter {
2326- Some ( ResourceLimiterInner :: Sync ( ref mut limiter) ) => {
2327- limiter ( & mut self . data ) . memory_growing ( current, desired, maximum)
2328- }
2329- #[ cfg( feature = "async" ) ]
2330- Some ( ResourceLimiterInner :: Async ( _) ) => self . block_on ( |store| {
2331- let limiter = match & mut store. 0 . limiter {
2332- Some ( ResourceLimiterInner :: Async ( limiter) ) => limiter,
2333- _ => unreachable ! ( ) ,
2334- } ;
2335- limiter ( & mut store. 0 . data ) . memory_growing ( current, desired, maximum)
2336- } ) ?,
2337- None => Ok ( true ) ,
2338- }
2339- }
2340-
2341- fn memory_grow_failed ( & mut self , error : anyhow:: Error ) -> Result < ( ) > {
2342- match self . limiter {
2343- Some ( ResourceLimiterInner :: Sync ( ref mut limiter) ) => {
2344- limiter ( & mut self . data ) . memory_grow_failed ( error)
2345- }
2346- #[ cfg( feature = "async" ) ]
2347- Some ( ResourceLimiterInner :: Async ( ref mut limiter) ) => {
2348- limiter ( & mut self . data ) . memory_grow_failed ( error)
2349- }
2350- None => {
2351- log:: debug!( "ignoring memory growth failure error: {error:?}" ) ;
2352- Ok ( ( ) )
2353- }
2354- }
2355- }
2356-
2357- fn table_growing (
2358- & mut self ,
2359- current : usize ,
2360- desired : usize ,
2361- maximum : Option < usize > ,
2362- ) -> Result < bool , anyhow:: Error > {
2363- match self . limiter {
2364- Some ( ResourceLimiterInner :: Sync ( ref mut limiter) ) => {
2365- limiter ( & mut self . data ) . table_growing ( current, desired, maximum)
2366- }
2367- #[ cfg( feature = "async" ) ]
2368- Some ( ResourceLimiterInner :: Async ( _) ) => self . block_on ( |store| {
2369- let limiter = match & mut store. 0 . limiter {
2370- Some ( ResourceLimiterInner :: Async ( limiter) ) => limiter,
2371- _ => unreachable ! ( ) ,
2372- } ;
2373- limiter ( & mut store. 0 . data ) . table_growing ( current, desired, maximum)
2374- } ) ?,
2375- None => Ok ( true ) ,
2376- }
2377- }
2378-
2379- fn table_grow_failed ( & mut self , error : anyhow:: Error ) -> Result < ( ) > {
2380- match self . limiter {
2381- Some ( ResourceLimiterInner :: Sync ( ref mut limiter) ) => {
2382- limiter ( & mut self . data ) . table_grow_failed ( error)
2383- }
2384- #[ cfg( feature = "async" ) ]
2385- Some ( ResourceLimiterInner :: Async ( ref mut limiter) ) => {
2386- limiter ( & mut self . data ) . table_grow_failed ( error)
2387- }
2388- None => {
2389- log:: debug!( "ignoring table growth failure: {error:?}" ) ;
2390- Ok ( ( ) )
2391- }
2392- }
2393- }
2394-
23952330 fn out_of_gas ( & mut self ) -> Result < ( ) > {
23962331 if !self . refuel ( ) {
23972332 return Err ( Trap :: OutOfFuel . into ( ) ) ;
0 commit comments