diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e861ea7b6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +# Ignore everything +** +!lib/** +!src/** +!Cargo.toml +!Cargo.lock \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e42dd7265..fec3babbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2357,6 +2357,7 @@ dependencies = [ "nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde-bench 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..02ea6c413 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM circleci/rust:1.33.0-stretch as wasmer-build-env +RUN sudo apt-get update && \ + sudo apt-get install -y --no-install-recommends \ + cmake \ + && sudo rm -rf /var/lib/apt/lists/* +RUN curl -SL https://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz \ + | tar -xJC /home/circleci +ENV LLVM_SYS_70_PREFIX /home/circleci/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/ + +FROM wasmer-build-env AS wasmer-debug-env +RUN sudo apt-get update && \ + sudo apt-get install -y --no-install-recommends \ + valgrind \ + && sudo rm -rf /var/lib/apt/lists/* + +FROM wasmer-build-env AS wasmer-build +WORKDIR /home/circleci/wasmer +COPY . /home/circleci/wasmer +RUN sudo chmod -R 777 . +RUN cargo build --release + +FROM debian:stretch AS wasmer +WORKDIR /root/ +COPY --from=wasmer-build /home/circleci/wasmer/target/release/wasmer . +ENTRYPOINT ["./wasmer"] \ No newline at end of file diff --git a/docs/docker.md b/docs/docker.md new file mode 100644 index 000000000..2086284f7 --- /dev/null +++ b/docs/docker.md @@ -0,0 +1,39 @@ +# Dockerfile Documentation +The `Dockerfile` included in the project root directory could be used for development purposes or to build a small image containing the `wasmer` executable. + +The `wasmer-build-env` stage in the Dockerfile contains the dependencies needed to compile Wasmer including LLVM. + +The `wasmer-debug-env` stage adds the `valgrind` profiling tool to the `wasmer-build-env` stage. + +The `wasmer-build` stage in the Dockerfile will copy the current directory, assuming the build context is the `wasmer` project, and build the project using `cargo build --release`. + +The `wasmer` stage will copy the resulting `wasmer` executable from the `wasmer-build` stage into a new base image to create a smaller image containing `wasmer`. + +## Example Usages + +### Wasmer image +1. From the `wasmer` project directory, build the image: +`docker build -t wasmer --target=wasmer .` + +2. List options: +`docker run wasmer --help` + +3. Mount a directory, and run an example wasm file: +`docker run -v /Users/admin/Documents/wasmer-workspace:/root/wasmer-workspace wasmer run /root/wasmer-workspace/examples/hello.wasm` + +### Profiling +1. Build `wasmer-debug-env`: + `docker build --tag=wasmer-debug-env --target wasmer-debug-env .` + +2. Mount a directory from the host and run interactively: + `docker run -it -v /Users/admin/Documents/wasmer-workspace:/home/circleci/wasmer-workspace wasmer-debug-env /bin/bash` + +3. Inside the container, build `wasmer` and run profiling tool: +``` +cd /home/circleci/wasmer-workspace/wasmer` +cargo build +valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --simulate-cache=yes target/debug/wasmer run test.wasm +``` + +The `callgrind.out` can be viewed with the `qcachegrind` tool on Mac OS (`brew install qcachegrind`). + diff --git a/lib/llvm-backend/src/backend.rs b/lib/llvm-backend/src/backend.rs index f40a6dfb2..927dbeca5 100644 --- a/lib/llvm-backend/src/backend.rs +++ b/lib/llvm-backend/src/backend.rs @@ -75,10 +75,12 @@ extern "C" { fn module_delete(module: *mut LLVMModule); fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; - fn throw_trap(ty: i32) -> !; + fn throw_trap(ty: i32); /// This should be the same as spliting up the fat pointer into two arguments, /// but this is cleaner, I think? + #[cfg_attr(nightly, unwind(allowed))] + #[allow(improper_ctypes)] fn throw_any(data: *mut dyn Any) -> !; #[allow(improper_ctypes)] diff --git a/lib/runtime-core/Cargo.toml b/lib/runtime-core/Cargo.toml index 215df568a..41d472626 100644 --- a/lib/runtime-core/Cargo.toml +++ b/lib/runtime-core/Cargo.toml @@ -45,6 +45,7 @@ field-offset = "0.1.1" [build-dependencies] blake2b_simd = "0.4.1" +rustc_version = "0.2.3" [features] debug = [] diff --git a/lib/runtime-core/build.rs b/lib/runtime-core/build.rs index e91238bc6..38071e31c 100644 --- a/lib/runtime-core/build.rs +++ b/lib/runtime-core/build.rs @@ -23,4 +23,9 @@ fn main() { f_out .write_all(hash_string.as_bytes()) .expect("Could not write to file for wasmer hash value"); + + // Enable "nightly" cfg if the current compiler is nightly. + if rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly { + println!("cargo:rustc-cfg=nightly"); + } } diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index d7ef274fd..a43a4c63a 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(nightly, feature(unwind_attributes))] + #[cfg(test)] #[macro_use] extern crate field_offset; diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 2ca67dba5..d18055ba1 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -339,11 +339,14 @@ macro_rules! impl_traits { fn to_raw(&self) -> NonNull { assert_eq!(mem::size_of::(), 0, "you cannot use a closure that captures state for `Func`."); + /// This is required for the llvm backend to be able to unwind through this function. + #[cfg_attr(nightly, unwind(allowed))] extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct { let f: FN = unsafe { mem::transmute_copy(&()) }; let err = match panic::catch_unwind(panic::AssertUnwindSafe(|| { - f( ctx $( ,$x )* ).report() + let res = f( ctx $( ,$x )* ).report(); + res })) { Ok(Ok(returns)) => return returns.into_c_struct(), Ok(Err(err)) => err, diff --git a/lib/runtime/examples/call.rs b/lib/runtime/examples/call.rs index 12f149062..894fa4ab1 100644 --- a/lib/runtime/examples/call.rs +++ b/lib/runtime/examples/call.rs @@ -59,9 +59,9 @@ fn main() -> Result<(), error::Error> { }, })?; - let foo: Func<(), i32> = instance.func("dbz")?; + let foo = instance.dyn_func("dbz")?; - let result = foo.call(); + let result = foo.call(&[]); println!("result: {:?}", result);