diff --git a/Cargo.lock b/Cargo.lock index 6186063dc6..24c4b1eb5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1397,6 +1397,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "psm" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e0536f6528466dbbbbe6b986c34175a8d0ff25b794c4bacda22e068cd2f2c5" +dependencies = [ + "cc", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -2572,6 +2581,7 @@ dependencies = [ "log", "memoffset", "more-asserts", + "psm", "region", "thiserror", "wasmtime-environ", diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index eb8a308953..aa787917f2 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -23,6 +23,7 @@ more-asserts = "0.2.1" cfg-if = "1.0" backtrace = "0.3.49" lazy_static = "1.3.0" +psm = "0.1.11" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3.7", features = ["winbase", "memoryapi", "errhandlingapi"] } diff --git a/crates/runtime/src/traphandlers.rs b/crates/runtime/src/traphandlers.rs index 4cea12eaac..592a9ecaca 100644 --- a/crates/runtime/src/traphandlers.rs +++ b/crates/runtime/src/traphandlers.rs @@ -499,9 +499,18 @@ impl<'a> CallThreadState<'a> { /// Note that this function must be called with `self` on the stack, not the /// heap/etc. fn update_stack_limit(&self, max_wasm_stack: usize) -> Result { - // Make an "educated guess" to figure out where the wasm sp value should - // start trapping if it drops below. - let wasm_stack_limit = self as *const _ as usize - max_wasm_stack; + // Determine the stack pointer where, after which, any wasm code will + // immediately trap. This is checked on the entry to all wasm functions. + // + // Note that this isn't 100% precise. We are requested to give wasm + // `max_wasm_stack` bytes, but what we're actually doing is giving wasm + // probably a little less than `max_wasm_stack` because we're + // calculating the limit relative to this function's approximate stack + // pointer. Wasm will be executed on a frame beneath this one (or next + // to it). In any case it's expected to be at most a few hundred bytes + // of slop one way or another. When wasm is typically given a MB or so + // (a million bytes) the slop shouldn't matter too much. + let wasm_stack_limit = psm::stack_pointer() as usize - max_wasm_stack; let interrupts = unsafe { &**(&*self.vmctx).instance().interrupts() }; let reset_stack_limit = match interrupts.stack_limit.compare_exchange(