Implement RFC 11: Redesigning Wasmtime's APIs (#2897)

Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
This commit is contained in:
Alex Crichton
2021-06-03 09:10:53 -05:00
committed by GitHub
parent a5a28b1c5b
commit 7a1b7cdf92
233 changed files with 13349 additions and 11997 deletions

View File

@@ -5,7 +5,7 @@ use wasmtime::*;
#[test]
fn test_trap_return() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module
(func $hello (import "" "hello"))
@@ -15,12 +15,15 @@ fn test_trap_return() -> Result<()> {
let module = Module::new(store.engine(), wat)?;
let hello_type = FuncType::new(None, None);
let hello_func = Func::new(&store, hello_type, |_, _, _| Err(Trap::new("test 123")));
let hello_func = Func::new(&mut store, hello_type, |_, _, _| Err(Trap::new("test 123")));
let instance = Instance::new(&store, &module, &[hello_func.into()])?;
let run_func = instance.get_typed_func::<(), ()>("run")?;
let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
let e = run_func.call(()).err().expect("error calling function");
let e = run_func
.call(&mut store, ())
.err()
.expect("error calling function");
assert!(e.to_string().contains("test 123"));
Ok(())
@@ -29,7 +32,7 @@ fn test_trap_return() -> Result<()> {
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn test_trap_trace() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $hello_mod
(func (export "run") (call $hello))
@@ -38,10 +41,13 @@ fn test_trap_trace() -> Result<()> {
"#;
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[])?;
let run_func = instance.get_typed_func::<(), ()>("run")?;
let instance = Instance::new(&mut store, &module, &[])?;
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
let e = run_func.call(()).err().expect("error calling function");
let e = run_func
.call(&mut store, ())
.err()
.expect("error calling function");
let trace = e.trace();
assert_eq!(trace.len(), 2);
@@ -67,7 +73,7 @@ fn test_trap_trace() -> Result<()> {
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn test_trap_trace_cb() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $hello_mod
(import "" "throw" (func $throw))
@@ -77,13 +83,16 @@ fn test_trap_trace_cb() -> Result<()> {
"#;
let fn_type = FuncType::new(None, None);
let fn_func = Func::new(&store, fn_type, |_, _, _| Err(Trap::new("cb throw")));
let fn_func = Func::new(&mut store, fn_type, |_, _, _| Err(Trap::new("cb throw")));
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[fn_func.into()])?;
let run_func = instance.get_typed_func::<(), ()>("run")?;
let instance = Instance::new(&mut store, &module, &[fn_func.into()])?;
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
let e = run_func.call(()).err().expect("error calling function");
let e = run_func
.call(&mut store, ())
.err()
.expect("error calling function");
let trace = e.trace();
assert_eq!(trace.len(), 2);
@@ -99,7 +108,7 @@ fn test_trap_trace_cb() -> Result<()> {
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn test_trap_stack_overflow() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $rec_mod
(func $run (export "run") (call $run))
@@ -107,10 +116,13 @@ fn test_trap_stack_overflow() -> Result<()> {
"#;
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[])?;
let run_func = instance.get_typed_func::<(), ()>("run")?;
let instance = Instance::new(&mut store, &module, &[])?;
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
let e = run_func.call(()).err().expect("error calling function");
let e = run_func
.call(&mut store, ())
.err()
.expect("error calling function");
let trace = e.trace();
assert!(trace.len() >= 32);
@@ -127,7 +139,7 @@ fn test_trap_stack_overflow() -> Result<()> {
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn trap_display_pretty() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $m
(func $die unreachable)
@@ -138,10 +150,13 @@ fn trap_display_pretty() -> Result<()> {
"#;
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[])?;
let run_func = instance.get_typed_func::<(), ()>("bar")?;
let instance = Instance::new(&mut store, &module, &[])?;
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "bar")?;
let e = run_func.call(()).err().expect("error calling function");
let e = run_func
.call(&mut store, ())
.err()
.expect("error calling function");
assert_eq!(
e.to_string(),
"\
@@ -159,7 +174,7 @@ wasm backtrace:
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn trap_display_multi_module() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $a
(func $die unreachable)
@@ -170,8 +185,8 @@ fn trap_display_multi_module() -> Result<()> {
"#;
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[])?;
let bar = instance.get_export("bar").unwrap();
let instance = Instance::new(&mut store, &module, &[])?;
let bar = instance.get_export(&mut store, "bar").unwrap();
let wat = r#"
(module $b
@@ -181,10 +196,13 @@ fn trap_display_multi_module() -> Result<()> {
)
"#;
let module = Module::new(store.engine(), wat)?;
let instance = Instance::new(&store, &module, &[bar])?;
let bar2 = instance.get_typed_func::<(), ()>("bar2")?;
let instance = Instance::new(&mut store, &module, &[bar])?;
let bar2 = instance.get_typed_func::<(), (), _>(&mut store, "bar2")?;
let e = bar2.call(()).err().expect("error calling function");
let e = bar2
.call(&mut store, ())
.err()
.expect("error calling function");
assert_eq!(
e.to_string(),
"\
@@ -203,7 +221,7 @@ wasm backtrace:
#[test]
fn trap_start_function_import() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let binary = wat::parse_str(
r#"
(module $a
@@ -215,8 +233,8 @@ fn trap_start_function_import() -> Result<()> {
let module = Module::new(store.engine(), &binary)?;
let sig = FuncType::new(None, None);
let func = Func::new(&store, sig, |_, _, _| Err(Trap::new("user trap")));
let err = Instance::new(&store, &module, &[func.into()])
let func = Func::new(&mut store, sig, |_, _, _| Err(Trap::new("user trap")));
let err = Instance::new(&mut store, &module, &[func.into()])
.err()
.unwrap();
assert!(err
@@ -229,7 +247,7 @@ fn trap_start_function_import() -> Result<()> {
#[test]
fn rust_panic_import() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let binary = wat::parse_str(
r#"
(module $a
@@ -243,22 +261,17 @@ fn rust_panic_import() -> Result<()> {
let module = Module::new(store.engine(), &binary)?;
let sig = FuncType::new(None, None);
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
let instance = Instance::new(
&store,
&module,
&[
func.into(),
Func::wrap(&store, || panic!("this is another panic")).into(),
],
)?;
let func = instance.get_typed_func::<(), ()>("foo")?;
let err = panic::catch_unwind(AssertUnwindSafe(|| drop(func.call(())))).unwrap_err();
let func = Func::new(&mut store, sig, |_, _, _| panic!("this is a panic"));
let func2 = Func::wrap(&mut store, || panic!("this is another panic"));
let instance = Instance::new(&mut store, &module, &[func.into(), func2.into()])?;
let func = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
let err =
panic::catch_unwind(AssertUnwindSafe(|| drop(func.call(&mut store, ())))).unwrap_err();
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
let func = instance.get_typed_func::<(), ()>("bar")?;
let func = instance.get_typed_func::<(), (), _>(&mut store, "bar")?;
let err = panic::catch_unwind(AssertUnwindSafe(|| {
drop(func.call(()));
drop(func.call(&mut store, ()));
}))
.unwrap_err();
assert_eq!(
@@ -270,7 +283,7 @@ fn rust_panic_import() -> Result<()> {
#[test]
fn rust_panic_start_function() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let binary = wat::parse_str(
r#"
(module $a
@@ -282,16 +295,16 @@ fn rust_panic_start_function() -> Result<()> {
let module = Module::new(store.engine(), &binary)?;
let sig = FuncType::new(None, None);
let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic"));
let func = Func::new(&mut store, sig, |_, _, _| panic!("this is a panic"));
let err = panic::catch_unwind(AssertUnwindSafe(|| {
drop(Instance::new(&store, &module, &[func.into()]));
drop(Instance::new(&mut store, &module, &[func.into()]));
}))
.unwrap_err();
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
let func = Func::wrap(&store, || panic!("this is another panic"));
let func = Func::wrap(&mut store, || panic!("this is another panic"));
let err = panic::catch_unwind(AssertUnwindSafe(|| {
drop(Instance::new(&store, &module, &[func.into()]));
drop(Instance::new(&mut store, &module, &[func.into()]));
}))
.unwrap_err();
assert_eq!(
@@ -303,7 +316,7 @@ fn rust_panic_start_function() -> Result<()> {
#[test]
fn mismatched_arguments() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let binary = wat::parse_str(
r#"
(module $a
@@ -313,18 +326,20 @@ fn mismatched_arguments() -> Result<()> {
)?;
let module = Module::new(store.engine(), &binary)?;
let instance = Instance::new(&store, &module, &[])?;
let func = instance.get_func("foo").unwrap();
let instance = Instance::new(&mut store, &module, &[])?;
let func = instance.get_func(&mut store, "foo").unwrap();
assert_eq!(
func.call(&[]).unwrap_err().to_string(),
func.call(&mut store, &[]).unwrap_err().to_string(),
"expected 1 arguments, got 0"
);
assert_eq!(
func.call(&[Val::F32(0)]).unwrap_err().to_string(),
func.call(&mut store, &[Val::F32(0)])
.unwrap_err()
.to_string(),
"argument type mismatch: found f32 but expected i32",
);
assert_eq!(
func.call(&[Val::I32(0), Val::I32(1)])
func.call(&mut store, &[Val::I32(0), Val::I32(1)])
.unwrap_err()
.to_string(),
"expected 1 arguments, got 2"
@@ -334,7 +349,7 @@ fn mismatched_arguments() -> Result<()> {
#[test]
fn call_signature_mismatch() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let binary = wat::parse_str(
r#"
(module $a
@@ -351,7 +366,7 @@ fn call_signature_mismatch() -> Result<()> {
)?;
let module = Module::new(store.engine(), &binary)?;
let err = Instance::new(&store, &module, &[])
let err = Instance::new(&mut store, &module, &[])
.err()
.unwrap()
.downcast::<Trap>()
@@ -365,7 +380,7 @@ fn call_signature_mismatch() -> Result<()> {
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn start_trap_pretty() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let wat = r#"
(module $m
(func $die unreachable)
@@ -377,7 +392,7 @@ fn start_trap_pretty() -> Result<()> {
"#;
let module = Module::new(store.engine(), wat)?;
let e = match Instance::new(&store, &module, &[]) {
let e = match Instance::new(&mut store, &module, &[]) {
Ok(_) => panic!("expected failure"),
Err(e) => e.downcast::<Trap>()?,
};
@@ -399,17 +414,17 @@ wasm backtrace:
#[test]
#[cfg_attr(all(target_os = "macos", target_arch = "aarch64"), ignore)] // TODO #2808 system libunwind is broken on aarch64
fn present_after_module_drop() -> Result<()> {
let store = Store::default();
let mut store = Store::<()>::default();
let module = Module::new(store.engine(), r#"(func (export "foo") unreachable)"#)?;
let instance = Instance::new(&store, &module, &[])?;
let func = instance.get_typed_func::<(), ()>("foo")?;
let instance = Instance::new(&mut store, &module, &[])?;
let func = instance.get_typed_func::<(), (), _>(&mut store, "foo")?;
println!("asserting before we drop modules");
assert_trap(func.call(()).unwrap_err());
assert_trap(func.call(&mut store, ()).unwrap_err());
drop((instance, module));
println!("asserting after drop");
assert_trap(func.call(()).unwrap_err());
assert_trap(func.call(&mut store, ()).unwrap_err());
return Ok(());
fn assert_trap(t: Trap) {
@@ -420,10 +435,10 @@ fn present_after_module_drop() -> Result<()> {
}
fn assert_trap_code(wat: &str, code: wasmtime::TrapCode) {
let store = Store::default();
let mut store = Store::<()>::default();
let module = Module::new(store.engine(), wat).unwrap();
let err = match Instance::new(&store, &module, &[]) {
let err = match Instance::new(&mut store, &module, &[]) {
Ok(_) => unreachable!(),
Err(e) => e,
};
@@ -493,19 +508,18 @@ fn parse_dwarf_info() -> Result<()> {
let mut config = Config::new();
config.wasm_backtrace_details(WasmBacktraceDetails::Enable);
let engine = Engine::new(&config)?;
let store = Store::new(&engine);
let module = Module::new(&engine, &wasm)?;
let mut linker = Linker::new(&store);
wasmtime_wasi::Wasi::new(
&store,
let mut linker = Linker::new(&engine);
wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;
let mut store = Store::new(
&engine,
wasmtime_wasi::sync::WasiCtxBuilder::new()
.inherit_stdio()
.build(),
)
.add_to_linker(&mut linker)?;
linker.module("", &module)?;
let run = linker.get_default("")?;
let trap = run.call(&[]).unwrap_err().downcast::<Trap>()?;
);
linker.module(&mut store, "", &module)?;
let run = linker.get_default(&mut store, "")?;
let trap = run.call(&mut store, &[]).unwrap_err().downcast::<Trap>()?;
let mut found = false;
for frame in trap.trace() {
@@ -529,7 +543,7 @@ fn no_hint_even_with_dwarf_info() -> Result<()> {
let mut config = Config::new();
config.wasm_backtrace_details(WasmBacktraceDetails::Disable);
let engine = Engine::new(&config)?;
let store = Store::new(&engine);
let mut store = Store::new(&engine, ());
let module = Module::new(
&engine,
r#"
@@ -541,7 +555,7 @@ fn no_hint_even_with_dwarf_info() -> Result<()> {
)
"#,
)?;
let trap = Instance::new(&store, &module, &[])
let trap = Instance::new(&mut store, &module, &[])
.err()
.unwrap()
.downcast::<Trap>()?;
@@ -564,7 +578,7 @@ fn hint_with_dwarf_info() -> Result<()> {
if std::env::var("WASMTIME_BACKTRACE_DETAILS").is_ok() {
return Ok(());
}
let store = Store::default();
let mut store = Store::<()>::default();
let module = Module::new(
store.engine(),
r#"
@@ -576,7 +590,7 @@ fn hint_with_dwarf_info() -> Result<()> {
)
"#,
)?;
let trap = Instance::new(&store, &module, &[])
let trap = Instance::new(&mut store, &module, &[])
.err()
.unwrap()
.downcast::<Trap>()?;
@@ -596,30 +610,23 @@ note: run with `WASMTIME_BACKTRACE_DETAILS=1` environment variable to display mo
fn multithreaded_traps() -> Result<()> {
// Compile and run unreachable on a thread, then moves over the whole store to another thread,
// and make sure traps are still correctly caught after notifying the store of the move.
let instance = {
let store = Store::default();
let module = Module::new(
store.engine(),
r#"(module (func (export "run") unreachable))"#,
)?;
Instance::new(&store, &module, &[])?
};
let mut store = Store::<()>::default();
let module = Module::new(
store.engine(),
r#"(module (func (export "run") unreachable))"#,
)?;
let instance = Instance::new(&mut store, &module, &[])?;
assert!(instance.get_typed_func::<(), ()>("run")?.call(()).is_err());
struct SendInstance {
inner: Instance,
}
unsafe impl Send for SendInstance {}
let instance = SendInstance { inner: instance };
assert!(instance
.get_typed_func::<(), (), _>(&mut store, "run")?
.call(&mut store, ())
.is_err());
let handle = std::thread::spawn(move || {
let instance = instance.inner;
assert!(instance
.get_typed_func::<(), ()>("run")
.get_typed_func::<(), (), _>(&mut store, "run")
.unwrap()
.call(())
.call(&mut store, ())
.is_err());
});