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..16f1ac5f4 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); @@ -2411,7 +2417,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 +4538,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/wasmer.rs b/src/bin/wasmer.rs index 7542e3289..2de0acb43 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 @@ -326,6 +332,8 @@ fn execute_wasm(options: &Run) -> Result<(), String> { Backend::LLVM => return Err("the llvm backend is not enabled".to_string()), }; + let track_state = !options.no_track_state; + #[cfg(feature = "loader:kernel")] let is_kernel_loader = if let Some(LoaderName::Kernel) = options.loader { true @@ -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,