@@ -118,6 +118,25 @@ impl HostFunc {
118118 }
119119 }
120120
121+ pub ( crate ) unsafe fn new_unchecked < T , F > ( func : F ) -> Arc < HostFunc >
122+ where
123+ T : ' static ,
124+ F : Fn ( StoreContextMut < ' _ , T > , ComponentFunc , & mut [ MaybeUninit < ValRaw > ] ) -> Result < ( ) >
125+ + Send
126+ + Sync
127+ + ' static ,
128+ {
129+ let entrypoint = raw_entrypoint :: < T , F > ;
130+ Arc :: new ( HostFunc {
131+ entrypoint,
132+ // This function performs external type checks and subsequently does
133+ // not need to perform up-front type checks. Instead everything is
134+ // dynamically managed at runtime.
135+ typecheck : Box :: new ( move |_expected_index, _expected_types| Ok ( ( ) ) ) ,
136+ func : Box :: new ( func) ,
137+ } )
138+ }
139+
121140 fn new_dynamic_canonical < T , F > ( func : F ) -> Arc < HostFunc >
122141 where
123142 F : Fn (
@@ -664,6 +683,55 @@ where
664683 }
665684}
666685
686+ unsafe fn call_raw < T , F > (
687+ mut store : StoreContextMut < ' _ , T > ,
688+ instance : Instance ,
689+ ty : TypeFuncIndex ,
690+ options_idx : OptionsIndex ,
691+ storage : & mut [ MaybeUninit < ValRaw > ] ,
692+ closure : F ,
693+ ) -> Result < ( ) >
694+ where
695+ F : Fn ( StoreContextMut < ' _ , T > , ComponentFunc , & mut [ MaybeUninit < ValRaw > ] ) -> Result < ( ) >
696+ + Send
697+ + Sync
698+ + ' static ,
699+ {
700+ let options = Options :: new_index ( store. 0 , instance, options_idx) ;
701+ let vminstance = instance. id ( ) . get ( store. 0 ) ;
702+ let opts = & vminstance. component ( ) . env_component ( ) . options [ options_idx] ;
703+ let caller_instance = opts. instance ;
704+ let mut flags = vminstance. instance_flags ( caller_instance) ;
705+
706+ // Perform a dynamic check that this instance can indeed be left. Exiting
707+ // the component is disallowed, for example, when the `realloc` function
708+ // calls a canonical import.
709+ if unsafe { !flags. may_leave ( ) } {
710+ return Err ( anyhow ! ( crate :: Trap :: CannotLeaveComponent ) ) ;
711+ }
712+
713+ let types = instance. id ( ) . get ( store. 0 ) . component ( ) . types ( ) . clone ( ) ;
714+
715+ let lift = & mut LiftContext :: new ( store. 0 . store_opaque_mut ( ) , & options, instance) ;
716+ lift. enter_call ( ) ;
717+ let ty = ComponentFunc :: from ( ty, & lift. instance_type ( ) ) ;
718+
719+ // TODO: Handle resources and async
720+
721+ closure ( store. as_context_mut ( ) , ty, storage) ?;
722+
723+ unsafe {
724+ flags. set_may_leave ( false ) ;
725+ }
726+ let mut lower = LowerContext :: new ( store, & options, & types, instance) ;
727+ unsafe {
728+ flags. set_may_leave ( true ) ;
729+ }
730+ lower. exit_call ( ) ?;
731+
732+ return Ok ( ( ) ) ;
733+ }
734+
667735pub ( crate ) fn validate_inbounds < T : ComponentType > ( memory : & [ u8 ] , ptr : & ValRaw ) -> Result < usize > {
668736 // FIXME(#4311): needs memory64 support
669737 let ptr = usize:: try_from ( ptr. get_u32 ( ) ) ?;
@@ -916,6 +984,36 @@ pub(crate) fn validate_inbounds_dynamic(
916984 Ok ( ptr)
917985}
918986
987+ extern "C" fn raw_entrypoint < T , F > (
988+ cx : NonNull < VMOpaqueContext > ,
989+ data : NonNull < u8 > ,
990+ ty : u32 ,
991+ options : u32 ,
992+ storage : NonNull < MaybeUninit < ValRaw > > ,
993+ storage_len : usize ,
994+ ) -> bool
995+ where
996+ F : Fn ( StoreContextMut < ' _ , T > , ComponentFunc , & mut [ MaybeUninit < ValRaw > ] ) -> Result < ( ) >
997+ + Send
998+ + Sync
999+ + ' static ,
1000+ T : ' static ,
1001+ {
1002+ let data = SendSyncPtr :: new ( NonNull :: new ( data. as_ptr ( ) as * mut F ) . unwrap ( ) ) ;
1003+ unsafe {
1004+ call_host_and_handle_result ( cx, |store, instance| {
1005+ call_raw :: < T , _ > (
1006+ store,
1007+ instance,
1008+ TypeFuncIndex :: from_u32 ( ty) ,
1009+ OptionsIndex :: from_u32 ( options) ,
1010+ NonNull :: slice_from_raw_parts ( storage, storage_len) . as_mut ( ) ,
1011+ & * data. as_ptr ( ) ,
1012+ )
1013+ } )
1014+ }
1015+ }
1016+
9191017extern "C" fn dynamic_entrypoint < T , F > (
9201018 cx : NonNull < VMOpaqueContext > ,
9211019 data : NonNull < u8 > ,
0 commit comments