22
33use super :: create_handle:: create_handle;
44use super :: trap:: TrapSink ;
5- use crate :: { Callable , FuncType , Store , Val } ;
5+ use crate :: { Callable , FuncType , Store , Trap , Val } ;
66use anyhow:: { bail, Result } ;
77use std:: cmp;
88use std:: convert:: TryFrom ;
@@ -71,43 +71,21 @@ unsafe extern "C" fn stub_fn(
7171 call_id : u32 ,
7272 values_vec : * mut i128 ,
7373) {
74- let mut instance = InstanceHandle :: from_vmctx ( vmctx) ;
75-
76- let ( args, returns_len) = {
77- let module = instance. module_ref ( ) ;
78- let signature = & module. signatures [ module. functions [ FuncIndex :: new ( call_id as usize ) ] ] ;
79-
80- let mut args = Vec :: new ( ) ;
81- for i in 2 ..signature. params . len ( ) {
82- args. push ( Val :: read_value_from (
83- values_vec. offset ( i as isize - 2 ) ,
84- signature. params [ i] . value_type ,
85- ) )
86- }
87- ( args, signature. returns . len ( ) )
88- } ;
89-
90- let mut returns = vec ! [ Val :: null( ) ; returns_len] ;
91- let state = & instance
92- . host_state ( )
93- . downcast_mut :: < TrampolineState > ( )
94- . expect ( "state" ) ;
95-
9674 // Be sure to `catch_unwind` here in case our callable panics, and if so we
9775 // need to manually carry the panic across the JIT frames back to the
9876 // original call-site of wasm code. Note that eventually we may be able to
9977 // JIT code such that native unwinding can unwind through those frames, but
10078 // for now it's just easier to always catch panics.
101- let result = panic:: catch_unwind ( AssertUnwindSafe ( || state. func . call ( & args, & mut returns) ) ) ;
79+ //
80+ // Also note that there are intentionally no local variables on this stack
81+ // frame. The reason for that is that some of the "raise" functions we have
82+ // below will trigger a longjmp, which won't run local destructors if we
83+ // have any. To prevent leaks we avoid having any local destructors by
84+ // avoiding local variables.
85+ let result = panic:: catch_unwind ( AssertUnwindSafe ( || call_stub ( vmctx, call_id, values_vec) ) ) ;
86+
10287 match result {
103- // On success we write out all the results into the return pointer that
104- // we were given.
105- Ok ( Ok ( ( ) ) ) => {
106- for ( i, r#return) in returns. iter_mut ( ) . enumerate ( ) {
107- // TODO check signature.returns[i].value_type ?
108- r#return. write_value_to ( values_vec. add ( i) ) ;
109- }
110- }
88+ Ok ( Ok ( ( ) ) ) => { }
11189
11290 // If a trap was raised (an error returned from the imported function)
11391 // then we smuggle the trap through `Box<dyn Error>` through to the
@@ -121,6 +99,40 @@ unsafe extern "C" fn stub_fn(
12199 // platforms.
122100 Err ( panic) => wasmtime_runtime:: resume_panic ( panic) ,
123101 }
102+
103+ unsafe fn call_stub (
104+ vmctx : * mut VMContext ,
105+ call_id : u32 ,
106+ values_vec : * mut i128 ,
107+ ) -> Result < ( ) , Trap > {
108+ let mut instance = InstanceHandle :: from_vmctx ( vmctx) ;
109+
110+ let ( args, returns_len) = {
111+ let module = instance. module_ref ( ) ;
112+ let signature = & module. signatures [ module. functions [ FuncIndex :: new ( call_id as usize ) ] ] ;
113+
114+ let mut args = Vec :: new ( ) ;
115+ for i in 2 ..signature. params . len ( ) {
116+ args. push ( Val :: read_value_from (
117+ values_vec. offset ( i as isize - 2 ) ,
118+ signature. params [ i] . value_type ,
119+ ) )
120+ }
121+ ( args, signature. returns . len ( ) )
122+ } ;
123+
124+ let mut returns = vec ! [ Val :: null( ) ; returns_len] ;
125+ let state = & instance
126+ . host_state ( )
127+ . downcast_mut :: < TrampolineState > ( )
128+ . expect ( "state" ) ;
129+ state. func . call ( & args, & mut returns) ?;
130+ for ( i, r#return) in returns. iter_mut ( ) . enumerate ( ) {
131+ // TODO check signature.returns[i].value_type ?
132+ r#return. write_value_to ( values_vec. add ( i) ) ;
133+ }
134+ Ok ( ( ) )
135+ }
124136}
125137
126138/// Create a trampoline for invoking a Callable.
0 commit comments