From 197f2f859ee4b885a318ba42816c40b421803144 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 24 Apr 2020 14:30:14 -0700 Subject: [PATCH] Fix tests for the Cranelift backend --- lib/llvm-backend/cpp/object_loader.hh | 20 ++++++++++---------- lib/llvm-backend/src/backend.rs | 6 +++--- lib/llvm-backend/src/code.rs | 5 +++-- lib/runtime-core/src/error.rs | 17 ++++++++++++++++- lib/runtime-core/src/instance.rs | 24 +++++++++++------------- lib/runtime-core/src/typed_func.rs | 2 +- tests/high_level_api.rs | 2 +- tests/imports.rs | 14 +++++++------- tests/middleware_common.rs | 13 +++++++++---- 9 files changed, 61 insertions(+), 42 deletions(-) diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 53bd2b0df85..045502dd8d9 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -50,8 +50,8 @@ typedef struct { } callbacks_t; typedef struct { - size_t data, vtable; -} box_any_t; + size_t data; +} runtime_error_t; enum WasmTrapType { Unreachable = 0, @@ -121,7 +121,7 @@ private: struct WasmErrorSink { WasmTrapType *trap_out; - box_any_t *user_error; + runtime_error_t *user_error; }; struct WasmException : std::exception { @@ -149,14 +149,14 @@ public: struct UserException : UncatchableException { public: - UserException(size_t data, size_t vtable) : error_data({data, vtable}) {} + UserException(size_t data) : error_data({data}) {} virtual std::string description() const noexcept override { return "user exception"; } - // The parts of a `Box`. - box_any_t error_data; + // The pointer to `RuntimeError`. + runtime_error_t error_data; virtual void write_error(WasmErrorSink &out) const noexcept override { *out.user_error = error_data; @@ -274,10 +274,10 @@ result_t module_load(const uint8_t *mem_ptr, size_t mem_size, void module_delete(WasmModule *module) { delete module; } -// Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust +// Throw a pointer that's assumed to be `*mut RuntimeError` on the rust // side. -[[noreturn]] void throw_any(size_t data, size_t vtable) { - unsafe_unwind(new UserException(data, vtable)); +[[noreturn]] void throw_runtime_error(size_t data) { + unsafe_unwind(new UserException(data)); } // Throw a pointer that's assumed to be codegen::BreakpointHandler on the @@ -288,7 +288,7 @@ void module_delete(WasmModule *module) { delete module; } bool cxx_invoke_trampoline(trampoline_t trampoline, void *ctx, void *func, void *params, void *results, WasmTrapType *trap_out, - box_any_t *user_error, void *invoke_env) noexcept { + runtime_error_t *user_error, void *invoke_env) noexcept { try { catch_unwind([trampoline, ctx, func, params, results]() { trampoline(ctx, func, params, results); diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index c3922b6bed9..16f80ac84c0 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -56,7 +56,8 @@ extern "C" { /// but this is cleaner, I think? #[cfg_attr(nightly, unwind(allowed))] #[allow(improper_ctypes)] - fn throw_runtime_error(data: RuntimeError) -> !; + // POINTER!!!!! TODOARINO + fn throw_runtime_error(data: *mut RuntimeError) -> !; #[allow(improper_ctypes)] fn cxx_invoke_trampoline( @@ -475,8 +476,7 @@ impl RunnableModule for LLVMBackend { } unsafe fn do_early_trap(&self, data: RuntimeError) -> ! { - // maybe need to box leak it? - throw_runtime_error(data) + throw_runtime_error(Box::into_raw(Box::new(data))) } } diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 554628e254b..0ed4f3ce0da 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -34,6 +34,7 @@ use std::{ use wasmer_runtime_core::{ backend::{CacheGen, CompilerConfig, Token}, cache::{Artifact, Error as CacheError}, + error::RuntimeError, codegen::*, memory::MemoryType, module::{ModuleInfo, ModuleInner}, @@ -940,11 +941,11 @@ pub struct CodegenError { // prevents unused function elimination. #[no_mangle] pub unsafe extern "C" fn callback_trampoline( - b: *mut Option>, + b: *mut Option, callback: *mut BreakpointHandler, ) { let callback = Box::from_raw(callback); - let result: Result<(), Box> = + let result: Result<(), RuntimeError> = callback(BreakpointInfo { fault: None }); match result { Ok(()) => *b = None, diff --git a/lib/runtime-core/src/error.rs b/lib/runtime-core/src/error.rs index b501c6067ad..44c12ad6eaf 100644 --- a/lib/runtime-core/src/error.rs +++ b/lib/runtime-core/src/error.rs @@ -265,10 +265,25 @@ pub enum InvokeError { /// extra TODO: investigate if this can be a `Box` instead (looks like probably no) /// TODO: EarlyTrap(Box), - /// Indicates an error that ocurred related to breakpoints. (currently Singlepass only) + /// Indicates an error that ocurred related to breakpoints. Breakpoint(Box), } +impl From for RuntimeError { + fn from(other: InvokeError) -> RuntimeError { + match other { + InvokeError::EarlyTrap(re) | InvokeError::Breakpoint(re) => *re, + _ => RuntimeError::InvokeError(other), + } + } +} + +impl PartialEq for RuntimeError { + fn eq(&self, _other: &RuntimeError) -> bool { + false + } +} + //impl std::error::Error for InvokeError {} impl std::error::Error for RuntimeError {} diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 7dd176b657c..274904fb346 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -5,7 +5,7 @@ use crate::{ backend::RunnableModule, backing::{ImportBacking, LocalBacking}, - error::{CallResult, InvokeError, ResolveError, ResolveResult, Result, RuntimeError}, + error::{CallResult, ResolveError, ResolveResult, Result, RuntimeError, InvokeError}, export::{Context, Export, ExportIter, Exportable, FuncPointer}, global::Global, import::{ImportObject, LikeNamespace}, @@ -587,23 +587,21 @@ pub(crate) fn call_func_with_index_inner( let run_wasm = |result_space: *mut u64| -> CallResult<()> { let mut error_out = None; - let success = unsafe { - invoke( - trampoline, - ctx_ptr, - func_ptr, - raw_args.as_ptr(), - result_space, - &mut error_out, - invoke_env, - ) - }; + let success = unsafe { invoke( + trampoline, + ctx_ptr, + func_ptr, + raw_args.as_ptr(), + result_space, + &mut error_out, + invoke_env, + )}; if success { Ok(()) } else { let error: RuntimeError = error_out - .map(RuntimeError::InvokeError) + .map(Into::into) .unwrap_or_else(|| RuntimeError::InvokeError(InvokeError::FailedWithNoError)); Err(error.into()) } diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 4594bcd4f80..b4db0fbacfa 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -590,7 +590,7 @@ macro_rules! impl_traits { ) { Ok(Rets::from_ret_array(rets)) } else { - Err(error_out.map_or_else(|| RuntimeError::InvokeError(InvokeError::FailedWithNoError), RuntimeError::InvokeError)) + Err(error_out.map_or_else(|| RuntimeError::InvokeError(InvokeError::FailedWithNoError), Into::into)) } } } diff --git a/tests/high_level_api.rs b/tests/high_level_api.rs index 389e20c411b..5d9ae70fb03 100644 --- a/tests/high_level_api.rs +++ b/tests/high_level_api.rs @@ -268,7 +268,7 @@ wasmer_backends! { let result = foo.call(); - if let Err(RuntimeError(e)) = result { + if let Err(RuntimeError::User(e)) = result { let exit_code = e.downcast::().unwrap(); assert_eq!(exit_code.code, 42); } else { diff --git a/tests/imports.rs b/tests/imports.rs index e4ce076719c..ed1a2da81d7 100644 --- a/tests/imports.rs +++ b/tests/imports.rs @@ -52,7 +52,7 @@ macro_rules! call_and_assert { expected_value, concat!("Expected right when calling `", stringify!($function), "`.") ), - (Err(RuntimeError(data)), Err(RuntimeError(expected_data))) => { + (Err(RuntimeError::User(data)), Err(RuntimeError::User(expected_data))) => { if let (Some(data), Some(expected_data)) = ( data.downcast_ref::<&str>(), expected_data.downcast_ref::<&str>(), @@ -406,7 +406,7 @@ wasmer_backends! { test!( test_fn, function_fn(i32) -> i32, (1) == Ok(2)); test!( test_closure, function_closure(i32) -> i32, (1) == Ok(2)); test!( test_fn_dynamic, function_fn_dynamic(i32) -> i32, (1) == Ok(2)); - test!( test_fn_dynamic_panic, function_fn_dynamic_panic(i32) -> i32, (1) == Err(RuntimeError(Box::new("test")))); + test!( test_fn_dynamic_panic, function_fn_dynamic_panic(i32) -> i32, (1) == Err(RuntimeError::User(Box::new("test")))); test!( test_closure_dynamic_0, @@ -460,31 +460,31 @@ wasmer_backends! { test_fn_trap, function_fn_trap(i32) -> i32, - (1) == Err(RuntimeError(Box::new(format!("foo {}", 2)))) + (1) == Err(RuntimeError::User(Box::new(format!("foo {}", 2)))) ); test!( test_closure_trap, function_closure_trap(i32) -> i32, - (1) == Err(RuntimeError(Box::new(format!("bar {}", 2)))) + (1) == Err(RuntimeError::User(Box::new(format!("bar {}", 2)))) ); test!( test_fn_trap_with_vmctx, function_fn_trap_with_vmctx(i32) -> i32, - (1) == Err(RuntimeError(Box::new(format!("baz {}", 2 + SHIFT)))) + (1) == Err(RuntimeError::User(Box::new(format!("baz {}", 2 + SHIFT)))) ); test!( test_closure_trap_with_vmctx, function_closure_trap_with_vmctx(i32) -> i32, - (1) == Err(RuntimeError(Box::new(format!("qux {}", 2 + SHIFT)))) + (1) == Err(RuntimeError::User(Box::new(format!("qux {}", 2 + SHIFT)))) ); test!( test_closure_trap_with_vmctx_and_env, function_closure_trap_with_vmctx_and_env(i32) -> i32, - (1) == Err(RuntimeError(Box::new(format!("! {}", 2 + shift + SHIFT)))) + (1) == Err(RuntimeError::User(Box::new(format!("! {}", 2 + shift + SHIFT)))) ); #[test] diff --git a/tests/middleware_common.rs b/tests/middleware_common.rs index 90516af0c30..9f139a4ad79 100644 --- a/tests/middleware_common.rs +++ b/tests/middleware_common.rs @@ -7,6 +7,7 @@ use wasmer_middleware_common::metering::*; use wasmer_runtime_core::codegen::ModuleCodeGenerator; use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler}; use wasmer_runtime_core::fault::{pop_code_version, push_code_version}; +use wasmer_runtime_core::error::RuntimeError; use wasmer_runtime_core::state::CodeVersion; // Assemblyscript @@ -179,10 +180,14 @@ fn middleware_test_traps_after_costly_call(backend: &'static str, compiler: impl } let err = result.unwrap_err(); - assert!(err - .0 - .downcast_ref::() - .is_some()); + if let RuntimeError::Metering(metering_err) = err { + assert!(metering_err + .downcast_ref::() + .is_some()); + } else { + assert!(false, "metering error not found"); + } + // verify it used the correct number of points assert_eq!(get_points_used(&instance), 109); // Used points will be slightly more than `limit` because of the way we do gas checking.