From 2e96b3529124aa470a05289e91fc92fb90a4cf00 Mon Sep 17 00:00:00 2001 From: Edgars Date: Fri, 31 Jul 2026 10:21:22 +0100 Subject: [PATCH] fix: harden Wasmtime integration --- .git-third-party/config.json | 6 +- .../patches/executor/third-party/wasm-tools/1 | 4 +- .../patches/executor/third-party/wasmtime/1 | 267 +++++++-------- .../patches/executor/third-party/wasmtime/2 | 10 +- .../patches/executor/third-party/wasmtime/3 | 8 +- .../patches/executor/third-party/wasmtime/4 | 54 ++-- .../patches/executor/third-party/wasmtime/5 | 18 +- .../patches/executor/third-party/wasmtime/6 | 169 ++++++++++ executor/Cargo.lock | 136 +++++--- executor/Cargo.toml | 1 + executor/src/exe/check.rs | 2 +- executor/src/exe/precompile.rs | 144 +-------- executor/src/rt/supervisor/actions.rs | 61 +--- executor/src/rt/supervisor/compilation.rs | 304 ++++++++++++++++-- executor/src/rt/supervisor/mod.rs | 28 +- 15 files changed, 710 insertions(+), 502 deletions(-) create mode 100644 .git-third-party/patches/executor/third-party/wasmtime/6 diff --git a/.git-third-party/config.json b/.git-third-party/config.json index eb8cc9e9..5f465058 100644 --- a/.git-third-party/config.json +++ b/.git-third-party/config.json @@ -2,13 +2,13 @@ "repos": { "executor/third-party/wasmtime": { "url": "https://github.com/bytecodealliance/wasmtime.git", - "commit": "6844a83b530f86ad13a65175282fe2dbcd33cad1", - "patches": 5, + "commit": "f8557c1ad85b8fc123b715d15db7b52483eade96", + "patches": 6, "submodules": [] }, "executor/third-party/wasm-tools": { "url": "https://github.com/bytecodealliance/wasm-tools.git", - "commit": "76927bf4bdbddf4b15f835c5eddfffbdfe3bdbd5", + "commit": "42127681cc850a4dc62824efc3786e25aa5f9910", "patches": 1 } } diff --git a/.git-third-party/patches/executor/third-party/wasm-tools/1 b/.git-third-party/patches/executor/third-party/wasm-tools/1 index e24efdf7..33549fee 100644 --- a/.git-third-party/patches/executor/third-party/wasm-tools/1 +++ b/.git-third-party/patches/executor/third-party/wasm-tools/1 @@ -9,7 +9,7 @@ Subject: [PATCH] fix: expose method for fuzzing 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/wasm-smith/src/core.rs b/crates/wasm-smith/src/core.rs -index e37ab57..502262b 100644 +index e37ab57ed..502262b28 100644 --- a/crates/wasm-smith/src/core.rs +++ b/crates/wasm-smith/src/core.rs @@ -2573,7 +2573,7 @@ impl Module { @@ -22,7 +22,7 @@ index e37ab57..502262b 100644 // If a function list is possible then build up a list of diff --git a/crates/wasm-smith/src/core/encode.rs b/crates/wasm-smith/src/core/encode.rs -index d2ffd48..5b9b551 100644 +index d2ffd4887..5b9b5514a 100644 --- a/crates/wasm-smith/src/core/encode.rs +++ b/crates/wasm-smith/src/core/encode.rs @@ -6,7 +6,8 @@ impl Module { diff --git a/.git-third-party/patches/executor/third-party/wasmtime/1 b/.git-third-party/patches/executor/third-party/wasmtime/1 index 93c93761..26a7bf51 100644 --- a/.git-third-party/patches/executor/third-party/wasmtime/1 +++ b/.git-third-party/patches/executor/third-party/wasmtime/1 @@ -8,17 +8,17 @@ Subject: [PATCH] feat: rebase genvm cranelift/frontend/src/frontend.rs | 4 + crates/cache/src/config.rs | 8 +- crates/cranelift/src/compiler.rs | 12 ++ - crates/cranelift/src/func_environ.rs | 74 ++++++++++++ + crates/cranelift/src/func_environ.rs | 69 +++++++++++ crates/cranelift/src/lib.rs | 2 + .../src/translate/code_translator.rs | 109 +++++++++++++++++- .../src/translate/func_translator.rs | 20 +++- crates/cranelift/src/translate/stack.rs | 10 ++ crates/environ/Cargo.toml | 2 +- - crates/environ/src/trap_encoding.rs | 5 + + crates/environ/src/trap_encoding.rs | 3 + crates/environ/src/tunables.rs | 4 + crates/environ/src/vmoffsets.rs | 10 ++ crates/wasmtime/Cargo.toml | 2 + - crates/wasmtime/src/config.rs | 22 +++- + crates/wasmtime/src/config.rs | 20 ++++ crates/wasmtime/src/engine/serialization.rs | 6 + crates/wasmtime/src/lib.rs | 3 + crates/wasmtime/src/runtime/func.rs | 71 ++++++++++++ @@ -30,29 +30,29 @@ Subject: [PATCH] feat: rebase genvm crates/wiggle/generate/src/wasmtime.rs | 60 ++++++++-- crates/wiggle/src/guest_error.rs | 2 + crates/wiggle/src/lib.rs | 5 + - 26 files changed, 453 insertions(+), 53 deletions(-) + 26 files changed, 445 insertions(+), 52 deletions(-) diff --git a/Cargo.toml b/Cargo.toml -index dc159f65..1a0bcd80 100644 +index 3d002f0cf..38fa4be22 100644 --- a/Cargo.toml +++ b/Cargo.toml -@@ -343,18 +343,18 @@ wit-bindgen = { version = "0.51.0", default-features = false } - wit-bindgen-rust-macro = { version = "0.51.0", default-features = false } +@@ -344,18 +344,18 @@ wit-bindgen = { version = "0.53.0", default-features = false } + wit-bindgen-rust-macro = { version = "0.53.0", default-features = false } # wasm-tools family: --wasmparser = { version = "0.244.0", default-features = false, features = ['simd'] } --wat = "1.244.0" --wast = "244.0.0" --wasmprinter = "0.244.0" --wasm-encoder = "0.244.0" --wasm-smith = "0.244.0" --wasm-mutate = "0.244.0" --wit-parser = "0.244.0" --wit-component = "0.244.0" --wasm-wave = "0.244.0" --wasm-compose = "0.244.0" --json-from-wast = "0.244.0" -+wasmparser = { path = "../wasm-tools/crates/wasmparser", default-features = false, features = ['simd']} +-wasmparser = { version = "0.245.0", default-features = false, features = ['simd'] } +-wat = "1.245.0" +-wast = "245.0.0" +-wasmprinter = "0.245.0" +-wasm-encoder = "0.245.0" +-wasm-smith = "0.245.0" +-wasm-mutate = "0.245.0" +-wit-parser = "0.245.0" +-wit-component = "0.245.0" +-wasm-wave = "0.245.0" +-wasm-compose = "0.245.0" +-json-from-wast = "0.245.0" ++wasmparser = { path = "../wasm-tools/crates/wasmparser", default-features = false, features = ['simd'] } +wat = { path = "../wasm-tools/crates/wat" } +wast = { path = "../wasm-tools/crates/wast" } +wasmprinter = { path = "../wasm-tools/crates/wasmprinter" } @@ -68,7 +68,7 @@ index dc159f65..1a0bcd80 100644 # Non-Bytecode Alliance maintained dependencies: # -------------------------- diff --git a/cranelift/frontend/src/frontend.rs b/cranelift/frontend/src/frontend.rs -index d51dbbbb..5ceb7b48 100644 +index d51dbbbbd..5ceb7b48c 100644 --- a/cranelift/frontend/src/frontend.rs +++ b/cranelift/frontend/src/frontend.rs @@ -47,6 +47,9 @@ pub struct FunctionBuilder<'a> { @@ -90,7 +90,7 @@ index d51dbbbb..5ceb7b48 100644 } diff --git a/crates/cache/src/config.rs b/crates/cache/src/config.rs -index 90de0060..2451a73e 100644 +index beef58d28..3cd366b7e 100644 --- a/crates/cache/src/config.rs +++ b/crates/cache/src/config.rs @@ -339,10 +339,16 @@ impl CacheConfig { @@ -112,7 +112,7 @@ index 90de0060..2451a73e 100644 // get config file path let (config_file, user_custom_file) = match config_file { diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs -index 3b75e282..0529e5fa 100644 +index cb0b22526..fb4fb01d3 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -314,6 +314,18 @@ impl wasmtime_environ::Compiler for Compiler { @@ -135,10 +135,10 @@ index 3b75e282..0529e5fa 100644 let FunctionBodyData { validator, body } = input; let mut validator = diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs -index 5bb16980..8f549ff5 100644 +index 22849dbb1..ec49b7acf 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs -@@ -203,6 +203,9 @@ pub struct FuncEnvironment<'module_environment> { +@@ -210,6 +210,9 @@ pub struct FuncEnvironment<'module_environment> { /// into the host to trap when signal handlers are disabled. pub(crate) stack_limit_at_function_entry: Option, @@ -148,7 +148,7 @@ index 5bb16980..8f549ff5 100644 /// Used by the stack switching feature. If set, we have a allocated a /// slot on this function's stack to be used for the /// current stack's `handler_list` field. -@@ -273,6 +276,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> { +@@ -280,6 +283,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> { stack_limit_at_function_entry: None, @@ -158,7 +158,7 @@ index 5bb16980..8f549ff5 100644 stack_switching_handler_list_buffer: None, stack_switching_values_buffer: None, -@@ -3296,6 +3302,7 @@ impl FuncEnvironment<'_> { +@@ -3324,6 +3330,7 @@ impl FuncEnvironment<'_> { sig_ref: ir::SigRef, call_args: &[ir::Value], ) -> WasmResult<()> { @@ -166,7 +166,7 @@ index 5bb16980..8f549ff5 100644 Call::new_tail(builder, self, srcloc).direct_call(callee_index, sig_ref, call_args)?; Ok(()) } -@@ -3311,6 +3318,7 @@ impl FuncEnvironment<'_> { +@@ -3339,6 +3346,7 @@ impl FuncEnvironment<'_> { callee: ir::Value, call_args: &[ir::Value], ) -> WasmResult<()> { @@ -174,7 +174,7 @@ index 5bb16980..8f549ff5 100644 Call::new_tail(builder, self, srcloc).indirect_call( features, table_index, -@@ -3330,6 +3338,7 @@ impl FuncEnvironment<'_> { +@@ -3358,6 +3366,7 @@ impl FuncEnvironment<'_> { callee: ir::Value, call_args: &[ir::Value], ) -> WasmResult<()> { @@ -182,7 +182,7 @@ index 5bb16980..8f549ff5 100644 Call::new_tail(builder, self, srcloc).call_ref(sig_ref, callee, call_args)?; Ok(()) } -@@ -3837,6 +3846,32 @@ impl FuncEnvironment<'_> { +@@ -3865,7 +3874,28 @@ impl FuncEnvironment<'_> { self.conditionally_trap(builder, overflow, ir::TrapCode::STACK_OVERFLOW); } @@ -206,16 +206,12 @@ index 5bb16980..8f549ff5 100644 + } + } + -+ // If the `vm_store_context` variable will get used then we initialize -+ // it here. -+ if true || self.tunables.consume_fuel || self.tunables.epoch_interruption { -+ self.get_vmstore_context_ptr(builder); -+ } -+ + self.update_state_slot_vmctx(builder); ++ self.get_vmstore_context_ptr(builder); + // Additionally we initialize `fuel_var` if it will get used. if self.tunables.consume_fuel { - self.fuel_function_entry(builder); -@@ -3882,6 +3917,44 @@ impl FuncEnvironment<'_> { +@@ -3910,6 +3940,44 @@ impl FuncEnvironment<'_> { self.isa.triple().architecture == target_lexicon::Architecture::X86_64 } @@ -260,7 +256,7 @@ index 5bb16980..8f549ff5 100644 pub fn translate_cont_bind( &mut self, builder: &mut FunctionBuilder<'_>, -@@ -4001,6 +4074,7 @@ impl FuncEnvironment<'_> { +@@ -4029,6 +4097,7 @@ impl FuncEnvironment<'_> { } pub fn handle_before_return(&mut self, retvals: &[ir::Value], builder: &mut FunctionBuilder) { @@ -269,10 +265,10 @@ index 5bb16980..8f549ff5 100644 if self.compiler.wmemcheck { let func_name = self.current_func_name(builder); diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs -index 1d1ac61c..4db70f6a 100644 +index 8c0a2da90..66c56b849 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs -@@ -72,6 +72,8 @@ pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode = +@@ -73,6 +73,8 @@ pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode = TrapCode::unwrap_user(Trap::ContinuationAlreadyConsumed as u8 + TRAP_OFFSET); pub const TRAP_CAST_FAILURE: TrapCode = TrapCode::unwrap_user(Trap::CastFailure as u8 + TRAP_OFFSET); @@ -282,10 +278,10 @@ index 1d1ac61c..4db70f6a 100644 /// Creates a new cranelift `Signature` with no wasm params/results for the /// given calling convention. diff --git a/crates/cranelift/src/translate/code_translator.rs b/crates/cranelift/src/translate/code_translator.rs -index b7565bd2..9dde783c 100644 +index 79d8edf56..ad613df54 100644 --- a/crates/cranelift/src/translate/code_translator.rs +++ b/crates/cranelift/src/translate/code_translator.rs -@@ -264,6 +264,7 @@ pub fn translate_operator( +@@ -265,6 +265,7 @@ pub fn translate_operator( .stacks .stack .extend_from_slice(builder.block_params(loop_body)); @@ -293,7 +289,7 @@ index b7565bd2..9dde783c 100644 builder.switch_to_block(loop_body); environ.translate_loop_header(builder)?; -@@ -1016,120 +1017,145 @@ pub fn translate_operator( +@@ -1017,120 +1018,145 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().ireduce(I32, val)); } Operator::F32Sqrt | Operator::F64Sqrt => { @@ -439,7 +435,7 @@ index b7565bd2..9dde783c 100644 let val = environ.stacks.pop1(); environ .stacks -@@ -1227,6 +1253,7 @@ pub fn translate_operator( +@@ -1228,6 +1254,7 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().rotr(arg1, arg2)); } Operator::F32Add | Operator::F64Add => { @@ -447,7 +443,7 @@ index b7565bd2..9dde783c 100644 let (arg1, arg2) = environ.stacks.pop2(); environ.stacks.push1(builder.ins().fadd(arg1, arg2)); } -@@ -1235,6 +1262,7 @@ pub fn translate_operator( +@@ -1236,6 +1263,7 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().isub(arg1, arg2)); } Operator::F32Sub | Operator::F64Sub => { @@ -455,7 +451,7 @@ index b7565bd2..9dde783c 100644 let (arg1, arg2) = environ.stacks.pop2(); environ.stacks.push1(builder.ins().fsub(arg1, arg2)); } -@@ -1243,10 +1271,12 @@ pub fn translate_operator( +@@ -1244,10 +1272,12 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().imul(arg1, arg2)); } Operator::F32Mul | Operator::F64Mul => { @@ -468,7 +464,7 @@ index b7565bd2..9dde783c 100644 let (arg1, arg2) = environ.stacks.pop2(); environ.stacks.push1(builder.ins().fdiv(arg1, arg2)); } -@@ -1271,14 +1301,17 @@ pub fn translate_operator( +@@ -1272,14 +1302,17 @@ pub fn translate_operator( environ.stacks.push1(result); } Operator::F32Min | Operator::F64Min => { @@ -486,7 +482,7 @@ index b7565bd2..9dde783c 100644 let (arg1, arg2) = environ.stacks.pop2(); environ.stacks.push1(builder.ins().fcopysign(arg1, arg2)); } -@@ -1711,9 +1744,13 @@ pub fn translate_operator( +@@ -1712,9 +1745,13 @@ pub fn translate_operator( environ.stacks.push1(splatted) } Operator::I32x4Splat @@ -502,7 +498,7 @@ index b7565bd2..9dde783c 100644 let splatted = builder.ins().splat(type_of(op), environ.stacks.pop1()); environ.stacks.push1(splatted) } -@@ -1794,9 +1831,15 @@ pub fn translate_operator( +@@ -1795,9 +1832,15 @@ pub fn translate_operator( // work. } Operator::I32x4ExtractLane { lane } @@ -520,7 +516,7 @@ index b7565bd2..9dde783c 100644 let vector = pop1_with_bitcast(environ, type_of(op), builder); environ .stacks -@@ -1812,9 +1855,16 @@ pub fn translate_operator( +@@ -1813,9 +1856,16 @@ pub fn translate_operator( .push1(builder.ins().insertlane(vector, reduced, *lane)) } Operator::I32x4ReplaceLane { lane } @@ -539,7 +535,7 @@ index b7565bd2..9dde783c 100644 let (vector, replacement) = environ.stacks.pop2(); let vector = optionally_bitcast_vector(vector, type_of(op), builder); environ -@@ -2022,30 +2072,37 @@ pub fn translate_operator( +@@ -2023,30 +2073,37 @@ pub fn translate_operator( translate_vector_fcmp(FloatCC::GreaterThanOrEqual, type_of(op), builder, environ) } Operator::F32x4Add | Operator::F64x2Add => { @@ -577,7 +573,7 @@ index b7565bd2..9dde783c 100644 // Note the careful ordering here with respect to `fcmp` and // `bitselect`. This matches the spec definition of: // -@@ -2059,6 +2116,7 @@ pub fn translate_operator( +@@ -2060,6 +2117,7 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().bitselect(cmp, b, a)) } Operator::F32x4PMin | Operator::F64x2PMin => { @@ -585,7 +581,7 @@ index b7565bd2..9dde783c 100644 // Note the careful ordering here which is similar to `pmax` above: // // fpmin(z1, z2) = -@@ -2071,26 +2129,32 @@ pub fn translate_operator( +@@ -2072,26 +2130,32 @@ pub fn translate_operator( environ.stacks.push1(builder.ins().bitselect(cmp, b, a)) } Operator::F32x4Sqrt | Operator::F64x2Sqrt => { @@ -618,7 +614,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, I32X4, builder); let widened_a = builder.ins().swiden_low(a); environ -@@ -2098,6 +2162,7 @@ pub fn translate_operator( +@@ -2099,6 +2163,7 @@ pub fn translate_operator( .push1(builder.ins().fcvt_from_sint(F64X2, widened_a)); } Operator::F64x2ConvertLowI32x4U => { @@ -626,7 +622,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, I32X4, builder); let widened_a = builder.ins().uwiden_low(a); environ -@@ -2105,20 +2170,24 @@ pub fn translate_operator( +@@ -2106,20 +2171,24 @@ pub fn translate_operator( .push1(builder.ins().fcvt_from_uint(F64X2, widened_a)); } Operator::F64x2PromoteLowF32x4 => { @@ -651,7 +647,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, F64X2, builder); let converted_a = builder.ins().fcvt_to_sint_sat(I64X2, a); let handle = builder.func.dfg.constants.insert(vec![0u8; 16].into()); -@@ -2141,12 +2210,14 @@ pub fn translate_operator( +@@ -2142,12 +2211,14 @@ pub fn translate_operator( // perhaps for other backends too) should be added and the codegen for // the relaxed instruction should conditionally be different. Operator::I32x4RelaxedTruncF32x4U | Operator::I32x4TruncSatF32x4U => { @@ -666,7 +662,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, F64X2, builder); let zero_constant = builder.func.dfg.constants.insert(vec![0u8; 16].into()); let result = if environ.is_x86() && !environ.isa().has_round() { -@@ -2267,41 +2338,49 @@ pub fn translate_operator( +@@ -2268,41 +2339,49 @@ pub fn translate_operator( .push1(builder.ins().iadd_pairwise(widen_low, widen_high)); } Operator::F32x4Ceil => { @@ -716,7 +712,7 @@ index b7565bd2..9dde783c 100644 let arg = pop1_with_bitcast(environ, F64X2, builder); let result = environ.nearest_f64x2(builder, arg); environ.stacks.push1(result); -@@ -2404,6 +2483,7 @@ pub fn translate_operator( +@@ -2405,6 +2484,7 @@ pub fn translate_operator( } Operator::F32x4RelaxedMax | Operator::F64x2RelaxedMax => { @@ -724,7 +720,7 @@ index b7565bd2..9dde783c 100644 let ty = type_of(op); let (a, b) = pop2_with_bitcast(environ, ty, builder); environ.stacks.push1( -@@ -2423,6 +2503,7 @@ pub fn translate_operator( +@@ -2424,6 +2504,7 @@ pub fn translate_operator( } Operator::F32x4RelaxedMin | Operator::F64x2RelaxedMin => { @@ -732,7 +728,7 @@ index b7565bd2..9dde783c 100644 let ty = type_of(op); let (a, b) = pop2_with_bitcast(environ, ty, builder); environ.stacks.push1( -@@ -2448,22 +2529,26 @@ pub fn translate_operator( +@@ -2449,22 +2530,26 @@ pub fn translate_operator( } Operator::F32x4RelaxedMadd => { @@ -759,7 +755,7 @@ index b7565bd2..9dde783c 100644 let (a, b, c) = pop3_with_bitcast(environ, type_of(op), builder); let a = builder.ins().fneg(a); let result = environ.fma_f64x2(builder, a, b, c); -@@ -2493,6 +2578,7 @@ pub fn translate_operator( +@@ -2494,6 +2579,7 @@ pub fn translate_operator( } Operator::I32x4RelaxedTruncF32x4S => { @@ -767,7 +763,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, F32X4, builder); environ.stacks.push1( if environ.relaxed_simd_deterministic() || !environ.is_x86() { -@@ -2505,6 +2591,7 @@ pub fn translate_operator( +@@ -2506,6 +2592,7 @@ pub fn translate_operator( ) } Operator::I32x4RelaxedTruncF64x2SZero => { @@ -775,7 +771,7 @@ index b7565bd2..9dde783c 100644 let a = pop1_with_bitcast(environ, F64X2, builder); let converted_a = if environ.relaxed_simd_deterministic() || !environ.is_x86() { // Deterministic semantics are to match the -@@ -3942,6 +4029,7 @@ fn translate_vector_icmp( +@@ -3943,6 +4030,7 @@ fn translate_vector_icmp( } fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, env: &mut FuncEnvironment<'_>) { @@ -783,7 +779,7 @@ index b7565bd2..9dde783c 100644 let (arg0, arg1) = env.stacks.pop2(); let val = builder.ins().fcmp(cc, arg0, arg1); env.stacks.push1(builder.ins().uextend(I32, val)); -@@ -3953,6 +4041,7 @@ fn translate_vector_fcmp( +@@ -3954,6 +4042,7 @@ fn translate_vector_fcmp( builder: &mut FunctionBuilder, env: &mut FuncEnvironment<'_>, ) { @@ -791,7 +787,7 @@ index b7565bd2..9dde783c 100644 let (a, b) = env.stacks.pop2(); let bitcast_a = optionally_bitcast_vector(a, needed_type, builder); let bitcast_b = optionally_bitcast_vector(b, needed_type, builder); -@@ -4479,3 +4568,11 @@ fn create_catch_block( +@@ -4480,3 +4569,11 @@ fn create_catch_block( Ok(block) } @@ -804,7 +800,7 @@ index b7565bd2..9dde783c 100644 + return true; +} diff --git a/crates/cranelift/src/translate/func_translator.rs b/crates/cranelift/src/translate/func_translator.rs -index bda7dd4d..08478285 100644 +index bda7dd4de..084782859 100644 --- a/crates/cranelift/src/translate/func_translator.rs +++ b/crates/cranelift/src/translate/func_translator.rs @@ -73,6 +73,9 @@ impl FuncTranslator { @@ -863,7 +859,7 @@ index bda7dd4d..08478285 100644 /// Declare `count` local variables of the same type, starting from `next_local`. diff --git a/crates/cranelift/src/translate/stack.rs b/crates/cranelift/src/translate/stack.rs -index f338fe3f..8b4716a9 100644 +index f338fe3f0..8b4716a9d 100644 --- a/crates/cranelift/src/translate/stack.rs +++ b/crates/cranelift/src/translate/stack.rs @@ -255,6 +255,7 @@ pub struct FuncTranslationStacks { @@ -916,12 +912,12 @@ index f338fe3f..8b4716a9 100644 /// Pop one value. diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml -index 07d8ef57..83e95f6d 100644 +index fe0310c6c..6ce3e57ea 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml -@@ -24,7 +24,7 @@ cpp_demangle = { version = "0.4.3", optional = true } - cranelift-entity = { workspace = true, features = ['enable-serde'] } +@@ -25,7 +25,7 @@ cranelift-entity = { workspace = true, features = ['enable-serde'] } cranelift-bitset = { workspace = true, features = ['enable-serde'] } + cranelift-bforest = { workspace = true } hashbrown = { workspace = true, features = ["default-hasher"] } -wasmparser = { workspace = true, features = ['validate', 'serde', 'features'] } +wasmparser = { workspace = true, features = ['validate', 'serde', 'features', "simd"] } @@ -929,62 +925,46 @@ index 07d8ef57..83e95f6d 100644 serde = { workspace = true } serde_derive = { workspace = true } diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs -index f9d22368..2d49707b 100644 +index cf011fe59..f2c969e1e 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs -@@ -141,6 +141,9 @@ pub enum Trap { - /// A component passed an unaligned pointer when lifting or lowering a - /// value. - UnalignedPointer, -+ -+ /// Deterministic mode violation -+ DeterministicMode, - // if adding a variant here be sure to update the `check!` macro below, and - // remember to update `trap.rs` and `trap.h` as mentioned above - } -@@ -193,6 +196,7 @@ impl Trap { - ListOutOfBounds - InvalidDiscriminant - UnalignedPointer -+ DeterministicMode - } +@@ -216,6 +216,9 @@ generate_trap_type! { + /// Cannot resume a thread which is not suspended. + CannotResumeThread = "cannot resume thread which is not suspended", - None -@@ -238,6 +242,7 @@ impl fmt::Display for Trap { - ListOutOfBounds => "list content out-of-bounds", - InvalidDiscriminant => "invalid variant discriminant", - UnalignedPointer => "unaligned pointer", -+ DeterministicMode => "deterministic mode violation (cpu)", - }; - write!(f, "wasm trap: {desc}") ++ /// Deterministic mode violation. ++ DeterministicMode = "deterministic mode violation (cpu)", ++ + // if adding a variant here be sure to update `trap.rs` and `trap.h` as + // mentioned above } diff --git a/crates/environ/src/tunables.rs b/crates/environ/src/tunables.rs -index fc9b4c3c..7f0ebd5b 100644 +index a3ea67ff7..375c45cef 100644 --- a/crates/environ/src/tunables.rs +++ b/crates/environ/src/tunables.rs -@@ -144,6 +144,9 @@ define_tunables! { - /// Whether any component model feature related to concurrency is - /// enabled. - pub concurrency_support: bool, +@@ -152,6 +152,9 @@ define_tunables! { + /// Whether recording in RR is enabled or not. This is used primarily + /// to signal checksum computation for compiled artifacts. + pub recording: bool, + + /// Whether floats enabled + pub floats_enabled: bool, } pub struct ConfigTunables { -@@ -220,6 +223,7 @@ impl Tunables { - inlining_sum_size_threshold: 2000, +@@ -230,6 +233,7 @@ impl Tunables { debug_guest: false, concurrency_support: true, + recording: false, + floats_enabled: true, } } diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs -index 60c88a2c..25ae8261 100644 +index 5f1d41e1c..a32e68642 100644 --- a/crates/environ/src/vmoffsets.rs +++ b/crates/environ/src/vmoffsets.rs -@@ -243,6 +243,16 @@ pub trait PtrSize { +@@ -250,6 +250,16 @@ pub trait PtrSize { self.vmstore_context_stack_chain() + self.size_of_vmstack_chain() } @@ -1002,7 +982,7 @@ index 60c88a2c..25ae8261 100644 /// The offset of the `base` field. diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml -index 7ff85259..71e2e6ee 100644 +index 05b2f10d7..429ffd4fe 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -17,6 +17,8 @@ workspace = true @@ -1015,10 +995,10 @@ index 7ff85259..71e2e6ee 100644 wasmtime-jit-debug = { workspace = true, optional = true } wasmtime-jit-icache-coherence = { workspace = true, optional = true } diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs -index 6c611d54..1cbbd4b2 100644 +index 5dd0da610..0b00c8395 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs -@@ -1037,6 +1037,17 @@ impl Config { +@@ -1075,6 +1075,17 @@ impl Config { self } @@ -1036,7 +1016,7 @@ index 6c611d54..1cbbd4b2 100644 /// Configures whether the [WebAssembly bulk memory operations /// proposal][proposal] will be enabled for compilation. /// -@@ -1521,6 +1532,15 @@ impl Config { +@@ -1559,6 +1570,15 @@ impl Config { self } @@ -1052,20 +1032,11 @@ index 6c611d54..1cbbd4b2 100644 /// Sets a custom memory creator. /// /// Custom memory creators are used when creating host `Memory` objects or when -@@ -2210,7 +2230,7 @@ impl Config { - | WasmFeatures::CM_THREADING - | WasmFeatures::CM_ERROR_CONTEXT - | WasmFeatures::CM_GC -- | WasmFeatures::CM_FIXED_SIZE_LIST; -+ | WasmFeatures::CM_FIXED_LENGTH_LISTS; - - #[allow(unused_mut, reason = "easier to avoid #[cfg]")] - let mut unsupported = !features_known_to_wasmtime; diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs -index 9b17cbb8..a01c1e66 100644 +index eab3c8e61..9d62dcb0c 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs -@@ -270,6 +270,7 @@ impl Metadata<'_> { +@@ -308,6 +308,7 @@ impl Metadata<'_> { relaxed_simd_deterministic, winch_callable, signals_based_traps, @@ -1073,7 +1044,7 @@ index 9b17cbb8..a01c1e66 100644 memory_init_cow, inlining, inlining_intra_module, -@@ -340,6 +341,11 @@ impl Metadata<'_> { +@@ -380,6 +381,11 @@ impl Metadata<'_> { other.signals_based_traps, "Signals-based traps", )?; @@ -1086,10 +1057,10 @@ index 9b17cbb8..a01c1e66 100644 memory_init_cow, other.memory_init_cow, diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs -index 4915240b..e509feba 100644 +index 51dc8e253..b105a7c06 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs -@@ -544,6 +544,9 @@ pub use self::error::{Error, Result, bail, ensure, format_err}; +@@ -539,6 +539,9 @@ pub use self::error::{Error, Result, bail, ensure, format_err}; #[cfg(feature = "reexport-wasmparser")] pub use wasmparser; @@ -1100,10 +1071,10 @@ index 4915240b..e509feba 100644 fn _assertions_lib() { diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs -index d8ce5016..c19cf62f 100644 +index 66044e2de..7315339ef 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs -@@ -1392,6 +1392,32 @@ impl Func { +@@ -1393,6 +1393,32 @@ impl Func { } } @@ -1136,7 +1107,7 @@ index d8ce5016..c19cf62f 100644 /// Prepares for entrance into WebAssembly. /// /// This function will set up context such that `closure` is allowed to call a -@@ -1426,6 +1452,51 @@ pub(crate) fn invoke_wasm_and_catch_traps( +@@ -1427,6 +1453,51 @@ pub(crate) fn invoke_wasm_and_catch_traps( core::mem::drop(previous_runtime_state); store.0.call_hook(CallHook::ReturningFromWasm)?; result @@ -1189,10 +1160,10 @@ index d8ce5016..c19cf62f 100644 /// This type helps managing the state of the runtime when entering and exiting diff --git a/crates/wasmtime/src/runtime/instance.rs b/crates/wasmtime/src/runtime/instance.rs -index 2a55d962..0c882e74 100644 +index 104d1d65d..f2619dc56 100644 --- a/crates/wasmtime/src/runtime/instance.rs +++ b/crates/wasmtime/src/runtime/instance.rs -@@ -630,7 +630,6 @@ impl Instance { +@@ -646,7 +646,6 @@ impl Instance { /// Returns both exported and non-exported memories. /// /// Gives access to the full memories space. @@ -1201,10 +1172,10 @@ index 2a55d962..0c882e74 100644 &'a self, store: &'a StoreOpaque, diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs -index f214fff5..16e617d2 100644 +index 97e2fd5ba..78a8e4567 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs -@@ -108,6 +108,7 @@ use crate::{Engine, Module, Val, ValRaw, module::ModuleRegistry}; +@@ -104,6 +104,7 @@ use crate::{Engine, Module, Val, ValRaw, module::ModuleRegistry}; #[cfg(feature = "gc")] use crate::{ExnRef, Rooted}; use crate::{Global, Instance, Table}; @@ -1212,17 +1183,17 @@ index f214fff5..16e617d2 100644 use core::convert::Infallible; use core::fmt; use core::marker; -@@ -571,6 +572,9 @@ pub struct StoreOpaque { - /// logic before returning to allow execution to resume. +@@ -569,6 +570,9 @@ pub struct StoreOpaque { + /// enabled, so the key-space is unique for each store.) #[cfg(feature = "debug")] - breakpoints: BreakpointState, + frame_data_cache: FrameDataCache, + + /// Context for the GenVM. + pub genvm_ctx: GenVMCtx, } /// Self-pointer to `StoreInner` from within a `StoreOpaque` which is chiefly -@@ -717,6 +721,14 @@ enum StoreInstanceKind { +@@ -715,6 +719,14 @@ enum StoreInstanceKind { Dummy, } @@ -1237,7 +1208,7 @@ index f214fff5..16e617d2 100644 impl Store { /// Creates a new [`Store`] to be associated with the given [`Engine`] and /// `data` provided. -@@ -727,14 +739,14 @@ impl Store { +@@ -725,14 +737,14 @@ impl Store { /// The store will limit the number of instances, linear memories, and /// tables created to 10,000. This can be overridden with the /// [`Store::limiter`] configuration method. @@ -1252,18 +1223,18 @@ index f214fff5..16e617d2 100644 /// Like `Store::new` but returns an error on allocation failure. - pub fn try_new(engine: &Engine, data: T) -> Result { + pub fn try_new(engine: &Engine, data: T, genvm_ctx: GenVMCtx) -> Result { - let store_data = StoreData::new(); + let store_data = StoreData::new(engine); log::trace!("creating new store {:?}", store_data.id()); -@@ -799,6 +811,7 @@ impl Store { - }, - #[cfg(feature = "debug")] +@@ -778,6 +790,7 @@ impl Store { breakpoints: Default::default(), + #[cfg(feature = "debug")] + frame_data_cache: FrameDataCache::new(), + genvm_ctx, }; let mut inner = try_new::>(StoreInner { inner, -@@ -2948,11 +2961,11 @@ impl StoreInner { +@@ -2827,11 +2840,11 @@ impl StoreInner { } } @@ -1281,10 +1252,10 @@ index f214fff5..16e617d2 100644 impl fmt::Debug for Store { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/crates/wasmtime/src/runtime/vm/vmcontext.rs b/crates/wasmtime/src/runtime/vm/vmcontext.rs -index c3287979..01e3373a 100644 +index aac495af2..a80eed44a 100644 --- a/crates/wasmtime/src/runtime/vm/vmcontext.rs +++ b/crates/wasmtime/src/runtime/vm/vmcontext.rs -@@ -1179,6 +1179,9 @@ pub struct VMStoreContext { +@@ -1212,6 +1212,9 @@ pub struct VMStoreContext { /// `store-data-address` unsafe intrinsic. pub store_data: VmPtr<()>, @@ -1294,7 +1265,7 @@ index c3287979..01e3373a 100644 /// The range, in addresses, of the guard page that is currently in use. /// /// This field is used when signal handlers are run to determine whether a -@@ -1271,8 +1274,10 @@ impl Default for VMStoreContext { +@@ -1305,8 +1308,10 @@ impl Default for VMStoreContext { last_wasm_entry_sp: UnsafeCell::new(0), last_wasm_entry_trap_handler: UnsafeCell::new(0), stack_chain: UnsafeCell::new(VMStackChain::Absent), @@ -1307,7 +1278,7 @@ index c3287979..01e3373a 100644 } } diff --git a/crates/wiggle/generate/src/config.rs b/crates/wiggle/generate/src/config.rs -index 43dd2bff..77a0528a 100644 +index 43dd2bffa..77a0528a4 100644 --- a/crates/wiggle/generate/src/config.rs +++ b/crates/wiggle/generate/src/config.rs @@ -251,7 +251,12 @@ impl Parse for Paths { @@ -1325,7 +1296,7 @@ index 43dd2bff..77a0528a 100644 .collect::>(); diff --git a/crates/wiggle/generate/src/module_trait.rs b/crates/wiggle/generate/src/module_trait.rs -index 598e3ff4..73b18731 100644 +index 598e3ff46..73b18731b 100644 --- a/crates/wiggle/generate/src/module_trait.rs +++ b/crates/wiggle/generate/src/module_trait.rs @@ -81,13 +81,6 @@ pub fn define_module_trait(m: &Module, settings: &CodegenSettings) -> TokenStrea @@ -1343,7 +1314,7 @@ index 598e3ff4..73b18731 100644 } } diff --git a/crates/wiggle/generate/src/wasmtime.rs b/crates/wiggle/generate/src/wasmtime.rs -index bea34fb3..ad861408 100644 +index bea34fb3a..ad8614086 100644 --- a/crates/wiggle/generate/src/wasmtime.rs +++ b/crates/wiggle/generate/src/wasmtime.rs @@ -2,6 +2,7 @@ use crate::CodegenSettings; @@ -1458,7 +1429,7 @@ index bea34fb3..ad861408 100644 #field_str, move |mut caller: wiggle::wasmtime_crate::Caller<'_, T> #(, #arg_decls)*| -> wiggle::error::Result<#ret_ty> { diff --git a/crates/wiggle/src/guest_error.rs b/crates/wiggle/src/guest_error.rs -index 590ee16e..03b79823 100644 +index 590ee16e8..03b798232 100644 --- a/crates/wiggle/src/guest_error.rs +++ b/crates/wiggle/src/guest_error.rs @@ -27,4 +27,6 @@ pub enum GuestError { @@ -1469,7 +1440,7 @@ index 590ee16e..03b79823 100644 + MemoryNotExported, } diff --git a/crates/wiggle/src/lib.rs b/crates/wiggle/src/lib.rs -index 1888a1ff..c8953ab9 100644 +index 1888a1ff2..c8953ab92 100644 --- a/crates/wiggle/src/lib.rs +++ b/crates/wiggle/src/lib.rs @@ -271,6 +271,11 @@ impl<'a> GuestMemory<'a> { diff --git a/.git-third-party/patches/executor/third-party/wasmtime/2 b/.git-third-party/patches/executor/third-party/wasmtime/2 index 9f6f844c..0bbfa025 100644 --- a/.git-third-party/patches/executor/third-party/wasmtime/2 +++ b/.git-third-party/patches/executor/third-party/wasmtime/2 @@ -19,10 +19,10 @@ Co-Authored-By: Claude Opus 4.8 (1M context) 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs -index c19cf62f..c09f17b5 100644 +index 7315339ef..358ae2f61 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs -@@ -1418,6 +1418,53 @@ impl std::fmt::Display for Fingerprint { +@@ -1419,6 +1419,53 @@ impl std::fmt::Display for Fingerprint { } } @@ -76,7 +76,7 @@ index c19cf62f..c09f17b5 100644 /// Prepares for entrance into WebAssembly. /// /// This function will set up context such that `closure` is allowed to call a -@@ -1451,52 +1498,10 @@ pub(crate) fn invoke_wasm_and_catch_traps( +@@ -1452,52 +1499,10 @@ pub(crate) fn invoke_wasm_and_catch_traps( } core::mem::drop(previous_runtime_state); store.0.call_hook(CallHook::ReturningFromWasm)?; @@ -133,10 +133,10 @@ index c19cf62f..c09f17b5 100644 /// This type helps managing the state of the runtime when entering and exiting diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs -index 16e617d2..3656a449 100644 +index 78a8e4567..789a8bb71 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs -@@ -725,8 +725,6 @@ enum StoreInstanceKind { +@@ -723,8 +723,6 @@ enum StoreInstanceKind { pub struct GenVMCtx { /// non-zero if should quit pub should_quit: Arc, diff --git a/.git-third-party/patches/executor/third-party/wasmtime/3 b/.git-third-party/patches/executor/third-party/wasmtime/3 index 43aead07..f49cc5cd 100644 --- a/.git-third-party/patches/executor/third-party/wasmtime/3 +++ b/.git-third-party/patches/executor/third-party/wasmtime/3 @@ -18,10 +18,10 @@ Claude-Session: https://claude.ai/code/session_013QtkVNJFxWsNwCLhTp5idV 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/cranelift/src/translate/code_translator.rs b/crates/cranelift/src/translate/code_translator.rs -index 9dde783c..927df0f8 100644 +index ad613df54..7517b54d1 100644 --- a/crates/cranelift/src/translate/code_translator.rs +++ b/crates/cranelift/src/translate/code_translator.rs -@@ -1750,7 +1750,8 @@ pub fn translate_operator( +@@ -1751,7 +1751,8 @@ pub fn translate_operator( } Operator::F32x4Splat | Operator::F64x2Splat => { @@ -31,7 +31,7 @@ index 9dde783c..927df0f8 100644 let splatted = builder.ins().splat(type_of(op), environ.stacks.pop1()); environ.stacks.push1(splatted) } -@@ -1839,7 +1840,7 @@ pub fn translate_operator( +@@ -1840,7 +1841,7 @@ pub fn translate_operator( } Operator::F32x4ExtractLane { lane } | Operator::F64x2ExtractLane { lane } => { @@ -40,7 +40,7 @@ index 9dde783c..927df0f8 100644 let vector = pop1_with_bitcast(environ, type_of(op), builder); environ .stacks -@@ -1864,7 +1865,7 @@ pub fn translate_operator( +@@ -1865,7 +1866,7 @@ pub fn translate_operator( } Operator::F32x4ReplaceLane { lane } | Operator::F64x2ReplaceLane { lane } => { diff --git a/.git-third-party/patches/executor/third-party/wasmtime/4 b/.git-third-party/patches/executor/third-party/wasmtime/4 index 3ccf9edb..b685dcf7 100644 --- a/.git-third-party/patches/executor/third-party/wasmtime/4 +++ b/.git-third-party/patches/executor/third-party/wasmtime/4 @@ -11,14 +11,14 @@ Content-Transfer-Encoding: 8bit crates/cranelift/src/func_environ.rs | 4 ++-- crates/cranelift/src/lib.rs | 4 ++-- crates/cranelift/src/translate/code_translator.rs | 2 +- - crates/environ/src/trap_encoding.rs | 8 ++++---- - 4 files changed, 9 insertions(+), 9 deletions(-) + crates/environ/src/trap_encoding.rs | 4 ++-- + 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs -index 8f549ff5..0c5821fa 100644 +index ec49b7acf..c2ed7b2ba 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs -@@ -3929,9 +3929,9 @@ impl FuncEnvironment<'_> { +@@ -3952,9 +3952,9 @@ impl FuncEnvironment<'_> { self.fuel_save_from_var(builder); } @@ -31,10 +31,10 @@ index 8f549ff5..0c5821fa 100644 } diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs -index 4db70f6a..8119e7da 100644 +index 66c56b849..6a3a89af7 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs -@@ -72,8 +72,8 @@ pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode = +@@ -73,8 +73,8 @@ pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode = TrapCode::unwrap_user(Trap::ContinuationAlreadyConsumed as u8 + TRAP_OFFSET); pub const TRAP_CAST_FAILURE: TrapCode = TrapCode::unwrap_user(Trap::CastFailure as u8 + TRAP_OFFSET); @@ -46,10 +46,10 @@ index 4db70f6a..8119e7da 100644 /// Creates a new cranelift `Signature` with no wasm params/results for the /// given calling convention. diff --git a/crates/cranelift/src/translate/code_translator.rs b/crates/cranelift/src/translate/code_translator.rs -index 927df0f8..b5cf3d17 100644 +index 7517b54d1..a5f477580 100644 --- a/crates/cranelift/src/translate/code_translator.rs +++ b/crates/cranelift/src/translate/code_translator.rs -@@ -4574,6 +4574,6 @@ fn float_op_unreachable_check(environ: &mut FuncEnvironment<'_>, builder: &mut F +@@ -4575,6 +4575,6 @@ fn float_op_unreachable_check(environ: &mut FuncEnvironment<'_>, builder: &mut F if environ.are_floats_enabled() { return false; } @@ -58,35 +58,17 @@ index 927df0f8..b5cf3d17 100644 return true; } diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs -index 2d49707b..fe4f0dea 100644 +index f2c969e1e..1c18d90ea 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs -@@ -142,8 +142,8 @@ pub enum Trap { - /// value. - UnalignedPointer, +@@ -216,8 +216,8 @@ generate_trap_type! { + /// Cannot resume a thread which is not suspended. + CannotResumeThread = "cannot resume thread which is not suspended", -- /// Deterministic mode violation -- DeterministicMode, -+ /// Nondeterministic instruction executed in deterministic mode -+ NondetInstruction, - // if adding a variant here be sure to update the `check!` macro below, and - // remember to update `trap.rs` and `trap.h` as mentioned above - } -@@ -196,7 +196,7 @@ impl Trap { - ListOutOfBounds - InvalidDiscriminant - UnalignedPointer -- DeterministicMode -+ NondetInstruction - } +- /// Deterministic mode violation. +- DeterministicMode = "deterministic mode violation (cpu)", ++ /// Nondeterministic instruction executed in deterministic mode. ++ NondetInstruction = "nondeterministic instruction (cpu)", - None -@@ -242,7 +242,7 @@ impl fmt::Display for Trap { - ListOutOfBounds => "list content out-of-bounds", - InvalidDiscriminant => "invalid variant discriminant", - UnalignedPointer => "unaligned pointer", -- DeterministicMode => "deterministic mode violation (cpu)", -+ NondetInstruction => "nondeterministic instruction (cpu)", - }; - write!(f, "wasm trap: {desc}") - } + // if adding a variant here be sure to update `trap.rs` and `trap.h` as + // mentioned above diff --git a/.git-third-party/patches/executor/third-party/wasmtime/5 b/.git-third-party/patches/executor/third-party/wasmtime/5 index 199319ca..1ec1cc72 100644 --- a/.git-third-party/patches/executor/third-party/wasmtime/5 +++ b/.git-third-party/patches/executor/third-party/wasmtime/5 @@ -10,10 +10,10 @@ Subject: [PATCH] feat(genvm): configure wasm stack limits 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs -index 1cbbd4b2..746ae852 100644 +index 0b00c8395..06bbd731a 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs -@@ -160,6 +160,8 @@ pub struct Config { +@@ -163,6 +163,8 @@ pub struct Config { pub(crate) custom_code_memory: Option>, pub(crate) allocation_strategy: InstanceAllocationStrategy, pub(crate) max_wasm_stack: usize, @@ -22,16 +22,16 @@ index 1cbbd4b2..746ae852 100644 /// Explicitly enabled features via `Config::wasm_*` methods. This is a /// signal that the embedder specifically wants something turned on /// regardless of the defaults that Wasmtime might otherwise have enabled. -@@ -274,6 +276,8 @@ impl Config { +@@ -277,6 +279,8 @@ impl Config { // 1` forces this), or at least it passed when this change was // committed. max_wasm_stack: 512 * 1024, + wasm_call_stack_limit: 1024, + wasm_value_stack_limit: 65535, - wasm_backtrace: true, wasm_backtrace_details_env_used: false, + wasm_backtrace_max_frames: Some(DEFAULT_WASM_BACKTRACE_MAX_FRAMES), native_unwind_info: None, -@@ -741,6 +745,16 @@ impl Config { +@@ -779,6 +783,16 @@ impl Config { self } @@ -49,10 +49,10 @@ index 1cbbd4b2..746ae852 100644 /// /// This setting configures the size of the stacks that are allocated for diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs -index 3656a449..ce31edb4 100644 +index 789a8bb71..e80dd5142 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs -@@ -753,7 +753,10 @@ impl Store { +@@ -751,7 +751,10 @@ impl Store { let inner = StoreOpaque { _marker: marker::PhantomPinned, engine: engine.clone(), @@ -65,10 +65,10 @@ index 3656a449..ce31edb4 100644 continuations: Vec::new(), instances: wasmtime_environ::collections::PrimaryMap::new(), diff --git a/crates/wasmtime/src/runtime/vm/vmcontext.rs b/crates/wasmtime/src/runtime/vm/vmcontext.rs -index 01e3373a..cc0421c3 100644 +index a80eed44a..b6a441901 100644 --- a/crates/wasmtime/src/runtime/vm/vmcontext.rs +++ b/crates/wasmtime/src/runtime/vm/vmcontext.rs -@@ -1196,6 +1196,14 @@ pub struct VMStoreContext { +@@ -1229,6 +1229,14 @@ pub struct VMStoreContext { } impl VMStoreContext { diff --git a/.git-third-party/patches/executor/third-party/wasmtime/6 b/.git-third-party/patches/executor/third-party/wasmtime/6 new file mode 100644 index 00000000..d7419aed --- /dev/null +++ b/.git-third-party/patches/executor/third-party/wasmtime/6 @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Edgars +Date: Fri, 31 Jul 2026 09:52:19 +0100 +Subject: [PATCH] fix(genvm): preserve Store API and fingerprint all instances + +--- + crates/wasmtime/src/config.rs | 4 +-- + crates/wasmtime/src/runtime/func.rs | 19 ++++++----- + crates/wasmtime/src/runtime/store.rs | 38 +++++++++++++++++----- + crates/wasmtime/tests/genvm_fingerprint.rs | 29 +++++++++++++++++ + 4 files changed, 72 insertions(+), 18 deletions(-) + create mode 100644 crates/wasmtime/tests/genvm_fingerprint.rs + +diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs +index 06bbd731a..583319e2b 100644 +--- a/crates/wasmtime/src/config.rs ++++ b/crates/wasmtime/src/config.rs +@@ -279,8 +279,8 @@ impl Config { + // 1` forces this), or at least it passed when this change was + // committed. + max_wasm_stack: 512 * 1024, +- wasm_call_stack_limit: 1024, +- wasm_value_stack_limit: 65535, ++ wasm_call_stack_limit: u32::MAX, ++ wasm_value_stack_limit: u32::MAX, + wasm_backtrace_details_env_used: false, + wasm_backtrace_max_frames: Some(DEFAULT_WASM_BACKTRACE_MAX_FRAMES), + native_unwind_info: None, +diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs +index 358ae2f61..6e20d5afa 100644 +--- a/crates/wasmtime/src/runtime/func.rs ++++ b/crates/wasmtime/src/runtime/func.rs +@@ -1442,13 +1442,18 @@ impl<'a, T: 'static> StoreContextMut<'a, T> { + }; + + for inst in store.0.all_instances().collect::>() { +- let mut mod_fp = ModuleFingerprint { +- memories: Vec::new(), +- }; +- + let inst_mod_name = inst.module(&mut store.0).name().unwrap_or("").to_owned(); +- +- for mem in inst.all_memories(store.0.store_opaque_mut()).collect::>() { ++ let mod_fp = ++ fp.module_instances ++ .entry(inst_mod_name) ++ .or_insert_with(|| ModuleFingerprint { ++ memories: Vec::new(), ++ }); ++ ++ for mem in inst ++ .all_memories(store.0.store_opaque_mut()) ++ .collect::>() ++ { + let data = match &mem.1 { + crate::runtime::vm::ExportMemory::Unshared(m) => m.data(&store), + crate::runtime::vm::ExportMemory::Shared(_sm, _) => &[], +@@ -1458,8 +1463,6 @@ impl<'a, T: 'static> StoreContextMut<'a, T> { + .memories + .push(MemoryFingerprint(blake3::hash(data).into())); + } +- +- fp.module_instances.insert(inst_mod_name, mod_fp); + } + + fp +diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs +index e80dd5142..6910ae6e2 100644 +--- a/crates/wasmtime/src/runtime/store.rs ++++ b/crates/wasmtime/src/runtime/store.rs +@@ -725,6 +725,14 @@ pub struct GenVMCtx { + pub should_quit: Arc, + } + ++impl Default for GenVMCtx { ++ fn default() -> Self { ++ Self { ++ should_quit: Arc::new(std::sync::atomic::AtomicU32::new(0)), ++ } ++ } ++} ++ + impl Store { + /// Creates a new [`Store`] to be associated with the given [`Engine`] and + /// `data` provided. +@@ -735,14 +743,28 @@ impl Store { + /// The store will limit the number of instances, linear memories, and + /// tables created to 10,000. This can be overridden with the + /// [`Store::limiter`] configuration method. +- pub fn new(engine: &Engine, data: T, genvm_ctx: GenVMCtx) -> Self { +- Self::try_new(engine, data, genvm_ctx).expect( ++ pub fn new(engine: &Engine, data: T) -> Self { ++ Self::try_new(engine, data).expect( + "allocation failure during `Store::new` (use `Store::try_new` to handle such errors)", + ) + } + + /// Like `Store::new` but returns an error on allocation failure. +- pub fn try_new(engine: &Engine, data: T, genvm_ctx: GenVMCtx) -> Result { ++ pub fn try_new(engine: &Engine, data: T) -> Result { ++ Self::try_new_with_genvm_ctx(engine, data, GenVMCtx::default()) ++ } ++ ++ /// Creates a new [`Store`] with GenVM-specific runtime context. ++ pub fn new_with_genvm_ctx(engine: &Engine, data: T, genvm_ctx: GenVMCtx) -> Self { ++ Self::try_new_with_genvm_ctx(engine, data, genvm_ctx).expect( ++ "allocation failure during `Store::new_with_genvm_ctx` \ ++ (use `Store::try_new_with_genvm_ctx` to handle such errors)", ++ ) ++ } ++ ++ /// Like [`Store::new_with_genvm_ctx`] but returns an error on allocation ++ /// failure. ++ pub fn try_new_with_genvm_ctx(engine: &Engine, data: T, genvm_ctx: GenVMCtx) -> Result { + let store_data = StoreData::new(engine); + log::trace!("creating new store {:?}", store_data.id()); + +@@ -2841,11 +2863,11 @@ impl StoreInner { + } + } + +-// impl Default for Store { +-// fn default() -> Store { +-// Store::new(&Engine::default(), T::default()) +-// } +-// } ++impl Default for Store { ++ fn default() -> Store { ++ Store::new(&Engine::default(), T::default()) ++ } ++} + + impl fmt::Debug for Store { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +diff --git a/crates/wasmtime/tests/genvm_fingerprint.rs b/crates/wasmtime/tests/genvm_fingerprint.rs +new file mode 100644 +index 000000000..b78054e6d +--- /dev/null ++++ b/crates/wasmtime/tests/genvm_fingerprint.rs +@@ -0,0 +1,29 @@ ++use wasmtime::{Engine, Instance, Module, Store}; ++ ++#[test] ++fn fingerprint_includes_every_instance_with_the_same_module_name() { ++ let engine = Engine::default(); ++ let module = Module::new( ++ &engine, ++ r#" ++ (module $same ++ (memory (export "memory") 1) ++ ) ++ "#, ++ ) ++ .unwrap(); ++ let mut store = Store::new(&engine, ()); ++ let first = Instance::new(&mut store, &module, &[]).unwrap(); ++ let _second = Instance::new(&mut store, &module, &[]).unwrap(); ++ ++ first ++ .get_memory(&mut store, "memory") ++ .unwrap() ++ .write(&mut store, 0, &[1]) ++ .unwrap(); ++ ++ let fingerprint = store.fingerprint(); ++ let memories = &fingerprint.module_instances["same"].memories; ++ assert_eq!(memories.len(), 2); ++ assert_ne!(memories[0], memories[1]); ++} diff --git a/executor/Cargo.lock b/executor/Cargo.lock index d1028bdd..4e0b1745 100644 --- a/executor/Cargo.lock +++ b/executor/Cargo.lock @@ -251,9 +251,9 @@ checksum = "ece5ad97cde626d9fb807bf2dd4b4c4d13d7317a93a2ee0f8f9ef6389850a49e" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" dependencies = [ "allocator-api2", ] @@ -446,28 +446,29 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-entity", + "wasmtime-internal-core", ] [[package]] name = "cranelift-bitset" -version = "0.129.1" +version = "0.130.2" dependencies = [ "serde", "serde_derive", @@ -476,7 +477,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.129.1" +version = "0.130.2" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -488,7 +489,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli 0.33.0", - "hashbrown 0.15.2", + "hashbrown 0.16.1", "libm", "log", "pulley-interpreter", @@ -502,7 +503,7 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -513,18 +514,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.129.1" +version = "0.130.2" [[package]] name = "cranelift-control" -version = "0.129.1" +version = "0.130.2" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-bitset", "serde", @@ -534,7 +535,7 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-codegen", "log", @@ -544,11 +545,11 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.129.1" +version = "0.130.2" [[package]] name = "cranelift-native" -version = "0.129.1" +version = "0.130.2" dependencies = [ "cranelift-codegen", "libc", @@ -557,7 +558,7 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.129.1" +version = "0.130.2" [[package]] name = "crc32fast" @@ -1030,6 +1031,7 @@ dependencies = [ "wasmparser", "wasmtime", "wasmtime-internal-cache", + "wat", "wiggle", "zip", ] @@ -1161,6 +1163,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "heck" version = "0.5.0" @@ -1568,12 +1576,12 @@ dependencies = [ [[package]] name = "object" -version = "0.37.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown 0.16.1", "indexmap 2.13.0", "memchr", ] @@ -1728,7 +1736,7 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cranelift-bitset", "log", @@ -1738,7 +1746,7 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "42.0.1" +version = "43.0.2" dependencies = [ "proc-macro2", "quote", @@ -1868,13 +1876,13 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.13.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" +checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown 0.17.1", "log", "rustc-hash", "smallvec", @@ -2508,6 +2516,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -2613,7 +2627,7 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.245.1" +version = "0.245.0" dependencies = [ "leb128fmt", "wasmparser", @@ -2621,7 +2635,7 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.245.1" +version = "0.245.0" dependencies = [ "bitflags", "hashbrown 0.16.1", @@ -2632,7 +2646,7 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.245.1" +version = "0.245.0" dependencies = [ "anyhow", "termcolor", @@ -2641,7 +2655,7 @@ dependencies = [ [[package]] name = "wasmtime" -version = "42.0.1" +version = "43.0.2" dependencies = [ "addr2line 0.26.0", "async-trait", @@ -2654,7 +2668,7 @@ dependencies = [ "log", "mach2", "memfd", - "object 0.37.3", + "object 0.38.1", "once_cell", "postcard", "pulley-interpreter", @@ -2681,21 +2695,23 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "42.0.1" +version = "43.0.2" dependencies = [ "anyhow", "cpp_demangle", + "cranelift-bforest", "cranelift-bitset", "cranelift-entity", "gimli 0.33.0", - "hashbrown 0.15.2", + "hashbrown 0.16.1", "indexmap 2.13.0", "log", - "object 0.37.3", + "object 0.38.1", "postcard", "rustc-demangle", "serde", "serde_derive", + "sha2", "smallvec", "target-lexicon", "wasm-encoder", @@ -2706,7 +2722,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-cache" -version = "42.0.1" +version = "43.0.2" dependencies = [ "base64", "directories-next", @@ -2724,7 +2740,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-macro" -version = "42.0.1" +version = "43.0.2" dependencies = [ "anyhow", "proc-macro2", @@ -2737,19 +2753,21 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "42.0.1" +version = "43.0.2" [[package]] name = "wasmtime-internal-core" -version = "42.0.1" +version = "43.0.2" dependencies = [ "anyhow", + "hashbrown 0.16.1", "libm", + "serde", ] [[package]] name = "wasmtime-internal-cranelift" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cfg-if", "cranelift-codegen", @@ -2760,7 +2778,7 @@ dependencies = [ "gimli 0.33.0", "itertools", "log", - "object 0.37.3", + "object 0.38.1", "pulley-interpreter", "smallvec", "target-lexicon", @@ -2774,7 +2792,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cc", "cfg-if", @@ -2787,7 +2805,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cc", "wasmtime-internal-versioned-export-macros", @@ -2795,7 +2813,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cfg-if", "libc", @@ -2805,18 +2823,18 @@ dependencies = [ [[package]] name = "wasmtime-internal-unwinder" -version = "42.0.1" +version = "43.0.2" dependencies = [ "cfg-if", "cranelift-codegen", "log", - "object 0.37.3", + "object 0.38.1", "wasmtime-environ", ] [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "42.0.1" +version = "43.0.2" dependencies = [ "proc-macro2", "quote", @@ -2825,7 +2843,7 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "42.0.1" +version = "43.0.2" dependencies = [ "anyhow", "bitflags", @@ -2843,9 +2861,27 @@ dependencies = [ "leb128", ] +[[package]] +name = "wast" +version = "245.0.0" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width", + "wasm-encoder", +] + +[[package]] +name = "wat" +version = "1.245.0" +dependencies = [ + "wast 245.0.0", +] + [[package]] name = "wiggle" -version = "42.0.1" +version = "43.0.2" dependencies = [ "bitflags", "thiserror 2.0.18", @@ -2857,7 +2893,7 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "42.0.1" +version = "43.0.2" dependencies = [ "heck", "proc-macro2", @@ -2869,7 +2905,7 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "42.0.1" +version = "43.0.2" dependencies = [ "proc-macro2", "quote", @@ -3084,7 +3120,7 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.245.1" +version = "0.245.0" dependencies = [ "anyhow", "hashbrown 0.16.1", @@ -3108,7 +3144,7 @@ dependencies = [ "anyhow", "log", "thiserror 1.0.69", - "wast", + "wast 35.0.2", ] [[package]] diff --git a/executor/Cargo.toml b/executor/Cargo.toml index f95967a3..5d8118ef 100644 --- a/executor/Cargo.toml +++ b/executor/Cargo.toml @@ -133,3 +133,4 @@ zip = "4.0.0" [dev-dependencies] afl = { version = "0.15.18", features = ["no_cfg_fuzzing"] } libc = "0.2.162" +wat = { path = "third-party/wasm-tools/crates/wat" } diff --git a/executor/src/exe/check.rs b/executor/src/exe/check.rs index e9d3da25..5968c169 100644 --- a/executor/src/exe/check.rs +++ b/executor/src/exe/check.rs @@ -10,7 +10,7 @@ pub struct Args { #[arg( long, default_value_t = false, - help = "after verification, precompile all runners into the on-disk cache" + help = "after verification, precompile all runners (currently disabled)" )] precompile: bool, } diff --git a/executor/src/exe/precompile.rs b/executor/src/exe/precompile.rs index ac4e8321..9767e7ec 100644 --- a/executor/src/exe/precompile.rs +++ b/executor/src/exe/precompile.rs @@ -1,7 +1,4 @@ -use std::collections::BTreeMap; - -use anyhow::Context as _; -use genvm::{caching, config, runners, wasmtime_to_anyhow}; +use genvm::{caching, config}; use genvm_common::*; @@ -15,102 +12,6 @@ pub struct Args { info: bool, } -fn compile_single_file_single_mode( - result_path: &std::path::Path, - engine: &wasmtime::Engine, - wasm_data: &[u8], - engine_type: &str, - runner_path: &std::path::Path, - path_in_runner: &str, -) -> anyhow::Result<()> { - let time_start = std::time::Instant::now(); - let precompiled = engine - .precompile_module(wasm_data) - .map_err(wasmtime_to_anyhow) - .with_context(|| "precompiling")?; - - log_info!(engine = engine_type, runner:? = runner_path, runner_path:? = path_in_runner, duration:? = time_start.elapsed(); "wasm compilation done"); - - std::fs::create_dir_all( - result_path - .parent() - .expect("precompiled wasm path has no parent directory"), - ) - .with_context(|| format!("creating directory for {result_path:?}"))?; - - let sz = precompiled.len(); - - std::fs::write(result_path, precompiled) - .with_context(|| format!("writing to {result_path:?}"))?; - - log_info!("size" = sz, result:? = result_path, engine = engine_type, runner:? = runner_path, runner_path:? = path_in_runner, duration:? = time_start.elapsed(); "wasm writing done"); - - Ok(()) -} - -fn compile_single_file( - precompile_dir: &std::path::Path, - engines: &genvm::rt::DetNondet, - runners_dir: &std::path::Path, - zip_path: &std::path::Path, -) -> anyhow::Result<()> { - let base_path = zip_path - .strip_prefix(runners_dir) - .with_context(|| format!("stripping {runners_dir:?} from {runners_dir:?}"))?; - - let base_path = if let Some(no_stem) = base_path.file_stem() { - base_path.with_file_name(no_stem) - } else { - base_path.to_owned() - }; - - let mut result_dir_path = precompile_dir.to_owned(); - result_dir_path.push(base_path); - - let data = util::mmap_file(zip_path).with_context(|| format!("memory mapping {zip_path:?}"))?; - - let arch = genvm::runners::Archive::from_ustar(bytes::Bytes::copy_from_slice(data.as_ref())) - .with_context(|| format!("parsing ustar archive {zip_path:?}"))?; - - for (entry_name, contents) in arch - .data - .iter() - .filter(|(k, _v)| k.ends_with(".wasm") || k.ends_with(".so")) - { - if !wasmparser::Parser::is_core_wasm(contents.as_ref()) { - continue; - } - - let entry_name_hash = caching::path_in_zip_to_hash(entry_name); - let result_file = result_dir_path.join(entry_name_hash); - - compile_single_file_single_mode( - result_file - .with_extension(caching::DET_NON_DET_PRECOMPILED_SUFFIX.det) - .as_path(), - &engines.det, - contents.as_ref(), - caching::DET_NON_DET_PRECOMPILED_SUFFIX.det, - zip_path, - entry_name, - ) - .with_context(|| format!("processing det {entry_name}"))?; - - compile_single_file_single_mode( - result_file - .with_extension(caching::DET_NON_DET_PRECOMPILED_SUFFIX.non_det) - .as_path(), - &engines.non_det, - contents.as_ref(), - caching::DET_NON_DET_PRECOMPILED_SUFFIX.non_det, - zip_path, - entry_name, - ) - .with_context(|| format!("processing non-det {entry_name}"))?; - } - Ok(()) -} - pub fn handle(args: Args, config: config::Config) -> anyhow::Result<()> { if args.info { log_info!(version = genvm_common::version::CURRENT.clone(); "current version"); @@ -128,42 +29,9 @@ pub fn handle(args: Args, config: config::Config) -> anyhow::Result<()> { run(&config) } -/// Precompiles every runner listed in `all.json` into the on-disk cache. Shared -/// by the `precompile` subcommand and `check --precompile`. -pub fn run(config: &config::Config) -> anyhow::Result<()> { - log_info!(version = genvm_common::version::CURRENT.clone(); "current version"); - - let cache_dir = caching::get_cache_dir(&config.cache_dir)?; - let mut precompile_dir = cache_dir.clone(); - precompile_dir.push(caching::PRECOMPILE_DIR_NAME); - - let registry_dir = std::path::Path::new(&config.registry_dir); - - log_info!(cache_dir:? = cache_dir, precompile_dir:? = precompile_dir, registry_dir:? = registry_dir; "information"); - - let engines = genvm::rt::supervisor::create_engines(|conf| { - conf.cranelift_opt_level(wasmtime::OptLevel::Speed); - Ok(()) - })?; - - let all_json_path = registry_dir.join("all.json"); - let all_json = std::fs::read_to_string(&all_json_path) - .with_context(|| format!("reading {all_json_path:?}"))?; - let all: BTreeMap> = - serde_json::from_str(&all_json).with_context(|| format!("parsing {all_json_path:?}"))?; - - let runners_dir = std::path::Path::new(&config.runners_dir); - - for (runner_id, hashes) in all { - for hash in hashes { - let mut runner_path = runners_dir.to_owned(); - runners::append_runner_subpath(&runner_id, &hash, &mut runner_path); - runner_path.set_extension("tar"); - - compile_single_file(&precompile_dir, &engines, runners_dir, &runner_path) - .with_context(|| format!("processing {runner_path:?}"))?; - } - } - - Ok(()) +/// Disabled until precompiled native artifacts are immutable and authenticated. +pub fn run(_config: &config::Config) -> anyhow::Result<()> { + anyhow::bail!( + "the precompiled module cache is disabled until its artifacts are immutable and authenticated" + ) } diff --git a/executor/src/rt/supervisor/actions.rs b/executor/src/rt/supervisor/actions.rs index 597a5bff..991b1fc1 100644 --- a/executor/src/rt/supervisor/actions.rs +++ b/executor/src/rt/supervisor/actions.rs @@ -1,6 +1,6 @@ use std::collections::{BTreeMap, HashSet, VecDeque}; -use crate::{caching, public_abi, rt, runners}; +use crate::{public_abi, rt, runners}; use anyhow::Context as _; use genlayer_sdk::abi; @@ -773,57 +773,6 @@ impl Ctx<'_, '_> { Ok((id, pin)) } - fn load_modules( - &mut self, - current: symbol_table::GlobalSymbol, - path: &std::sync::Arc, - ) -> anyhow::Result>> { - let Some((id, hash)) = runners::verify_runner(current.as_str()) else { - return Ok(None); - }; - - let special_name = caching::path_in_zip_to_hash(path); - let Some(cache_dir) = &self.supervisor.wasm_mod_cache.cache_dir else { - return Ok(None); - }; - - let mut cache_dir = cache_dir.to_owned(); - cache_dir.push(caching::PRECOMPILE_DIR_NAME); - runners::append_runner_subpath(id, hash, &mut cache_dir); - cache_dir.push(special_name); - - let det_mod = cache_dir.with_extension(caching::DET_NON_DET_PRECOMPILED_SUFFIX.det); - - if !det_mod.exists() { - return Ok(None); - } - - cache_dir.set_extension(caching::DET_NON_DET_PRECOMPILED_SUFFIX.non_det); - let non_det_mod = cache_dir; - - if !det_mod.exists() { - return Ok(None); - } - - self.supervisor - .shared_data - .metrics - .supervisor - .precompile_hits - .increment(); - - Ok(Some(rt::DetNondet { - det: unsafe { - wasmtime::Module::deserialize_file(&self.supervisor.engines.det, &det_mod) - } - .with_context(|| format!("deserializing det module {path:?} of {current}"))?, - non_det: unsafe { - wasmtime::Module::deserialize_file(&self.supervisor.engines.non_det, &non_det_mod) - } - .with_context(|| format!("deserializing non-det module {path:?} of {current}"))?, - })) - } - async fn link_wasm( &mut self, contents: bytes::Bytes, @@ -841,14 +790,6 @@ impl Ctx<'_, '_> { .wasm_mod_cache .wasm_modules_cache .get_or_create(wasm_key, || async { - match self.load_modules(current, path) { - Ok(Some(loaded)) => return Ok(loaded), - Ok(None) => {} - Err(e) => { - log_error!(path:? = path, error:ah = e; "failed to load precompiled wasm module, recompiling"); - } - } - self.supervisor .compile_wasm(contents.as_ref(), wasm_key.as_str()) .await diff --git a/executor/src/rt/supervisor/compilation.rs b/executor/src/rt/supervisor/compilation.rs index c9e9bad1..92a2ecb9 100644 --- a/executor/src/rt/supervisor/compilation.rs +++ b/executor/src/rt/supervisor/compilation.rs @@ -4,37 +4,178 @@ use wiggle::error::Context as _; use crate::rt; use genvm_common::*; -impl super::Supervisor { - pub fn validate_wasm(&self, wasm: &[u8]) -> wasmtime::Result<()> { - use wasmparser::*; +pub(crate) const CONTRACT_WASM_FEATURES: wasmparser::WasmFeatures = + wasmparser::WasmFeatures::WASM2.union(wasmparser::WasmFeatures::TAIL_CALL); - let add_features = WasmFeatures::REFERENCE_TYPES.bits() | WasmFeatures::FLOATS.bits(); +fn is_nondeterministic_float_operator(operator: &wasmparser::Operator<'_>) -> bool { + use wasmparser::Operator::*; - let det_features = self.engines.det.config().get_features().bits() | add_features; + matches!( + operator, + F32Abs + | F32Neg + | F32Ceil + | F32Floor + | F32Trunc + | F32Nearest + | F32Sqrt + | F32Add + | F32Sub + | F32Mul + | F32Div + | F32Min + | F32Max + | F32Copysign + | F64Abs + | F64Neg + | F64Ceil + | F64Floor + | F64Trunc + | F64Nearest + | F64Sqrt + | F64Add + | F64Sub + | F64Mul + | F64Div + | F64Min + | F64Max + | F64Copysign + | F32Eq + | F32Ne + | F32Lt + | F32Gt + | F32Le + | F32Ge + | F64Eq + | F64Ne + | F64Lt + | F64Gt + | F64Le + | F64Ge + | I32TruncF32S + | I32TruncF32U + | I32TruncF64S + | I32TruncF64U + | I64TruncF32S + | I64TruncF32U + | I64TruncF64S + | I64TruncF64U + | F32ConvertI32S + | F32ConvertI32U + | F32ConvertI64S + | F32ConvertI64U + | F32DemoteF64 + | F64ConvertI32S + | F64ConvertI32U + | F64ConvertI64S + | F64ConvertI64U + | F64PromoteF32 + | I32TruncSatF32S + | I32TruncSatF32U + | I32TruncSatF64S + | I32TruncSatF64U + | I64TruncSatF32S + | I64TruncSatF32U + | I64TruncSatF64S + | I64TruncSatF64U + | F32x4Eq + | F32x4Ne + | F32x4Lt + | F32x4Gt + | F32x4Le + | F32x4Ge + | F64x2Eq + | F64x2Ne + | F64x2Lt + | F64x2Gt + | F64x2Le + | F64x2Ge + | F32x4Ceil + | F32x4Floor + | F32x4Trunc + | F32x4Nearest + | F32x4Abs + | F32x4Neg + | F32x4Sqrt + | F32x4Add + | F32x4Sub + | F32x4Mul + | F32x4Div + | F32x4Min + | F32x4Max + | F32x4PMin + | F32x4PMax + | F64x2Ceil + | F64x2Floor + | F64x2Trunc + | F64x2Nearest + | F64x2Abs + | F64x2Neg + | F64x2Sqrt + | F64x2Add + | F64x2Sub + | F64x2Mul + | F64x2Div + | F64x2Min + | F64x2Max + | F64x2PMin + | F64x2PMax + | I32x4TruncSatF32x4S + | I32x4TruncSatF32x4U + | F32x4ConvertI32x4S + | F32x4ConvertI32x4U + | I32x4TruncSatF64x2SZero + | I32x4TruncSatF64x2UZero + | F64x2ConvertLowI32x4S + | F64x2ConvertLowI32x4U + | F32x4DemoteF64x2Zero + | F64x2PromoteLowF32x4 + | I32x4RelaxedTruncF32x4S + | I32x4RelaxedTruncF32x4U + | I32x4RelaxedTruncF64x2SZero + | I32x4RelaxedTruncF64x2UZero + | F32x4RelaxedMadd + | F32x4RelaxedNmadd + | F64x2RelaxedMadd + | F64x2RelaxedNmadd + | F32x4RelaxedMin + | F32x4RelaxedMax + | F64x2RelaxedMin + | F64x2RelaxedMax + ) +} - let non_det_features = self.engines.non_det.config().get_features().bits() | add_features; +pub(crate) fn validate_contract_wasm(wasm: &[u8]) -> wasmtime::Result<()> { + let mut validator = wasmparser::Validator::new_with_features(CONTRACT_WASM_FEATURES); + validator.validate_all(wasm).with_context(|| { + format!( + "validating {}", + &String::from_utf8_lossy(&wasm[..10.min(wasm.len())]) + ) + })?; - let mut det_validator = wasmparser::Validator::new_with_features( - WasmFeatures::from_bits(det_features).expect("invalid deterministic wasm feature bits"), - ); - let mut non_det_validator = wasmparser::Validator::new_with_features( - WasmFeatures::from_bits(non_det_features) - .expect("invalid non-deterministic wasm feature bits"), - ); - det_validator.validate_all(wasm).with_context(|| { - format!( - "validating {}", - &String::from_utf8_lossy(&wasm[..10.min(wasm.len())]) - ) - })?; - non_det_validator.validate_all(wasm).with_context(|| { - format!( - "validating {}", - &String::from_utf8_lossy(&wasm[..10.min(wasm.len())]) - ) - })?; + for payload in wasmparser::Parser::new(0).parse_all(wasm) { + let wasmparser::Payload::CodeSectionEntry(body) = payload? else { + continue; + }; + let mut operators = body.get_operators_reader()?; + while !operators.eof() { + let offset = operators.original_position(); + let operator = operators.read()?; + if is_nondeterministic_float_operator(&operator) { + return Err(wasmtime::Error::msg(format!( + "nondeterministic floating-point operator {operator:?} at offset {offset}" + ))); + } + } + } + + Ok(()) +} - Ok(()) +impl super::Supervisor { + pub fn validate_wasm(&self, wasm: &[u8]) -> wasmtime::Result<()> { + validate_contract_wasm(wasm) } pub async fn compile_wasm( @@ -107,3 +248,114 @@ impl super::Supervisor { }) } } + +#[cfg(test)] +mod tests { + use super::validate_contract_wasm; + + fn validate(wat: &str) -> wasmtime::Result<()> { + let wasm = wat::parse_str(wat).map_err(|error| wasmtime::Error::msg(error.to_string()))?; + validate_contract_wasm(&wasm) + } + + #[test] + fn deterministic_policy_allows_float_bit_transport() { + validate( + r#" + (module + (memory 1) + (func (param i32) (result i32) + local.get 0 + f32.load + i32.reinterpret_f32 + ) + (func (param i32) (result i64) + local.get 0 + f64.load + i64.reinterpret_f64 + ) + (func (param i32 f32) + local.get 0 + local.get 1 + f32.store + ) + (func (param f32) (result v128) + local.get 0 + f32x4.splat + ) + (func (param v128) (result f32) + local.get 0 + f32x4.extract_lane 0 + ) + (func (param v128 f32) (result v128) + local.get 0 + local.get 1 + f32x4.replace_lane 0 + ) + (func (result f32) + f32.const 1.0 + ) + (func (result f64) + f64.const 1.0 + ) + (func (param f64) (result v128) + local.get 0 + f64x2.splat + ) + (func (param v128 f64) (result v128) + local.get 0 + local.get 1 + f64x2.replace_lane 0 + ) + (func (param v128) (result f64) + local.get 0 + f64x2.extract_lane 0 + ) + ) + "#, + ) + .unwrap(); + } + + #[test] + fn deterministic_policy_rejects_scalar_float_computation() { + let error = validate( + r#" + (module + (func (param f32 f32) (result f32) + local.get 0 + local.get 1 + f32.add + ) + ) + "#, + ) + .unwrap_err(); + + assert!(error.to_string().contains("F32Add"), "{error:#}"); + } + + #[test] + fn deterministic_policy_rejects_simd_float_computation() { + let error = validate( + r#" + (module + (func (param v128 v128) (result v128) + local.get 0 + local.get 1 + f64x2.mul + ) + ) + "#, + ) + .unwrap_err(); + + assert!(error.to_string().contains("F64x2Mul"), "{error:#}"); + } + + #[test] + fn contract_feature_set_rejects_memory64() { + let error = validate("(module (memory i64 1))").unwrap_err(); + assert!(format!("{error:#}").contains("memory64"), "{error:#}"); + } +} diff --git a/executor/src/rt/supervisor/mod.rs b/executor/src/rt/supervisor/mod.rs index 9778592e..7eb004d9 100644 --- a/executor/src/rt/supervisor/mod.rs +++ b/executor/src/rt/supervisor/mod.rs @@ -16,7 +16,6 @@ pub(crate) mod actions; mod compilation; struct WasmModuleCache { - cache_dir: Option, wasm_modules_cache: sync::CacheMap>, } @@ -164,34 +163,24 @@ pub fn create_engines( public_abi::top_limits::WASM_STACK_VALUE_SLOTS, ); - base_conf - .wasm_tail_call(true) - .wasm_bulk_memory(true) - .wasm_simd(true) - .relaxed_simd_deterministic(true) - .wasm_relaxed_simd(false); - use wasmparser::WasmFeatures; base_conf - .wasm_features(WasmFeatures::BULK_MEMORY, true) - .wasm_features(WasmFeatures::SIGN_EXTENSION, true) - .wasm_features(WasmFeatures::MUTABLE_GLOBAL, true) - .wasm_features(WasmFeatures::MULTI_VALUE, true) - .wasm_features(WasmFeatures::SATURATING_FLOAT_TO_INT, false) - //.wasm_features(WasmFeatures::REFERENCE_TYPES, false) - .wasm_features(WasmFeatures::SATURATING_FLOAT_TO_INT, true); + .wasm_features(WasmFeatures::all(), false) + .wasm_features(compilation::CONTRACT_WASM_FEATURES, true) + .relaxed_simd_deterministic(true); config_base(&mut base_conf)?; let mut det_conf = base_conf.clone(); det_conf .wasm_floats_enabled(false) - .cranelift_nan_canonicalization(true) - .wasm_backtrace(true); + .cranelift_nan_canonicalization(true); let mut non_det_conf = base_conf.clone(); - non_det_conf.wasm_floats_enabled(true).wasm_backtrace(false); + non_det_conf + .wasm_floats_enabled(true) + .wasm_backtrace_max_frames(None); let det_engine = wasmtime::Engine::new(&det_conf) .map_err(crate::wasmtime_to_anyhow) @@ -368,7 +357,6 @@ impl Supervisor { ) .context("creating runner cache reader")?, wasm_mod_cache: WasmModuleCache { - cache_dir: my_cache_dir, wasm_modules_cache: sync::CacheMap::new(), }, custom_runners: runners::cache::WeakCache::new(), @@ -430,7 +418,7 @@ pub async fn spawn( let engine = zelf.engines.get(vm.conf.permissions.deterministic); let limiter = vm.limiter.clone(); - let mut store = wasmtime::Store::new( + let mut store = wasmtime::Store::new_with_genvm_ctx( engine, rt::vm::WasmtimeStoreData { limits: vm.limiter.clone(),