diff --git a/src/main.rs b/src/main.rs index b63f3cff3..c13524222 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +#![feature(test)] + +extern crate test; #[macro_use] extern crate error_chain; #[macro_use] diff --git a/src/spec/tests.rs b/src/spec/tests.rs index fc7a0c14b..bee693785 100644 --- a/src/spec/tests.rs +++ b/src/spec/tests.rs @@ -2,17 +2,19 @@ use std::collections::HashMap; use std::path::Path; use std::rc::Rc; -use super::{run_single_file, InvokationResult, ScriptHandler}; use cranelift_codegen::ir::types; -use crate::webassembly::{ - compile, instantiate, Error, ErrorKind, Export, Instance, Module, ResultObject, -}; +use cranelift_entity::EntityRef; use libffi::high::call::*; use libffi::high::types::CType; use std::iter::Iterator; use wabt::script::{Action, Value}; // use crate::webassembly::instance::InvokeResult; +use super::{run_single_file, InvokationResult, ScriptHandler}; +use crate::webassembly::{ + compile, instantiate, Error, ErrorKind, Export, Instance, Module, ResultObject, +}; + struct StoreCtrl<'module> { last_module: Option, modules: HashMap>, @@ -162,8 +164,13 @@ impl<'module> ScriptHandler for StoreCtrl<'module> { mod tests { use std::path::Path; - + use crate::test::Bencher; use super::run_single_file; + use std::mem; + use crate::webassembly::{ + compile, instantiate, Error, ErrorKind, Export, Instance, Module, ResultObject, + }; + use wabt::wat2wasm; fn do_test(test_name: String) { let mut handler = &mut super::StoreCtrl::new(); @@ -195,4 +202,34 @@ mod tests { br_if, call, } + + fn my_func () -> Vec { + let x = String::from("hello"); + let bytes = x.into_bytes(); + return bytes; + } + + #[bench] + fn bench_identity(b: &mut Bencher) { + pub const BENCHMARK_BYTES: &[u8] = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/src/spec/tests/benchmark.wast" + )); + let wasm_bytes = wat2wasm(BENCHMARK_BYTES.to_vec()).expect("Can't convert wat to wasm"); + let result_object = instantiate(wasm_bytes, None).expect("Not compiled properly"); + let instance = result_object.instance; + let module = result_object.module; + let func_index = match module.info.exports.get("identity") { + Some(&Export::Function(index)) => index, + _ => panic!("Function not found"), + }; + let func_addr = instance.get_function_pointer(func_index); + let func = unsafe { + mem::transmute::<_, fn(i32) -> i32>(func_addr) + }; + assert_eq!(func(1), 1, "Identity function not working."); + b.iter(|| { + func(1); + }); + } } diff --git a/src/spec/tests/benchmark.wast b/src/spec/tests/benchmark.wast new file mode 100644 index 000000000..98f6a6037 --- /dev/null +++ b/src/spec/tests/benchmark.wast @@ -0,0 +1,7 @@ +(module + (table 0 anyfunc) + (memory 0) + (func (export "identity") (param i32) (result i32) + (get_local 0) + ) +) diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index efd5d9b4d..29f29b044 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -401,6 +401,10 @@ impl Instance { pub fn memories(&self) -> Arc> { self.memories.clone() } + pub fn get_function_pointer(&self, func_index: FuncIndex) -> *const u8 { + let func_pointer = &self.functions[func_index.index()]; + func_pointer.as_ptr() + } /// Invoke a WebAssembly function given a FuncIndex and the /// arguments that the function should be called with