diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs
index 11f93342e..44076aca7 100644
--- a/lib/clif-backend/src/module.rs
+++ b/lib/clif-backend/src/module.rs
@@ -73,16 +73,15 @@ impl Module {
             handler_data.clone(),
         )?;
 
-        let protected_caller = Caller::new(&self.info, handler_data, trampolines);
-
         let cache_gen = Box::new(CacheGenerator::new(
             backend_cache,
             Arc::clone(&func_resolver.memory),
         ));
 
+        let runnable_module = Caller::new(&self.info, handler_data, trampolines, func_resolver);
+
         Ok(ModuleInner {
-            func_resolver: Box::new(func_resolver),
-            protected_caller: Box::new(protected_caller),
+            runnable_module: Box::new(runnable_module),
             cache_gen,
 
             info: self.info,
@@ -103,16 +102,15 @@ impl Module {
             )
             .map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;
 
-        let protected_caller = Caller::new(&info, handler_data, trampolines);
-
         let cache_gen = Box::new(CacheGenerator::new(
             backend_cache,
             Arc::clone(&func_resolver.memory),
         ));
 
+        let runnable_module = Caller::new(&info, handler_data, trampolines, func_resolver);
+
         Ok(ModuleInner {
-            func_resolver: Box::new(func_resolver),
-            protected_caller: Box::new(protected_caller),
+            runnable_module: Box::new(runnable_module),
             cache_gen,
 
             info,
diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs
index e2706b6e1..6e5623f25 100644
--- a/lib/clif-backend/src/resolver.rs
+++ b/lib/clif-backend/src/resolver.rs
@@ -357,13 +357,8 @@ pub struct FuncResolver {
     pub(crate) memory: Arc<Memory>,
 }
 
-// Implements FuncResolver trait.
-impl backend::FuncResolver for FuncResolver {
-    fn get(
-        &self,
-        _module: &wasmer_runtime_core::module::ModuleInner,
-        index: LocalFuncIndex,
-    ) -> Option<NonNull<vm::Func>> {
+impl FuncResolver {
+    pub fn lookup(&self, index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
         lookup_func(&self.map, &self.memory, index)
     }
 }
diff --git a/lib/clif-backend/src/signal/mod.rs b/lib/clif-backend/src/signal/mod.rs
index 766ad75fb..66d347c21 100644
--- a/lib/clif-backend/src/signal/mod.rs
+++ b/lib/clif-backend/src/signal/mod.rs
@@ -1,15 +1,15 @@
 use crate::relocation::{TrapData, TrapSink};
+use crate::resolver::FuncResolver;
 use crate::trampoline::Trampolines;
 use hashbrown::HashSet;
 use libc::c_void;
 use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
 use wasmer_runtime_core::{
-    backend::{ProtectedCaller, Token, UserTrapper},
-    error::RuntimeResult,
+    backend::{RunnableModule, UserTrapper},
     export::Context,
     module::{ExportIndex, ModuleInfo, ModuleInner},
     typed_func::{Wasm, WasmTrapInfo},
-    types::{FuncIndex, FuncSig, LocalOrImport, SigIndex, Type, Value},
+    types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value},
     vm::{self, ImportBacking},
 };
 
@@ -42,6 +42,7 @@ pub struct Caller {
     func_export_set: HashSet<FuncIndex>,
     handler_data: HandlerData,
     trampolines: Arc<Trampolines>,
+    resolver: FuncResolver,
 }
 
 impl Caller {
@@ -49,6 +50,7 @@ impl Caller {
         module: &ModuleInfo,
         handler_data: HandlerData,
         trampolines: Arc<Trampolines>,
+        resolver: FuncResolver,
     ) -> Self {
         let mut func_export_set = HashSet::new();
         for export_index in module.exports.values() {
@@ -64,92 +66,17 @@ impl Caller {
             func_export_set,
             handler_data,
             trampolines,
+            resolver,
         }
     }
 }
 
-impl ProtectedCaller for Caller {
-    fn call(
-        &self,
-        module: &ModuleInner,
-        func_index: FuncIndex,
-        params: &[Value],
-        import_backing: &ImportBacking,
-        vmctx: *mut vm::Ctx,
-        _: Token,
-    ) -> RuntimeResult<Vec<Value>> {
-        let (func_ptr, ctx, signature, sig_index) =
-            get_func_from_index(&module, import_backing, func_index);
-
-        let vmctx_ptr = match ctx {
-            Context::External(external_vmctx) => external_vmctx,
-            Context::Internal => vmctx,
-        };
-
-        assert!(self.func_export_set.contains(&func_index));
-
-        assert!(
-            signature.returns().len() <= 1,
-            "multi-value returns not yet supported"
-        );
-
-        assert!(
-            signature.check_param_value_types(params),
-            "incorrect signature"
-        );
-
-        let param_vec: Vec<u64> = params
-            .iter()
-            .map(|val| match val {
-                Value::I32(x) => *x as u64,
-                Value::I64(x) => *x as u64,
-                Value::F32(x) => x.to_bits() as u64,
-                Value::F64(x) => x.to_bits(),
-            })
-            .collect();
-
-        let mut return_vec = vec![0; signature.returns().len()];
-
-        let trampoline = self
-            .trampolines
-            .lookup(sig_index)
-            .expect("that trampoline doesn't exist");
-
-        #[cfg(not(target_os = "windows"))]
-        call_protected(&self.handler_data, || unsafe {
-            // Leap of faith.
-            trampoline(
-                vmctx_ptr,
-                func_ptr,
-                param_vec.as_ptr(),
-                return_vec.as_mut_ptr(),
-            );
-        })?;
-
-        // the trampoline is called from C on windows
-        #[cfg(target_os = "windows")]
-        call_protected(
-            &self.handler_data,
-            trampoline,
-            vmctx_ptr,
-            func_ptr,
-            param_vec.as_ptr(),
-            return_vec.as_mut_ptr(),
-        )?;
-
-        Ok(return_vec
-            .iter()
-            .zip(signature.returns().iter())
-            .map(|(&x, ty)| match ty {
-                Type::I32 => Value::I32(x as i32),
-                Type::I64 => Value::I64(x as i64),
-                Type::F32 => Value::F32(f32::from_bits(x as u32)),
-                Type::F64 => Value::F64(f64::from_bits(x as u64)),
-            })
-            .collect())
+impl RunnableModule for Caller {
+    fn get_func(&self, _: &ModuleInfo, func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
+        self.resolver.lookup(func_index)
     }
 
-    fn get_wasm_trampoline(&self, module: &ModuleInner, sig_index: SigIndex) -> Option<Wasm> {
+    fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
         unsafe extern "C" fn invoke(
             trampoline: unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64),
             ctx: *mut vm::Ctx,
@@ -208,8 +135,8 @@ fn get_func_from_index<'a>(
     let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
         LocalOrImport::Local(local_func_index) => (
             module
-                .func_resolver
-                .get(&module, local_func_index)
+                .runnable_module
+                .get_func(&module.info, local_func_index)
                 .expect("broken invariant, func resolver not synced with module.exports")
                 .cast(),
             Context::Internal,