Fail with Trap in Instance::new() instead of Error (#683)

This commit is contained in:
Yury Delendik
2019-12-30 16:25:16 -06:00
committed by GitHub
parent 51f3ac0c45
commit 681445b18b
18 changed files with 172 additions and 86 deletions

View File

@@ -7,7 +7,7 @@ use wasmtime::*;
struct HelloCallback; struct HelloCallback;
impl Callable for HelloCallback { impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
println!("Calling back..."); println!("Calling back...");
println!("> Hello World!"); println!("> Hello World!");
Ok(()) Ok(())

View File

@@ -7,7 +7,7 @@ use wasmtime::*;
struct Callback; struct Callback;
impl Callable for Callback { impl Callable for Callback {
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), Trap> {
println!("Calling back..."); println!("Calling back...");
println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64()); println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64());

View File

@@ -1,7 +1,7 @@
use crate::r#ref::HostRef; use crate::r#ref::HostRef;
use crate::runtime::Store; use crate::runtime::Store;
use crate::trampoline::{generate_func_export, take_api_trap}; use crate::trampoline::{generate_func_export, take_api_trap};
use crate::trap::Trap; use crate::trap::{Trap, TrapInfo};
use crate::types::FuncType; use crate::types::FuncType;
use crate::values::Val; use crate::values::Val;
use std::rc::Rc; use std::rc::Rc;
@@ -18,7 +18,7 @@ use wasmtime_runtime::Export;
/// struct TimesTwo; /// struct TimesTwo;
/// ///
/// impl wasmtime::Callable for TimesTwo { /// impl wasmtime::Callable for TimesTwo {
/// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<wasmtime::Trap>> { /// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), wasmtime::Trap> {
/// let mut value = params[0].unwrap_i32(); /// let mut value = params[0].unwrap_i32();
/// value *= 2; /// value *= 2;
/// results[0] = value.into(); /// results[0] = value.into();
@@ -75,7 +75,7 @@ use wasmtime_runtime::Export;
/// let results = run_function /// let results = run_function
/// .borrow() /// .borrow()
/// .call(&[original.into()]) /// .call(&[original.into()])
/// .map_err(|trap| trap.borrow().to_string())?; /// .map_err(|trap| trap.to_string())?;
/// ///
/// // Compare that the results returned matches what we expect. /// // Compare that the results returned matches what we expect.
/// assert_eq!(original * 2, results[0].unwrap_i32()); /// assert_eq!(original * 2, results[0].unwrap_i32());
@@ -87,11 +87,11 @@ pub trait Callable {
/// `params` is an immutable list of parameters provided to the function. /// `params` is an immutable list of parameters provided to the function.
/// `results` is mutable list of results to be potentially set by your /// `results` is mutable list of results to be potentially set by your
/// function. Produces a `Trap` if the function encounters any errors. /// function. Produces a `Trap` if the function encounters any errors.
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>; fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
} }
pub(crate) trait WrappedCallable { pub(crate) trait WrappedCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>; fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
fn signature(&self) -> &ir::Signature { fn signature(&self) -> &ir::Signature {
match self.wasmtime_export() { match self.wasmtime_export() {
Export::Function { signature, .. } => signature, Export::Function { signature, .. } => signature,
@@ -119,7 +119,7 @@ impl WasmtimeFn {
} }
impl WrappedCallable for WasmtimeFn { impl WrappedCallable for WasmtimeFn {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
use std::cmp::max; use std::cmp::max;
use std::mem; use std::mem;
@@ -150,7 +150,7 @@ impl WrappedCallable for WasmtimeFn {
.context() .context()
.compiler() .compiler()
.get_published_trampoline(body, &signature, value_size) .get_published_trampoline(body, &signature, value_size)
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?; .map_err(|e| Trap::new(format!("trampoline error: {:?}", e)))?;
// Call the trampoline. // Call the trampoline.
if let Err(message) = unsafe { if let Err(message) = unsafe {
@@ -160,8 +160,9 @@ impl WrappedCallable for WasmtimeFn {
values_vec.as_mut_ptr() as *mut u8, values_vec.as_mut_ptr() as *mut u8,
) )
} { } {
let trap = take_api_trap().unwrap_or_else(|| HostRef::new(Trap::new(message))); let trap = take_api_trap()
return Err(trap); .unwrap_or_else(|| HostRef::new(TrapInfo::new(format!("call error: {}", message))));
return Err(trap.into());
} }
// Load the return values out of `values_vec`. // Load the return values out of `values_vec`.
@@ -206,7 +207,7 @@ impl NativeCallable {
} }
impl WrappedCallable for NativeCallable { impl WrappedCallable for NativeCallable {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
self.callable.call(params, results) self.callable.call(params, results)
} }
fn wasmtime_handle(&self) -> &InstanceHandle { fn wasmtime_handle(&self) -> &InstanceHandle {

View File

@@ -147,7 +147,7 @@ impl Func {
self.r#type.results().len() self.r#type.results().len()
} }
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, HostRef<Trap>> { pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
let mut results = vec![Val::null(); self.result_arity()]; let mut results = vec![Val::null(); self.result_arity()];
self.callable.call(params, &mut results)?; self.callable.call(params, &mut results)?;
Ok(results.into_boxed_slice()) Ok(results.into_boxed_slice())

View File

@@ -4,8 +4,9 @@ use crate::module::Module;
use crate::r#ref::HostRef; use crate::r#ref::HostRef;
use crate::runtime::Store; use crate::runtime::Store;
use crate::trampoline::take_api_trap; use crate::trampoline::take_api_trap;
use crate::trap::Trap;
use crate::types::{ExportType, ExternType}; use crate::types::{ExportType, ExternType};
use anyhow::Result; use anyhow::{Error, Result};
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::rc::Rc; use std::rc::Rc;
@@ -31,7 +32,7 @@ pub fn instantiate_in_context(
imports: Vec<(String, String, Extern)>, imports: Vec<(String, String, Extern)>,
mut context: Context, mut context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>, exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>)> { ) -> Result<(InstanceHandle, HashSet<Context>), Error> {
let mut contexts = HashSet::new(); let mut contexts = HashSet::new();
let debug_info = context.debug_info(); let debug_info = context.debug_info();
let mut resolver = SimpleResolver { imports }; let mut resolver = SimpleResolver { imports };
@@ -42,10 +43,12 @@ pub fn instantiate_in_context(
exports, exports,
debug_info, debug_info,
) )
.map_err(|e| { .map_err(|e| -> Error {
// TODO wrap HostRef<Trap> into Error if let Some(trap) = take_api_trap() {
drop(take_api_trap()); Trap::from(trap).into()
e } else {
e.into()
}
})?; })?;
contexts.insert(context); contexts.insert(context);
Ok((instance, contexts)) Ok((instance, contexts))
@@ -68,7 +71,7 @@ impl Instance {
store: &HostRef<Store>, store: &HostRef<Store>,
module: &HostRef<Module>, module: &HostRef<Module>,
externs: &[Extern], externs: &[Extern],
) -> Result<Instance> { ) -> Result<Instance, Error> {
let context = store.borrow_mut().context().clone(); let context = store.borrow_mut().context().clone();
let exports = store.borrow_mut().global_exports().clone(); let exports = store.borrow_mut().global_exports().clone();
let imports = module let imports = module

View File

@@ -28,6 +28,6 @@ pub use crate::instance::Instance;
pub use crate::module::Module; pub use crate::module::Module;
pub use crate::r#ref::{AnyRef, HostInfo, HostRef}; pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
pub use crate::runtime::{Config, Engine, Store}; pub use crate::runtime::{Config, Engine, Store};
pub use crate::trap::Trap; pub use crate::trap::{FrameInfo, Trap, TrapInfo};
pub use crate::types::*; pub use crate::types::*;
pub use crate::values::*; pub use crate::values::*;

View File

@@ -96,6 +96,7 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *m
0 0
} }
Err(trap) => { Err(trap) => {
let trap = trap.trap_info_unchecked();
record_api_trap(trap); record_api_trap(trap);
1 1
} }

View File

@@ -1,7 +1,7 @@
use std::cell::Cell; use std::cell::Cell;
use crate::r#ref::HostRef; use crate::r#ref::HostRef;
use crate::Trap; use crate::TrapInfo;
use wasmtime_environ::ir::{SourceLoc, TrapCode}; use wasmtime_environ::ir::{SourceLoc, TrapCode};
use wasmtime_environ::TrapInformation; use wasmtime_environ::TrapInformation;
use wasmtime_jit::trampoline::binemit; use wasmtime_jit::trampoline::binemit;
@@ -10,10 +10,10 @@ use wasmtime_jit::trampoline::binemit;
pub const API_TRAP_CODE: TrapCode = TrapCode::User(13); pub const API_TRAP_CODE: TrapCode = TrapCode::User(13);
thread_local! { thread_local! {
static RECORDED_API_TRAP: Cell<Option<HostRef<Trap>>> = Cell::new(None); static RECORDED_API_TRAP: Cell<Option<HostRef<TrapInfo>>> = Cell::new(None);
} }
pub fn record_api_trap(trap: HostRef<Trap>) { pub fn record_api_trap(trap: HostRef<TrapInfo>) {
RECORDED_API_TRAP.with(|data| { RECORDED_API_TRAP.with(|data| {
let trap = Cell::new(Some(trap)); let trap = Cell::new(Some(trap));
data.swap(&trap); data.swap(&trap);
@@ -24,7 +24,7 @@ pub fn record_api_trap(trap: HostRef<Trap>) {
}); });
} }
pub fn take_api_trap() -> Option<HostRef<Trap>> { pub fn take_api_trap() -> Option<HostRef<TrapInfo>> {
RECORDED_API_TRAP.with(|data| data.take()) RECORDED_API_TRAP.with(|data| data.take())
} }

View File

@@ -1,11 +1,88 @@
use crate::instance::Instance;
use crate::r#ref::HostRef;
use std::fmt;
use std::sync::{Arc, Mutex};
use thiserror::Error; use thiserror::Error;
#[derive(Debug)]
pub struct FrameInfo;
impl FrameInfo {
pub fn instance(&self) -> *const Instance {
unimplemented!("FrameInfo::instance");
}
pub fn func_index() -> usize {
unimplemented!("FrameInfo::func_index");
}
pub fn func_offset() -> usize {
unimplemented!("FrameInfo::func_offset");
}
pub fn module_offset() -> usize {
unimplemented!("FrameInfo::module_offset");
}
}
#[derive(Debug)]
pub struct TrapInfo {
message: String,
trace: Vec<FrameInfo>,
}
impl TrapInfo {
pub fn new<I: Into<String>>(message: I) -> Self {
Self {
message: message.into(),
trace: vec![],
}
}
/// Returns a reference the `message` stored in `Trap`.
pub fn message(&self) -> &str {
&self.message
}
pub fn origin(&self) -> Option<&FrameInfo> {
self.trace.first()
}
pub fn trace(&self) -> &[FrameInfo] {
&self.trace
}
}
/// A struct to hold unsafe TrapInfo host reference, designed
/// to be Send-able. The only access for it provided via the
/// Trap::trap_info_unchecked() method.
struct UnsafeTrapInfo(HostRef<TrapInfo>);
impl UnsafeTrapInfo {
fn trap_info(&self) -> HostRef<TrapInfo> {
self.0.clone()
}
}
unsafe impl Send for UnsafeTrapInfo {}
impl fmt::Debug for UnsafeTrapInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UnsafeTrapInfo")
}
}
/// A struct representing an aborted instruction execution, with a message /// A struct representing an aborted instruction execution, with a message
/// indicating the cause. /// indicating the cause.
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("Wasm trap: {message}")] #[error("Wasm trap: {message}")]
pub struct Trap { pub struct Trap {
message: String, message: String,
info: Arc<Mutex<UnsafeTrapInfo>>,
}
fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) {
(t, t)
} }
impl Trap { impl Trap {
@@ -15,20 +92,26 @@ impl Trap {
/// let trap = wasmtime::Trap::new("unexpected error"); /// let trap = wasmtime::Trap::new("unexpected error");
/// assert_eq!("unexpected error", trap.message()); /// assert_eq!("unexpected error", trap.message());
/// ``` /// ```
pub fn new<I: Into<String>>(message: I) -> Trap { pub fn new<I: Into<String>>(message: I) -> Self {
Self { Trap::from(HostRef::new(TrapInfo::new(message)))
message: message.into(),
}
}
/// Create a `Trap` without defining a message for the trap. Mostly useful
/// for prototypes and tests.
pub fn fake() -> Trap {
Self::new("TODO trap")
} }
/// Returns a reference the `message` stored in `Trap`. /// Returns a reference the `message` stored in `Trap`.
pub fn message(&self) -> &str { pub fn message(&self) -> &str {
&self.message &self.message
} }
/// Returns inner TrapInfo assotiated with the Trap.
/// The method is unsafe: obtained TrapInfo is not thread safe.
pub(crate) unsafe fn trap_info_unchecked(&self) -> HostRef<TrapInfo> {
self.info.lock().unwrap().trap_info()
}
}
impl From<HostRef<TrapInfo>> for Trap {
fn from(trap_info: HostRef<TrapInfo>) -> Self {
let message = trap_info.borrow().message().to_string();
let info = Arc::new(Mutex::new(UnsafeTrapInfo(trap_info)));
Trap { message, info }
}
} }

View File

@@ -8,7 +8,7 @@
use super::{ use super::{
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType, AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
TableType, Trap, Val, ValType, TableType, Trap, TrapInfo, Val, ValType,
}; };
use std::rc::Rc; use std::rc::Rc;
use std::{mem, ptr, slice}; use std::{mem, ptr, slice};
@@ -317,7 +317,7 @@ pub type wasm_message_t = wasm_name_t;
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
pub struct wasm_trap_t { pub struct wasm_trap_t {
trap: HostRef<Trap>, trap_info: HostRef<TrapInfo>,
} }
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
@@ -469,7 +469,8 @@ pub unsafe extern "C" fn wasm_func_call(
ptr::null_mut() ptr::null_mut()
} }
Err(trap) => { Err(trap) => {
let trap = Box::new(wasm_trap_t { trap }); let trap_info = trap.trap_info_unchecked();
let trap = Box::new(wasm_trap_t { trap_info });
Box::into_raw(trap) Box::into_raw(trap)
} }
} }
@@ -539,7 +540,7 @@ impl wasm_val_t {
} }
impl Callable for wasm_func_callback_t { impl Callable for wasm_func_callback_t {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
let params = params let params = params
.iter() .iter()
.map(|p| wasm_val_t::from_val(p)) .map(|p| wasm_val_t::from_val(p))
@@ -549,7 +550,8 @@ impl Callable for wasm_func_callback_t {
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) }; let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
if !out.is_null() { if !out.is_null() {
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) }; let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
return Err((*trap).into()); let trap_info: HostRef<TrapInfo> = (*trap).into();
return Err(Trap::from(trap_info));
} }
for i in 0..results.len() { for i in 0..results.len() {
results[i] = out_results[i].val(); results[i] = out_results[i].val();
@@ -558,9 +560,9 @@ impl Callable for wasm_func_callback_t {
} }
} }
impl Into<HostRef<Trap>> for wasm_trap_t { impl Into<HostRef<TrapInfo>> for wasm_trap_t {
fn into(self) -> HostRef<Trap> { fn into(self) -> HostRef<TrapInfo> {
self.trap self.trap_info
} }
} }
@@ -571,7 +573,7 @@ struct CallbackWithEnv {
} }
impl Callable for CallbackWithEnv { impl Callable for CallbackWithEnv {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
let params = params let params = params
.iter() .iter()
.map(|p| wasm_val_t::from_val(p)) .map(|p| wasm_val_t::from_val(p))
@@ -581,7 +583,8 @@ impl Callable for CallbackWithEnv {
let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) }; let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) };
if !out.is_null() { if !out.is_null() {
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) }; let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
return Err((*trap).into()); let trap_info: HostRef<TrapInfo> = (*trap).into();
return Err(Trap::from(trap_info));
} }
for i in 0..results.len() { for i in 0..results.len() {
results[i] = out_results[i].val(); results[i] = out_results[i].val();
@@ -677,12 +680,13 @@ pub unsafe extern "C" fn wasm_instance_new(
} }
Box::into_raw(instance) Box::into_raw(instance)
} }
Err(_) => { Err(trap) => {
if !result.is_null() { if !result.is_null() {
// TODO Unwrap trap from error let trap_info = match trap.downcast::<Trap>() {
let trap = Box::new(wasm_trap_t { Ok(trap) => trap.trap_info_unchecked(),
trap: HostRef::new(Trap::new("trap during instantiation".to_string())), Err(_) => HostRef::new(TrapInfo::new("instance error".to_string())),
}); };
let trap = Box::new(wasm_trap_t { trap_info });
(*result) = Box::into_raw(trap); (*result) = Box::into_raw(trap);
} }
ptr::null_mut() ptr::null_mut()
@@ -925,7 +929,7 @@ pub unsafe extern "C" fn wasm_trap_new(
} }
let message = String::from_utf8_lossy(message).to_string(); let message = String::from_utf8_lossy(message).to_string();
let trap = Box::new(wasm_trap_t { let trap = Box::new(wasm_trap_t {
trap: HostRef::new(Trap::new(message)), trap_info: HostRef::new(TrapInfo::new(message)),
}); });
Box::into_raw(trap) Box::into_raw(trap)
} }
@@ -933,7 +937,7 @@ pub unsafe extern "C" fn wasm_trap_new(
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) { pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
buffer.extend_from_slice((*trap).trap.borrow().message().as_bytes()); buffer.extend_from_slice((*trap).trap_info.borrow().message().as_bytes());
buffer.reserve_exact(1); buffer.reserve_exact(1);
buffer.push(0); buffer.push(0);
(*out).set_buffer(buffer); (*out).set_buffer(buffer);

View File

@@ -20,7 +20,7 @@ fn test_import_calling_export() {
} }
impl Callable for Callback { impl Callable for Callback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
self.other self.other
.borrow() .borrow()
.as_ref() .as_ref()

View File

@@ -7,8 +7,8 @@ fn test_trap_return() -> Result<(), String> {
struct HelloCallback; struct HelloCallback;
impl Callable for HelloCallback { impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
Err(HostRef::new(Trap::new("test 123"))) Err(Trap::new("test 123"))
} }
} }
@@ -32,7 +32,7 @@ fn test_trap_return() -> Result<(), String> {
let imports = vec![hello_func.into()]; let imports = vec![hello_func.into()];
let instance = Instance::new(&store, &module, imports.as_slice()) let instance = Instance::new(&store, &module, imports.as_slice())
.map_err(|e| format!("failed to instantiate module: {}", e))?; .map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
.expect("expected function export"); .expect("expected function export");
@@ -43,7 +43,7 @@ fn test_trap_return() -> Result<(), String> {
.err() .err()
.expect("error calling function"); .expect("error calling function");
assert_eq!(e.borrow().message(), "test 123"); assert_eq!(e.message(), "test 123");
Ok(()) Ok(())
} }

