@@ -22,7 +22,6 @@ use crate::{
2222 } ,
2323 engine:: {
2424 DedupFuncType ,
25- EngineFunc ,
2625 FuncEntry ,
2726 executor:: {
2827 LoadFromCellsByValue ,
@@ -85,22 +84,6 @@ macro_rules! compile_or_get_func_entry {
8584 } } ;
8685}
8786
88- pub fn compile_or_get_func ( state : & mut VmState , func : EngineFunc ) -> Result < ( Ip , u16 , u16 ) , Error > {
89- let Some ( func_entry) = state. code . entry ( func) else {
90- unreachable ! ( "missing function entry at: {func:?}" )
91- } ;
92- compile_or_get_func_entry ( state, func_entry)
93- }
94-
95- macro_rules! compile_or_get_func {
96- ( $state: expr, $func: expr) => { {
97- match $crate:: engine:: executor:: handler:: utils:: compile_or_get_func( $state, $func) {
98- Ok ( ( ip, len_local_slots, len_stack_slots) ) => ( ip, len_local_slots, len_stack_slots) ,
99- Err ( error) => done!( $state, DoneReason :: error( error) ) ,
100- }
101- } } ;
102- }
103-
10487macro_rules! trap {
10588 ( $trap_code: expr) => { {
10689 return $crate:: engine:: executor:: handler:: Control :: Break (
@@ -789,7 +772,7 @@ pub fn update_instance(
789772 ( new_instance, mem0, mem0_len)
790773}
791774
792- #[ inline]
775+ #[ inline( always ) ]
793776pub fn call_func_entry (
794777 state : & mut VmState ,
795778 caller_ip : Ip ,
@@ -812,30 +795,7 @@ pub fn call_func_entry(
812795 Control :: Continue ( ( callee_ip, callee_sp) )
813796}
814797
815- #[ inline( never) ]
816- pub fn call_wasm (
817- state : & mut VmState ,
818- caller_ip : Ip ,
819- params : BoundedSlotSpan ,
820- func : EngineFunc ,
821- instance : Option < Inst > ,
822- ) -> Control < ( Ip , Sp ) , Break > {
823- let ( callee_ip, len_local_slots, len_stack_slots) = compile_or_get_func ! ( state, func) ;
824- let callee_sp = state
825- . stack
826- . push_frame (
827- Some ( caller_ip) ,
828- callee_ip,
829- params,
830- len_local_slots,
831- len_stack_slots,
832- instance,
833- )
834- . into_control ( ) ?;
835- Control :: Continue ( ( callee_ip, callee_sp) )
836- }
837-
838- #[ inline]
798+ #[ inline( always) ]
839799pub fn return_call_func_entry (
840800 state : & mut VmState ,
841801 params : BoundedSlotSpan ,
@@ -856,27 +816,6 @@ pub fn return_call_func_entry(
856816 Control :: Continue ( ( callee_ip, callee_sp) )
857817}
858818
859- #[ inline( never) ]
860- pub fn return_call_wasm (
861- state : & mut VmState ,
862- params : BoundedSlotSpan ,
863- func : EngineFunc ,
864- instance : Option < Inst > ,
865- ) -> Control < ( Ip , Sp ) , Break > {
866- let ( callee_ip, len_local_slots, len_stack_slots) = compile_or_get_func ! ( state, func) ;
867- let callee_sp = state
868- . stack
869- . replace_frame (
870- callee_ip,
871- params,
872- len_local_slots,
873- len_stack_slots,
874- instance,
875- )
876- . into_control ( ) ?;
877- Control :: Continue ( ( callee_ip, callee_sp) )
878- }
879-
880819pub fn call_host (
881820 state : & mut VmState ,
882821 func : Func ,
@@ -950,6 +889,7 @@ pub fn return_call_host(
950889 }
951890}
952891
892+ #[ inline]
953893#[ expect( clippy:: too_many_arguments) ]
954894pub fn call_wasm_or_host (
955895 state : & mut VmState ,
@@ -965,39 +905,41 @@ pub fn call_wasm_or_host(
965905 // (indirect calls); the reference is only used to copy out the callee data below,
966906 // before any store mutation, so it never aliases a `&mut` into the funcs arena.
967907 let func_entity = unsafe { func_entity. as_ref ( ) } ;
968- let next_state = match func_entity {
969- FuncEntity :: Wasm ( wasm_func) => {
970- let func = wasm_func. func_body ( ) ;
971- let callee_instance = * wasm_func. instance ( ) ;
972- let callee_instance: Inst = resolve_instance ( state. store , & callee_instance) . into ( ) ;
973- let ( callee_ip, callee_sp) =
974- call_wasm ( state, caller_ip, params, func, Some ( callee_instance) ) ?;
975- let ( instance, mem0, mem0_len) =
976- update_instance ( state. store , instance, callee_instance, mem0, mem0_len) ;
977- ( callee_ip, callee_sp, mem0, mem0_len, instance)
978- }
908+ let wasm_func = match func_entity {
909+ FuncEntity :: Wasm ( wasm_func) => wasm_func,
979910 FuncEntity :: Host ( host_func) => {
980- let host_func = * host_func;
981911 let sp = call_host (
982912 state,
983913 func,
984914 Some ( caller_ip) ,
985- host_func,
915+ * host_func,
986916 params,
987917 Some ( instance) ,
988918 CallHooks :: Call ,
989919 ) ?;
990- // Host functions may re-enter WASM (e.g. calling cabi_realloc)
991- // which can trigger memory.grow, invalidating the cached mem0
992- // pointer. Re-extract to avoid stale pointer dereference.
920+ // Note: host functions may grow memories, invalidating the cached `(memory 0)`.
921+ // Therefore, it is required to re-extract `(memory 0)` to avoid a stale cache.
993922 let ( mem0, mem0_len) = extract_mem0 ( state. store , instance) ;
994- ( caller_ip, sp, mem0, mem0_len, instance)
923+ return Control :: Continue ( ( caller_ip, sp, mem0, mem0_len, instance) ) ;
995924 }
996925 } ;
997- Control :: Continue ( next_state)
926+ // Hot path: calling a Wasm function. Uses the cached `FuncEntry` and the same inlined
927+ // machinery as `call_internal`, differing only in the possible instance switch.
928+ let callee_instance: Inst = resolve_instance ( state. store , wasm_func. instance ( ) ) . into ( ) ;
929+ let ( callee_ip, callee_sp) = call_func_entry (
930+ state,
931+ caller_ip,
932+ params,
933+ wasm_func. func_entry ( ) ,
934+ Some ( callee_instance) ,
935+ ) ?;
936+ let ( instance, mem0, mem0_len) =
937+ update_instance ( state. store , instance, callee_instance, mem0, mem0_len) ;
938+ Control :: Continue ( ( callee_ip, callee_sp, mem0, mem0_len, instance) )
998939}
999940
1000941/// Tail-call (`return_call`) twin of [`call_wasm_or_host`].
942+ #[ inline]
1001943pub fn return_call_wasm_or_host (
1002944 state : & mut VmState ,
1003945 func : Func ,
@@ -1009,25 +951,22 @@ pub fn return_call_wasm_or_host(
1009951) -> Control < ( Ip , Sp , Mem0Ptr , Mem0Len , Inst ) , Break > {
1010952 // SAFETY: see `call_wasm_or_host`.
1011953 let func_entity = unsafe { func_entity. as_ref ( ) } ;
1012- let ( callee_ip, sp, new_instance) = match func_entity {
1013- FuncEntity :: Wasm ( wasm_func) => {
1014- let wasm_func_body = wasm_func. func_body ( ) ;
1015- let callee_instance = * wasm_func. instance ( ) ;
1016- let callee_instance: Inst = resolve_instance ( state. store , & callee_instance) . into ( ) ;
1017- let changed_instance = match callee_instance != instance {
1018- true => Some ( callee_instance) ,
1019- false => None ,
1020- } ;
1021- let ( callee_ip, callee_sp) =
1022- return_call_wasm ( state, params, wasm_func_body, changed_instance) ?;
1023- ( callee_ip, callee_sp, callee_instance)
1024- }
954+ let wasm_func = match func_entity {
955+ FuncEntity :: Wasm ( wasm_func) => wasm_func,
1025956 FuncEntity :: Host ( host_func) => {
1026- let host_func = * host_func;
1027- return_call_host ( state, func, host_func, params, instance) ?
957+ let ( callee_ip, sp, new_instance) =
958+ return_call_host ( state, func, * host_func, params, instance) ?;
959+ let ( instance, mem0, mem0_len) =
960+ update_instance ( state. store , instance, new_instance, mem0, mem0_len) ;
961+ return Control :: Continue ( ( callee_ip, sp, mem0, mem0_len, instance) ) ;
1028962 }
1029963 } ;
964+ // Hot path: tail-calling a Wasm function. See `call_wasm_or_host` for the shape.
965+ let callee_instance: Inst = resolve_instance ( state. store , wasm_func. instance ( ) ) . into ( ) ;
966+ let changed_instance = ( callee_instance != instance) . then_some ( callee_instance) ;
967+ let ( callee_ip, callee_sp) =
968+ return_call_func_entry ( state, params, wasm_func. func_entry ( ) , changed_instance) ?;
1030969 let ( instance, mem0, mem0_len) =
1031- update_instance ( state. store , instance, new_instance , mem0, mem0_len) ;
1032- Control :: Continue ( ( callee_ip, sp , mem0, mem0_len, instance) )
970+ update_instance ( state. store , instance, callee_instance , mem0, mem0_len) ;
971+ Control :: Continue ( ( callee_ip, callee_sp , mem0, mem0_len, instance) )
1033972}
0 commit comments