Remove WasmTrapInfo and passExceptionCode in the generic Box<Any> container.

This commit is contained in:
losfair
2020-02-06 23:49:50 +08:00
parent 2c44b700c8
commit e0aafbe9dd
18 changed files with 166 additions and 248 deletions

View File

@ -13,6 +13,7 @@ use crate::{
module::ModuleInfo,
sys::Memory,
};
use std::fmt;
use std::{any::Any, ptr::NonNull};
use std::collections::HashMap;
@ -158,13 +159,36 @@ impl ExceptionTable {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum ExceptionCode {
/// An `unreachable` opcode was executed.
Unreachable,
Unreachable = 0,
/// Call indirect incorrect signature trap.
IncorrectCallIndirectSignature = 1,
/// Memory out of bounds trap.
MemoryOutOfBounds = 2,
/// Call indirect out of bounds trap.
CallIndirectOOB = 3,
/// An arithmetic exception, e.g. divided by zero.
Arithmetic,
IllegalArithmetic = 4,
/// Misaligned atomic access trap.
MisalignedAtomicAccess = 5,
}
/// Memory access exception, e.g. misaligned/out-of-bound read/write.
Memory,
impl fmt::Display for ExceptionCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
ExceptionCode::Unreachable => "unreachable",
ExceptionCode::IncorrectCallIndirectSignature => {
"incorrect `call_indirect` signature"
}
ExceptionCode::MemoryOutOfBounds => "memory out-of-bounds access",
ExceptionCode::CallIndirectOOB => "`call_indirect` out-of-bounds",
ExceptionCode::IllegalArithmetic => "illegal arithmetic operation",
ExceptionCode::MisalignedAtomicAccess => "misaligned atomic access",
}
)
}
}
pub trait Compiler {

View File

@ -179,18 +179,7 @@ impl std::error::Error for LinkError {}
/// The main way to do this is `Instance.call`.
///
/// Comparing two `RuntimeError`s always evaluates to false.
pub enum RuntimeError {
/// Trap.
Trap {
/// Trap message.
msg: Box<str>,
},
/// Error.
Error {
/// Error data.
data: Box<dyn Any + Send>,
},
}
pub struct RuntimeError(pub Box<dyn Any + Send>);
impl PartialEq for RuntimeError {
fn eq(&self, _other: &RuntimeError) -> bool {
@ -200,21 +189,15 @@ impl PartialEq for RuntimeError {
impl std::fmt::Display for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
RuntimeError::Trap { ref msg } => {
write!(f, "WebAssembly trap occurred during runtime: {}", msg)
}
RuntimeError::Error { data } => {
if let Some(s) = data.downcast_ref::<String>() {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
write!(f, "\"{}\"", s)
} else if let Some(exc_code) = data.downcast_ref::<ExceptionCode>() {
write!(f, "Caught exception of type \"{:?}\".", exc_code)
} else {
write!(f, "unknown error")
}
}
let data = &*self.0;
if let Some(s) = data.downcast_ref::<String>() {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
write!(f, "\"{}\"", s)
} else if let Some(exc_code) = data.downcast_ref::<ExceptionCode>() {
write!(f, "Caught exception of type \"{:?}\".", exc_code)
} else {
write!(f, "unknown error")
}
}
}

View File

@ -13,7 +13,7 @@ use crate::{
sig_registry::SigRegistry,
structures::TypedIndex,
table::Table,
typed_func::{Func, Wasm, WasmTrapInfo, WasmTypeList},
typed_func::{Func, Wasm, WasmTypeList},
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Type, Value},
vm::{self, InternalField},
};
@ -673,8 +673,7 @@ pub(crate) fn call_func_with_index_inner(
} = wasm;
let run_wasm = |result_space: *mut u64| unsafe {
let mut trap_info = WasmTrapInfo::Unknown;
let mut user_error = None;
let mut error_out = None;
let success = invoke(
trampoline,
@ -682,21 +681,16 @@ pub(crate) fn call_func_with_index_inner(
func_ptr,
raw_args.as_ptr(),
result_space,
&mut trap_info,
&mut user_error,
&mut error_out,
invoke_env,
);
if success {
Ok(())
} else {
if let Some(data) = user_error {
Err(RuntimeError::Error { data })
} else {
Err(RuntimeError::Trap {
msg: trap_info.to_string().into(),
})
}
Err(error_out
.map(RuntimeError)
.unwrap_or_else(|| RuntimeError(Box::new("invoke(): Unknown error".to_string()))))
}
};

View File

@ -11,52 +11,12 @@ use std::{
any::Any,
convert::Infallible,
ffi::c_void,
fmt,
marker::PhantomData,
mem, panic,
ptr::{self, NonNull},
sync::Arc,
};
/// Wasm trap info.
#[repr(C)]
pub enum WasmTrapInfo {
/// Unreachable trap.
Unreachable = 0,
/// Call indirect incorrect signature trap.
IncorrectCallIndirectSignature = 1,
/// Memory out of bounds trap.
MemoryOutOfBounds = 2,
/// Call indirect out of bounds trap.
CallIndirectOOB = 3,
/// Illegal arithmetic trap.
IllegalArithmetic = 4,
/// Misaligned atomic access trap.
MisalignedAtomicAccess = 5,
/// Unknown trap.
Unknown,
}
impl fmt::Display for WasmTrapInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
WasmTrapInfo::Unreachable => "unreachable",
WasmTrapInfo::IncorrectCallIndirectSignature => {
"incorrect `call_indirect` signature"
}
WasmTrapInfo::MemoryOutOfBounds => "memory out-of-bounds access",
WasmTrapInfo::CallIndirectOOB => "`call_indirect` out-of-bounds",
WasmTrapInfo::IllegalArithmetic => "illegal arithmetic operation",
WasmTrapInfo::MisalignedAtomicAccess => "misaligned atomic access",
WasmTrapInfo::Unknown => "unknown",
}
)
}
}
/// This is just an empty trait to constrict that types that
/// can be put into the third/fourth (depending if you include lifetimes)
/// of the `Func` struct.
@ -77,8 +37,7 @@ pub type Invoke = unsafe extern "C" fn(
func: NonNull<vm::Func>,
args: *const u64,
rets: *mut u64,
trap_info: *mut WasmTrapInfo,
user_error: *mut Option<Box<dyn Any + Send>>,
error_out: *mut Option<Box<dyn Any + Send>>,
extra: Option<NonNull<c_void>>,
) -> bool;
@ -401,8 +360,7 @@ macro_rules! impl_traits {
let ( $( $x ),* ) = self;
let args = [ $( $x.to_native().to_binary()),* ];
let mut rets = Rets::empty_ret_array();
let mut trap = WasmTrapInfo::Unknown;
let mut user_error = None;
let mut error_out = None;
if (wasm.invoke)(
wasm.trampoline,
@ -410,17 +368,14 @@ macro_rules! impl_traits {
f,
args.as_ptr(),
rets.as_mut().as_mut_ptr(),
&mut trap,
&mut user_error,
&mut error_out,
wasm.invoke_env
) {
Ok(Rets::from_ret_array(rets))
} else {
if let Some(data) = user_error {
Err(RuntimeError::Error { data })
} else {
Err(RuntimeError::Trap { msg: trap.to_string().into() })
}
Err(error_out.map(RuntimeError).unwrap_or_else(|| {
RuntimeError(Box::new("invoke(): Unknown error".to_string()))
}))
}
}
}