View File

@@ -10,7 +10,7 @@ use wasmtime::{
pub fn dummy_imports( pub fn dummy_imports(
store: &HostRef<Store>, store: &HostRef<Store>,
import_tys: &[ImportType], import_tys: &[ImportType],
) -> Result<Vec<Extern>, HostRef<Trap>> { ) -> Result<Vec<Extern>, Trap> {
let mut imports = Vec::with_capacity(import_tys.len()); let mut imports = Vec::with_capacity(import_tys.len());
for imp in import_tys { for imp in import_tys {
imports.push(match imp.ty() { imports.push(match imp.ty() {
@@ -45,7 +45,7 @@ impl DummyFunc {
} }
impl Callable for DummyFunc { impl Callable for DummyFunc {
fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
for (ret_ty, result) in self.0.results().iter().zip(results) { for (ret_ty, result) in self.0.results().iter().zip(results) {
*result = dummy_value(ret_ty)?; *result = dummy_value(ret_ty)?;
} }
@@ -55,38 +55,38 @@ impl Callable for DummyFunc {
} }
/// Construct a dummy value for the given value type. /// Construct a dummy value for the given value type.
pub fn dummy_value(val_ty: &ValType) -> Result<Val, HostRef<Trap>> { pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
Ok(match val_ty { Ok(match val_ty {
ValType::I32 => Val::I32(0), ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0), ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0), ValType::F32 => Val::F32(0),
ValType::F64 => Val::F64(0), ValType::F64 => Val::F64(0),
ValType::V128 => { ValType::V128 => {
return Err(HostRef::new(Trap::new( return Err(Trap::new(
"dummy_value: unsupported function return type: v128".to_string(), "dummy_value: unsupported function return type: v128".to_string(),
))) ))
} }
ValType::AnyRef => { ValType::AnyRef => {
return Err(HostRef::new(Trap::new( return Err(Trap::new(
"dummy_value: unsupported function return type: anyref".to_string(), "dummy_value: unsupported function return type: anyref".to_string(),
))) ))
} }
ValType::FuncRef => { ValType::FuncRef => {
return Err(HostRef::new(Trap::new( return Err(Trap::new(
"dummy_value: unsupported function return type: funcref".to_string(), "dummy_value: unsupported function return type: funcref".to_string(),
))) ))
} }
}) })
} }
/// Construct a dummy global for the given global type. /// Construct a dummy global for the given global type.
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, HostRef<Trap>> { pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, Trap> {
let val = dummy_value(ty.content())?; let val = dummy_value(ty.content())?;
Ok(Global::new(store, ty, val)) Ok(Global::new(store, ty, val))
} }
/// Construct a dummy table for the given table type. /// Construct a dummy table for the given table type.
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, HostRef<Trap>> { pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, Trap> {
let init_val = dummy_value(&ty.element())?; let init_val = dummy_value(&ty.element())?;
Ok(Table::new(store, ty, init_val)) Ok(Table::new(store, ty, init_val))
} }

View File

@@ -82,7 +82,7 @@ impl wasmtime::Callable for WrappedFn {
&self, &self,
params: &[wasmtime::Val], params: &[wasmtime::Val],
returns: &mut [wasmtime::Val], returns: &mut [wasmtime::Val],
) -> Result<(), wasmtime::HostRef<wasmtime::Trap>> { ) -> Result<(), wasmtime::Trap> {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();

View File

@@ -91,7 +91,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
.borrow() .borrow()
.call(&[]) .call(&[])
{ {
bail!("trapped: {:?}", trap.borrow()); bail!("trapped: {:?}", trap);
} }
Ok(()) Ok(())

View File

@@ -9,9 +9,9 @@ struct MyCall<F>(F);
impl<F> Callable for MyCall<F> impl<F> Callable for MyCall<F>
where where
F: Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>>, F: Fn(&[Val], &mut [Val]) -> Result<(), Trap>,
{ {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> { fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
(self.0)(params, results) (self.0)(params, results)
} }
} }
@@ -19,7 +19,7 @@ where
fn wrap( fn wrap(
store: &HostRef<Store>, store: &HostRef<Store>,
ty: FuncType, ty: FuncType,
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>> + 'static, callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
) -> Func { ) -> Func {
Func::new(store, ty, Rc::new(MyCall(callable))) Func::new(store, ty, Rc::new(MyCall(callable)))
} }

View File

@@ -36,7 +36,7 @@ pub struct WastContext {
enum Outcome<T = Vec<Val>> { enum Outcome<T = Vec<Val>> {
Ok(T), Ok(T),
Trap(HostRef<Trap>), Trap(Trap),
} }
impl WastContext { impl WastContext {
@@ -101,7 +101,7 @@ impl WastContext {
.filter_map(|e| e.downcast_ref::<InstantiationError>()) .filter_map(|e| e.downcast_ref::<InstantiationError>())
.next(); .next();
if let Some(InstantiationError::StartTrap(msg)) = err { if let Some(InstantiationError::StartTrap(msg)) = err {
return Ok(Outcome::Trap(HostRef::new(Trap::new(msg.clone())))); return Ok(Outcome::Trap(Trap::new(msg.clone())));
} }
return Err(e); return Err(e);
} }
@@ -139,7 +139,7 @@ impl WastContext {
fn module(&mut self, instance_name: Option<&str>, module: &[u8]) -> Result<()> { fn module(&mut self, instance_name: Option<&str>, module: &[u8]) -> Result<()> {
let instance = match self.instantiate(module)? { let instance = match self.instantiate(module)? {
Outcome::Ok(i) => i, Outcome::Ok(i) => i,
Outcome::Trap(e) => bail!("instantiation failed with: {}", e.borrow().message()), Outcome::Trap(e) => bail!("instantiation failed with: {}", e.message()),
}; };
if let Some(name) = instance_name { if let Some(name) = instance_name {
self.instances.insert(name.to_string(), instance.clone()); self.instances.insert(name.to_string(), instance.clone());
@@ -241,7 +241,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
}, },
@@ -254,7 +253,6 @@ impl WastContext {
bail!("{}\nexpected trap, got {:?}", context(span), values) bail!("{}\nexpected trap, got {:?}", context(span), values)
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
if t.message().contains(message) { if t.message().contains(message) {
continue; continue;
} }
@@ -283,7 +281,6 @@ impl WastContext {
bail!("{}\nexpected trap, got {:?}", context(span), values) bail!("{}\nexpected trap, got {:?}", context(span), values)
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
if t.message().contains(message) { if t.message().contains(message) {
continue; continue;
} }
@@ -315,7 +312,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }
@@ -340,7 +336,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }
@@ -365,7 +360,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }
@@ -390,7 +384,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }
@@ -415,7 +408,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }
@@ -440,7 +432,6 @@ impl WastContext {
} }
} }
Outcome::Trap(t) => { Outcome::Trap(t) => {
let t = t.borrow();
bail!("{}\nunexpected trap: {}", context(span), t.message()) bail!("{}\nunexpected trap: {}", context(span), t.message())
} }
} }

View File

@@ -349,7 +349,10 @@ fn instantiate_module(
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let instance = HostRef::new(Instance::new(store, &module, &imports)?); let instance = HostRef::new(match Instance::new(store, &module, &imports) {
Ok(instance) => instance,
Err(trap) => bail!("Failed to instantiate {:?}: {:?}", path, trap),
});
Ok((instance, module, data)) Ok((instance, module, data))
} }