diff --git a/.circleci/config.yml b/.circleci/config.yml index e02dd9a55..40c2772ea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -111,6 +111,10 @@ jobs: name: Debug flag checked command: | cargo check --features "debug" --release + - run: + name: Check + command: | + make check - run: name: Release command: make release-fast @@ -163,6 +167,11 @@ jobs: ulimit -n 8000 sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680 make test + - run: + name: Check + command: | + export PATH="$HOME/.cargo/bin:$PATH" + make check - run: name: Release command: | diff --git a/Cargo.toml b/Cargo.toml index 017d18e15..dbb82e820 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ rustc_version = "0.2.3" [features] default = ["fast-tests", "wasi"] -"loader:kernel" = ["wasmer-kernel-loader"] +"loader-kernel" = ["wasmer-kernel-loader"] debug = ["wasmer-runtime-core/debug"] trace = ["wasmer-runtime-core/trace"] extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"] diff --git a/Makefile b/Makefile index 38fbb8dc4..deffef349 100644 --- a/Makefile +++ b/Makefile @@ -117,8 +117,11 @@ debug: install: cargo install --path . +check: + cargo check --release --features backend-singlepass,backend-llvm,loader-kernel + release: - cargo build --release --features backend-singlepass,backend-llvm,loader:kernel + cargo build --release --features backend-singlepass,backend-llvm,loader-kernel # Only one backend (cranelift) release-fast: diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index aa1f6c730..1eb8ba108 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -117,6 +117,7 @@ pub struct CompilerConfig { pub symbol_map: Option>, pub memory_bound_check_mode: MemoryBoundCheckMode, pub enforce_stack_check: bool, + pub track_state: bool, } pub trait Compiler { diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 72046bf6f..8650cb4ac 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -111,7 +111,13 @@ impl ModuleStateMap { .unwrap(); match fsm.call_offsets.get(&(ip - base)) { - Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))), + Some(x) => { + if x.diff_id < fsm.diffs.len() { + Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))) + } else { + None + } + } None => None, } } @@ -132,7 +138,13 @@ impl ModuleStateMap { .unwrap(); match fsm.trappable_offsets.get(&(ip - base)) { - Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))), + Some(x) => { + if x.diff_id < fsm.diffs.len() { + Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))) + } else { + None + } + } None => None, } } @@ -149,7 +161,13 @@ impl ModuleStateMap { .unwrap(); match fsm.loop_offsets.get(&(ip - base)) { - Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))), + Some(x) => { + if x.diff_id < fsm.diffs.len() { + Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))) + } else { + None + } + } None => None, } } diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 6ccd8cf29..7bc6581ba 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -317,6 +317,7 @@ pub struct CodegenError { struct CodegenConfig { memory_bound_check_mode: MemoryBoundCheckMode, enforce_stack_check: bool, + track_state: bool, } impl ModuleCodeGenerator @@ -366,7 +367,8 @@ impl ModuleCodeGenerator begin_label_info.1 = Some(begin_offset); let begin_label = begin_label_info.0; - let machine = Machine::new(); + let mut machine = Machine::new(); + machine.track_state = self.config.as_ref().unwrap().track_state; dynasm!( assembler @@ -532,6 +534,7 @@ impl ModuleCodeGenerator self.config = Some(Arc::new(CodegenConfig { memory_bound_check_mode: config.memory_bound_check_mode, enforce_stack_check: config.enforce_stack_check, + track_state: config.track_state, })); Ok(()) } @@ -1594,6 +1597,9 @@ impl X64FunctionCode { fsm: &mut FunctionStateMap, control_stack: &mut [ControlFrame], ) -> usize { + if !m.track_state { + return ::std::usize::MAX; + } let last_frame = control_stack.last_mut().unwrap(); let mut diff = m.state.diff(&last_frame.state); diff.last = Some(last_frame.state_diff_id); @@ -1769,7 +1775,7 @@ impl FunctionCodeGenerator for X64FunctionCode { .unwrap() .insert(a.get_offset(), callback); } - InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}, + InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {} InternalEvent::GetInternal(idx) => { let idx = idx as usize; assert!(idx < INTERNALS_SIZE); @@ -1820,7 +1826,11 @@ impl FunctionCodeGenerator for X64FunctionCode { ), Location::GPR(tmp), ); - let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); + let loc = get_location_released( + a, + &mut self.machine, + self.value_stack.pop().unwrap(), + ); // Move internal into storage. Self::emit_relaxed_binop( @@ -1832,8 +1842,7 @@ impl FunctionCodeGenerator for X64FunctionCode { Location::Memory(tmp, (idx * 8) as i32), ); self.machine.release_temp_gpr(tmp); - } - //_ => unimplemented!(), + } //_ => unimplemented!(), } return Ok(()); } @@ -2411,7 +2420,14 @@ impl FunctionCodeGenerator for X64FunctionCode { loc_b, ); a.emit_jmp(Condition::NotEqual, normal_path); - a.emit_mov(Size::S64, Location::Imm64(0), ret); + Self::emit_relaxed_binop( + a, + &mut self.machine, + Assembler::emit_mov, + Size::S64, + Location::Imm64(0), + ret, + ); a.emit_jmp(Condition::None, end); a.emit_label(normal_path); @@ -4525,9 +4541,14 @@ impl FunctionCodeGenerator for X64FunctionCode { |a, m, addr| { match ret { Location::GPR(_) => {} - _ => { - a.emit_mov(Size::S64, Location::Imm64(0), ret); + Location::Memory(base, offset) => { + a.emit_mov( + Size::S32, + Location::Imm32(0), + Location::Memory(base, offset + 4), + ); // clear upper bits } + _ => unreachable!(), } Self::emit_relaxed_binop( a, diff --git a/lib/singlepass-backend/src/machine.rs b/lib/singlepass-backend/src/machine.rs index 61c3c79ce..b09d0bf85 100644 --- a/lib/singlepass-backend/src/machine.rs +++ b/lib/singlepass-backend/src/machine.rs @@ -13,6 +13,7 @@ pub struct Machine { stack_offset: MachineStackOffset, save_area_offset: Option, pub state: MachineState, + pub(crate) track_state: bool, } impl Machine { @@ -23,6 +24,7 @@ impl Machine { stack_offset: MachineStackOffset(0), save_area_offset: None, state: x64::new_machine_state(), + track_state: true, } } diff --git a/src/bin/kwasmd.rs b/src/bin/kwasmd.rs index d7c05d48d..def71d589 100644 --- a/src/bin/kwasmd.rs +++ b/src/bin/kwasmd.rs @@ -5,10 +5,10 @@ extern crate structopt; use structopt::StructOpt; -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] use wasmer_singlepass_backend::SinglePassCompiler; -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] use std::os::unix::net::{UnixListener, UnixStream}; #[derive(Debug, StructOpt)] @@ -24,14 +24,14 @@ struct Listen { socket: String, } -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] const CMD_RUN_CODE: u32 = 0x901; -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] const CMD_READ_MEMORY: u32 = 0x902; -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] const CMD_WRITE_MEMORY: u32 = 0x903; -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] fn handle_client(mut stream: UnixStream) { use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::io::{Read, Write}; @@ -54,6 +54,7 @@ fn handle_client(mut stream: UnixStream) { symbol_map: None, memory_bound_check_mode: MemoryBoundCheckMode::Disable, enforce_stack_check: true, + track_state: false, }, &SinglePassCompiler::new(), ) @@ -131,7 +132,7 @@ fn handle_client(mut stream: UnixStream) { } } -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] fn run_listen(opts: Listen) { let listener = UnixListener::bind(&opts.socket).unwrap(); use std::thread; @@ -154,7 +155,7 @@ fn run_listen(opts: Listen) { } } -#[cfg(feature = "loader:kernel")] +#[cfg(feature = "loader-kernel")] fn main() { let options = CLIOptions::from_args(); match options { @@ -164,7 +165,7 @@ fn main() { } } -#[cfg(not(feature = "loader:kernel"))] +#[cfg(not(feature = "loader-kernel"))] fn main() { panic!("Kwasm loader is not enabled during compilation."); } diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 7542e3289..070acd9e8 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -112,10 +112,16 @@ struct Run { )] loader: Option, + /// Path to previously saved instance image to resume. #[cfg(feature = "backend-singlepass")] #[structopt(long = "resume")] resume: Option, + /// Whether or not state tracking should be disabled during compilation. + /// State tracking is necessary for tier switching and backtracing. + #[structopt(long = "no-track-state")] + no_track_state: bool, + /// The command name is a string that will override the first argument passed /// to the wasm program. This is used in wapm to provide nicer output in /// help commands and error messages of the running wasm program @@ -137,7 +143,7 @@ struct Run { #[derive(Debug, Copy, Clone)] enum LoaderName { Local, - #[cfg(feature = "loader:kernel")] + #[cfg(feature = "loader-kernel")] Kernel, } @@ -145,7 +151,7 @@ impl LoaderName { pub fn variants() -> &'static [&'static str] { &[ "local", - #[cfg(feature = "loader:kernel")] + #[cfg(feature = "loader-kernel")] "kernel", ] } @@ -156,7 +162,7 @@ impl FromStr for LoaderName { fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { "local" => Ok(LoaderName::Local), - #[cfg(feature = "loader:kernel")] + #[cfg(feature = "loader-kernel")] "kernel" => Ok(LoaderName::Kernel), _ => Err(format!("The loader {} doesn't exist", s)), } @@ -326,14 +332,16 @@ fn execute_wasm(options: &Run) -> Result<(), String> { Backend::LLVM => return Err("the llvm backend is not enabled".to_string()), }; - #[cfg(feature = "loader:kernel")] + let track_state = !options.no_track_state; + + #[cfg(feature = "loader-kernel")] let is_kernel_loader = if let Some(LoaderName::Kernel) = options.loader { true } else { false }; - #[cfg(not(feature = "loader:kernel"))] + #[cfg(not(feature = "loader-kernel"))] let is_kernel_loader = false; let module = if is_kernel_loader { @@ -343,6 +351,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { symbol_map: em_symbol_map, memory_bound_check_mode: MemoryBoundCheckMode::Disable, enforce_stack_check: true, + track_state, }, &*compiler, ) @@ -352,6 +361,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { &wasm_binary[..], CompilerConfig { symbol_map: em_symbol_map, + track_state, ..Default::default() }, &*compiler, @@ -397,6 +407,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { &wasm_binary[..], CompilerConfig { symbol_map: em_symbol_map, + track_state, ..Default::default() }, &*compiler, @@ -440,7 +451,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { .load(LocalLoader) .expect("Can't use the local loader"), ), - #[cfg(feature = "loader:kernel")] + #[cfg(feature = "loader-kernel")] LoaderName::Kernel => Box::new( instance .load(::wasmer_kernel_loader::KernelLoader)