From c188998cc0a6f617fd06b7b6f5fa2755ab3333dc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Jan 2026 11:22:43 -0700 Subject: [PATCH 1/5] refactor recursive reentrance checks This commit makes a few changes related to recursive reentrance checks, instance poisoning, etc.: - Implements the more restrictive lift/lower rules described in https://github.com/WebAssembly/component-model/pull/589 such that a component instance may not lower a function lifted by one of its ancestors, nor vice-versa. Any such lower will result in a fused adapter which traps unconditionally, preventing guest-to-guest recursive reentrance without requiring data flow analysis. - Note that this required updating several WAST tests which were violating the new rule, including some in the `tests/component-model` Git submodule, which I've updated. - This is handled entirely in the `fact` module now; I've removed the `AlwaysTrap` case previously handled by `wasmtime-cranelift`. - Removes `FLAG_MAY_ENTER` from `InstanceFlags`. It is no longer needed for guest-to-guest calls due to the above, and for guest-to-host-to-guest calls we can rely on either `FLAG_NEEDS_POST_RETURN` for sync-lifted functions or the `GuestTask` call stack for async-lifted functions. - Adds a `StoreOpaque::trapped` field which is set when _any_ instance belonging to that store traps, at which point the entire store is considered poisoned, meaning no instance belonging to it may be entered. This prevents indeterminant concurrent task state left over from the trapping instance from leaking into other instances. Note that this does _not_ include code to push and pop `GuestTask` instances for guest-to-guest sync-to-sync calls, nor for host-to-guest calls using e.g. the synchronous `Func::call` API, so certain intrinsics which expect a `GuestTask` to be present such as `backpressure.inc` will still fail in such cases. I'll address that in a later PR. Also note that I made a small change to `wasmtime-wit-bindgen`, adding a `Send` bound on the `T` type parameter for `store | async` functions. This allowed me to recursively call `{Typed}Func::call_concurrent` from inside a host function, and it doesn't have any downsides AFAICT. Fixes #12128 --- crates/cranelift/src/compiler/component.rs | 65 +-- crates/cranelift/src/lib.rs | 4 - crates/environ/src/component/dfg.rs | 2 - crates/environ/src/component/info.rs | 5 - .../environ/src/component/translate/adapt.rs | 3 + .../environ/src/component/translate/inline.rs | 88 ++-- .../src/component/vmcomponent_offsets.rs | 4 - crates/environ/src/fact.rs | 13 +- crates/environ/src/fact/trampoline.rs | 43 +- crates/environ/src/trap_encoding.rs | 9 - .../component-async-tests/src/round_trip.rs | 5 +- .../tests/scenario/round_trip.rs | 145 +++++- .../src/runtime/component/concurrent.rs | 294 ++++++------ .../runtime/component/concurrent_disabled.rs | 15 +- crates/wasmtime/src/runtime/component/func.rs | 48 +- .../src/runtime/component/func/host.rs | 13 +- .../src/runtime/component/func/options.rs | 20 +- crates/wasmtime/src/runtime/component/mod.rs | 2 +- .../src/runtime/component/resources/any.rs | 8 +- .../component/resources/host_tables.rs | 19 +- .../wasmtime/src/runtime/component/store.rs | 7 + crates/wasmtime/src/runtime/func.rs | 22 +- crates/wasmtime/src/runtime/store.rs | 16 + crates/wasmtime/src/runtime/vm/component.rs | 36 +- .../src/runtime/vm/component/libcalls.rs | 4 +- crates/wit-bindgen/src/lib.rs | 2 +- tests/all/component_model/func.rs | 439 ++++++++++++------ tests/all/component_model/import.rs | 150 +++--- tests/all/component_model/strings.rs | 4 +- tests/component-model | 2 +- .../component-model/adapter.wast | 2 +- .../async/backpressure-deadlock.wast | 111 +++-- .../async/future-cancel-write-completed.wast | 99 ++-- .../component-model/async/future-read.wast | 176 ++++--- .../async/reenter-during-yield.wast | 82 ++++ .../component-model/async/wait-forever.wast | 36 +- 36 files changed, 1184 insertions(+), 809 deletions(-) create mode 100644 tests/misc_testsuite/component-model/async/reenter-during-yield.wast diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index 2d7578c5af37..fc583c06827d 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -1,6 +1,6 @@ //! Compilation support for the component model. -use crate::{TRAP_ALWAYS, TRAP_CANNOT_ENTER, TRAP_INTERNAL_ASSERT, compiler::Compiler}; +use crate::{TRAP_INTERNAL_ASSERT, compiler::Compiler}; use cranelift_codegen::ir::condcodes::IntCC; use cranelift_codegen::ir::{self, InstBuilder, MemFlags, Value}; use cranelift_codegen::isa::{CallConv, TargetIsa}; @@ -20,7 +20,6 @@ struct TrampolineCompiler<'a> { offsets: VMComponentOffsets, block0: ir::Block, signature: &'a WasmFuncType, - tunables: &'a Tunables, } /// What host functions can be called, used in `translate_hostcall` below. @@ -100,7 +99,6 @@ impl<'a> TrampolineCompiler<'a> { component: &'a Component, types: &'a ComponentTypesBuilder, signature: &'a WasmFuncType, - tunables: &'a Tunables, ) -> TrampolineCompiler<'a> { let isa = &*compiler.isa; let func = ir::Function::with_name_signature( @@ -117,7 +115,6 @@ impl<'a> TrampolineCompiler<'a> { offsets: VMComponentOffsets::new(isa.pointer_bytes(), component), block0, signature, - tunables, } } @@ -160,21 +157,6 @@ impl<'a> TrampolineCompiler<'a> { }, ); } - Trampoline::AlwaysTrap => { - if self.tunables.signals_based_traps { - self.builder.ins().trap(TRAP_ALWAYS); - return; - } - self.translate_libcall( - host::trap, - TrapSentinel::Falsy, - WasmArgs::InRegisters, - |me, params| { - let code = wasmtime_environ::Trap::AlwaysTrapAdapter as u8; - params.push(me.builder.ins().iconst(ir::types::I32, i64::from(code))); - }, - ); - } Trampoline::ResourceNew { instance, ty } => { // Currently this only supports resources represented by `i32` assert_eq!(self.signature.params()[0], WasmValType::I32); @@ -1130,13 +1112,8 @@ impl<'a> TrampolineCompiler<'a> { // brif should_run_destructor, run_destructor_block, return_block // // run_destructor_block: - // ;; test may_enter, but only if the component instances - // ;; differ - // flags = load.i32 vmctx+$instance_flags_offset - // masked = band flags, $FLAG_MAY_ENTER - // trapz masked, CANNOT_ENTER_CODE - // - // ;; set may_block to false, saving the old value to restore later + // ;; set may_block to false, saving the old value to restore + // ;; later, but only if the component instances differ // old_may_block = load.i32 vmctx+$may_block_offset // store 0, vmctx+$may_block_offset // @@ -1184,25 +1161,13 @@ impl<'a> TrampolineCompiler<'a> { self.builder.switch_to_block(run_destructor_block); - // If this is a defined resource within the component itself then a - // check needs to be emitted for the `may_enter` flag. Note though - // that this check can be elided if the resource table resides in - // the same component instance that defined the resource as the - // component is calling itself. + // If this is a defined resource within the component itself then the + // `may_block` field must be updated. Note though that this update can + // be elided if the resource table resides in the same component + // instance that defined the resource as the component is calling + // itself. let old_may_block = if let Some(def) = resource_def { if self.types[resource].unwrap_concrete_instance() != def.instance { - let flags = self.builder.ins().load( - ir::types::I32, - trusted, - vmctx, - i32::try_from(self.offsets.instance_flags(def.instance)).unwrap(), - ); - let masked = self - .builder - .ins() - .band_imm(flags, i64::from(FLAG_MAY_ENTER)); - self.builder.ins().trapz(masked, TRAP_CANNOT_ENTER); - // Stash the old value of `may_block` and then set it to false. let old_may_block = self.builder.ins().load( ir::types::I32, @@ -1434,7 +1399,7 @@ impl ComponentCompiler for Compiler { types: &ComponentTypesBuilder, key: FuncKey, abi: Abi, - tunables: &Tunables, + _tunables: &Tunables, symbol: &str, ) -> Result { let (abi2, trampoline_index) = key.unwrap_component_trampoline(); @@ -1466,14 +1431,7 @@ impl ComponentCompiler for Compiler { } let mut compiler = self.function_compiler(); - let mut c = TrampolineCompiler::new( - self, - &mut compiler, - &component.component, - types, - sig, - tunables, - ); + let mut c = TrampolineCompiler::new(self, &mut compiler, &component.component, types, sig); // If we are crossing the Wasm-to-native boundary, we need to save the // exit FP and return address for stack walking purposes. However, we @@ -1512,7 +1470,7 @@ impl ComponentCompiler for Compiler { fn compile_intrinsic( &self, - tunables: &Tunables, + _tunables: &Tunables, component: &ComponentTranslation, types: &ComponentTypesBuilder, intrinsic: UnsafeIntrinsic, @@ -1557,7 +1515,6 @@ impl ComponentCompiler for Compiler { &component.component, &types, &wasm_func_ty, - tunables, ); match intrinsic { diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index b44e3cde445e..5ebcf2bcd158 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -48,10 +48,6 @@ use self::compiler::Compiler; const TRAP_INTERNAL_ASSERT: TrapCode = TrapCode::unwrap_user(1); const TRAP_OFFSET: u8 = 2; -pub const TRAP_ALWAYS: TrapCode = - TrapCode::unwrap_user(Trap::AlwaysTrapAdapter as u8 + TRAP_OFFSET); -pub const TRAP_CANNOT_ENTER: TrapCode = - TrapCode::unwrap_user(Trap::CannotEnterComponent as u8 + TRAP_OFFSET); pub const TRAP_INDIRECT_CALL_TO_NULL: TrapCode = TrapCode::unwrap_user(Trap::IndirectCallToNull as u8 + TRAP_OFFSET); pub const TRAP_BAD_SIGNATURE: TrapCode = diff --git a/crates/environ/src/component/dfg.rs b/crates/environ/src/component/dfg.rs index 5f5a3b84faed..1c7e9910744d 100644 --- a/crates/environ/src/component/dfg.rs +++ b/crates/environ/src/component/dfg.rs @@ -326,7 +326,6 @@ pub enum Trampoline { to: MemoryId, to64: bool, }, - AlwaysTrap, ResourceNew { instance: RuntimeComponentInstanceIndex, ty: TypeResourceTableIndex, @@ -945,7 +944,6 @@ impl LinearizeDfg<'_> { to: self.runtime_memory(*to), to64: *to64, }, - Trampoline::AlwaysTrap => info::Trampoline::AlwaysTrap, Trampoline::ResourceNew { instance, ty } => info::Trampoline::ResourceNew { instance: *instance, ty: *ty, diff --git a/crates/environ/src/component/info.rs b/crates/environ/src/component/info.rs index 65a12aebdb35..ea1cb94f7ea9 100644 --- a/crates/environ/src/component/info.rs +++ b/crates/environ/src/component/info.rs @@ -734,10 +734,6 @@ pub enum Trampoline { to64: bool, }, - /// A small adapter which simply traps, used for degenerate lift/lower - /// combinations. - AlwaysTrap, - /// A `resource.new` intrinsic which will inject a new resource into the /// table specified. ResourceNew { @@ -1199,7 +1195,6 @@ impl Trampoline { let to = if *to64 { "64" } else { "32" }; format!("component-transcode-{op}-m{from}-m{to}") } - AlwaysTrap => format!("component-always-trap"), ResourceNew { ty, .. } => format!("component-resource-new[{}]", ty.as_u32()), ResourceRep { ty, .. } => format!("component-resource-rep[{}]", ty.as_u32()), ResourceDrop { ty, .. } => format!("component-resource-drop[{}]", ty.as_u32()), diff --git a/crates/environ/src/component/translate/adapt.rs b/crates/environ/src/component/translate/adapt.rs index 2f66974a7a4c..d528099a2069 100644 --- a/crates/environ/src/component/translate/adapt.rs +++ b/crates/environ/src/component/translate/adapt.rs @@ -166,6 +166,9 @@ pub struct AdapterOptions { /// The Wasmtime-assigned component instance index where the options were /// originally specified. pub instance: RuntimeComponentInstanceIndex, + /// The ancestors (i.e. chain of instantiating instances) of the instance + /// specified in the `instance` field. + pub ancestors: Vec, /// How strings are encoded. pub string_encoding: StringEncoding, /// The async callback function used by these options, if specified. diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs index afff24fc414d..b6004c62ce1b 100644 --- a/crates/environ/src/component/translate/inline.rs +++ b/crates/environ/src/component/translate/inline.rs @@ -386,7 +386,7 @@ impl<'a> Inliner<'a> { // Process the initializer and if it started the instantiation // of another component then we push that frame on the stack to // continue onwards. - Some(init) => match self.initializer(frame, types, init)? { + Some(init) => match self.initializer(frames, types, init)? { Some(new_frame) => { frames.push((new_frame, types.resources_mut().clone())); } @@ -422,12 +422,13 @@ impl<'a> Inliner<'a> { fn initializer( &mut self, - frame: &mut InlinerFrame<'a>, + frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>, types: &mut ComponentTypesBuilder, initializer: &'a LocalInitializer, ) -> Result>> { use LocalInitializer::*; + let (frame, _) = frames.last_mut().unwrap(); match initializer { // When a component imports an item the actual definition of the // item is looked up here (not at runtime) via its name. The @@ -512,7 +513,8 @@ impl<'a> Inliner<'a> { } => { let lower_ty = types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?; - let options_lower = self.adapter_options(frame, types, options); + let options_lower = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let lower_core_type = options_lower.core_type; let func = match &frame.component_funcs[*func] { // If this component function was originally a host import @@ -533,45 +535,8 @@ impl<'a> Inliner<'a> { dfg::CoreDef::Trampoline(index) } - // This case handles when a lifted function is later - // lowered, and both the lowering and the lifting are - // happening within the same component instance. - // - // In this situation if the `canon.lower`'d function is - // called then it immediately sets `may_enter` to `false`. - // When calling the callee, however, that's `canon.lift` - // which immediately traps if `may_enter` is `false`. That - // means that this pairing of functions creates a function - // that always traps. - // - // When closely reading the spec though the precise trap - // that comes out can be somewhat variable. Technically the - // function yielded here is one that should validate the - // arguments by lifting them, and then trap. This means that - // the trap could be different depending on whether all - // arguments are valid for now. This was discussed in - // WebAssembly/component-model#51 somewhat and the - // conclusion was that we can probably get away with "always - // trap" here. - // - // The `CoreDef::AlwaysTrap` variant here is used to - // indicate that this function is valid but if something - // actually calls it then it just generates a trap - // immediately. - ComponentFuncDef::Lifted { - options: options_lift, - .. - } if options_lift.instance == options_lower.instance => { - let index = self - .result - .trampolines - .push((lower_core_type, dfg::Trampoline::AlwaysTrap)); - dfg::CoreDef::Trampoline(index) - } - - // Lowering a lifted function where the destination - // component is different than the source component means - // that a "fused adapter" was just identified. + // Lowering a lifted functio means that a "fused adapter" + // was just identified. // // Metadata about this fused adapter is recorded in the // `Adapters` output of this compilation pass. Currently the @@ -624,7 +589,8 @@ impl<'a> Inliner<'a> { // plumbed through to exports or a fused adapter later on. Lift(ty, func, options) => { let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let func = frame.funcs[*func].1.clone(); frame .component_funcs @@ -724,7 +690,8 @@ impl<'a> Inliner<'a> { .collect::>()?; let results = types.new_tuple_type(results); let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -756,7 +723,8 @@ impl<'a> Inliner<'a> { } WaitableSetWait { options } => { let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -769,7 +737,8 @@ impl<'a> Inliner<'a> { } WaitableSetPoll { options } => { let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -849,7 +818,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -868,7 +838,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -964,7 +935,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -983,7 +955,8 @@ impl<'a> Inliner<'a> { unreachable!() }; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1060,7 +1033,8 @@ impl<'a> Inliner<'a> { ErrorContextNew { options } => { let ty = types.error_context_table_type()?; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1075,7 +1049,8 @@ impl<'a> Inliner<'a> { ErrorContextDebugMessage { options } => { let ty = types.error_context_table_type()?; let func = options.core_type; - let options = self.adapter_options(frame, types, options); + let options = self.adapter_options(frames, types, options); + let (frame, _) = frames.last_mut().unwrap(); let options = self.canonical_options(options); let index = self.result.trampolines.push(( func, @@ -1559,10 +1534,11 @@ impl<'a> Inliner<'a> { /// specified into a runtime representation. fn adapter_options( &mut self, - frame: &InlinerFrame<'a>, + frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>, types: &ComponentTypesBuilder, options: &LocalCanonicalOptions, ) -> AdapterOptions { + let (frame, _) = frames.last_mut().unwrap(); let data_model = match options.data_model { LocalDataModel::Gc {} => DataModel::Gc {}, LocalDataModel::LinearMemory { memory, realloc } => { @@ -1584,6 +1560,12 @@ impl<'a> Inliner<'a> { let post_return = options.post_return.map(|i| frame.funcs[i].1.clone()); AdapterOptions { instance: frame.instance, + ancestors: frames + .iter() + .rev() + .skip(1) + .map(|(frame, _)| frame.instance) + .collect(), string_encoding: options.string_encoding, callback, post_return, diff --git a/crates/environ/src/component/vmcomponent_offsets.rs b/crates/environ/src/component/vmcomponent_offsets.rs index 6743dbba2fa8..2fc76f7e03a5 100644 --- a/crates/environ/src/component/vmcomponent_offsets.rs +++ b/crates/environ/src/component/vmcomponent_offsets.rs @@ -29,10 +29,6 @@ pub const VMCOMPONENT_MAGIC: u32 = u32::from_le_bytes(*b"comp"); /// canonical ABI flag `may_leave` pub const FLAG_MAY_LEAVE: i32 = 1 << 0; -/// Flag for the `VMComponentContext::flags` field which corresponds to the -/// canonical ABI flag `may_enter` -pub const FLAG_MAY_ENTER: i32 = 1 << 1; - /// Flag for the `VMComponentContext::flags` field which is set whenever a /// function is called to indicate that `post_return` must be called next. pub const FLAG_NEEDS_POST_RETURN: i32 = 1 << 2; diff --git a/crates/environ/src/fact.rs b/crates/environ/src/fact.rs index 686c0ba96b56..77011665a017 100644 --- a/crates/environ/src/fact.rs +++ b/crates/environ/src/fact.rs @@ -114,9 +114,6 @@ struct AdapterData { /// The core wasm function that this adapter will be calling (the original /// function that was `canon lift`'d) callee: FuncIndex, - /// FIXME(#4185) should be plumbed and handled as part of the new reentrance - /// rules not yet implemented here. - called_as_export: bool, } /// Configuration options which apply at the "global adapter" level. @@ -124,7 +121,12 @@ struct AdapterData { /// These options are typically unique per-adapter and generally aren't needed /// when translating recursive types within an adapter. struct AdapterOptions { + /// The Wasmtime-assigned component instance index where the options were + /// originally specified. instance: RuntimeComponentInstanceIndex, + /// The ancestors (i.e. chain of instantiating instances) of the instance + /// specified in the `instance` field. + ancestors: Vec, /// The ascribed type of this adapter. ty: TypeFuncIndex, /// The global that represents the instance flags for where this adapter @@ -307,9 +309,6 @@ impl<'a> Module<'a> { lift, lower, callee, - // FIXME(#4185) should be plumbed and handled as part of the new - // reentrance rules not yet implemented here. - called_as_export: true, }, ); @@ -321,6 +320,7 @@ impl<'a> Module<'a> { fn import_options(&mut self, ty: TypeFuncIndex, options: &AdapterOptionsDfg) -> AdapterOptions { let AdapterOptionsDfg { instance, + ancestors, string_encoding, post_return: _, // handled above callback, @@ -399,6 +399,7 @@ impl<'a> Module<'a> { AdapterOptions { instance: *instance, + ancestors: ancestors.clone(), ty, flags, post_return: None, diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 2df0b1e6babb..d3bdecc42b8e 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -16,8 +16,8 @@ //! can be somewhat arbitrary, an intentional decision. use crate::component::{ - CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_ENTER, FLAG_MAY_LEAVE, FixedEncoding as FE, - FlatType, InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, + CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_LEAVE, FixedEncoding as FE, FlatType, + InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT, START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, @@ -114,6 +114,19 @@ pub(super) fn compile(module: &mut Module<'_>, adapter: &AdapterData) { ) } + // If the lift and lower instances are equal, or if one is an ancestor of + // the other, we trap unconditionally. This ensures that recursive + // reentrance via an adapter is impossible. + if adapter.lift.instance == adapter.lower.instance + || adapter.lower.ancestors.contains(&adapter.lift.instance) + || adapter.lift.ancestors.contains(&adapter.lower.instance) + { + let (mut compiler, _, _) = compiler(module, adapter); + compiler.trap(Trap::CannotEnterComponent); + compiler.finish(); + return; + } + // This closure compiles a function to be exported to the host which host to // lift the parameters from the caller and lower them to the callee. // @@ -739,20 +752,6 @@ impl<'a, 'b> Compiler<'a, 'b> { FLAG_MAY_LEAVE, Trap::CannotLeaveComponent, ); - if adapter.called_as_export { - self.trap_if_not_flag( - adapter.lift.flags, - FLAG_MAY_ENTER, - Trap::CannotEnterComponent, - ); - self.set_flag(adapter.lift.flags, FLAG_MAY_ENTER, false); - } else if self.module.debug { - self.assert_not_flag( - adapter.lift.flags, - FLAG_MAY_ENTER, - Trap::DebugAssertMayEnterUnset, - ); - } let task_may_block = self.module.import_task_may_block(); let old_task_may_block = if self.types[adapter.lift.ty].async_ { @@ -831,9 +830,6 @@ impl<'a, 'b> Compiler<'a, 'b> { } self.instruction(Call(func.as_u32())); } - if adapter.called_as_export { - self.set_flag(adapter.lift.flags, FLAG_MAY_ENTER, true); - } for tmp in temps { self.free_temp_local(tmp); @@ -3399,15 +3395,6 @@ impl<'a, 'b> Compiler<'a, 'b> { self.instruction(End); } - fn assert_not_flag(&mut self, flags_global: GlobalIndex, flag_to_test: i32, trap: Trap) { - self.instruction(GlobalGet(flags_global.as_u32())); - self.instruction(I32Const(flag_to_test)); - self.instruction(I32And); - self.instruction(If(BlockType::Empty)); - self.trap(trap); - self.instruction(End); - } - fn set_flag(&mut self, flags_global: GlobalIndex, flag_to_set: i32, value: bool) { self.instruction(GlobalGet(flags_global.as_u32())); if value { diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs index 95bc95c70407..be083aea73fc 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs @@ -57,13 +57,6 @@ pub enum Trap { /// Execution has potentially run too long and may be interrupted. Interrupt, - /// When the `component-model` feature is enabled this trap represents a - /// function that was `canon lift`'d, then `canon lower`'d, then called. - /// This combination of creation of a function in the component model - /// generates a function that always traps and, when called, produces this - /// flavor of trap. - AlwaysTrapAdapter, - /// When wasm code is configured to consume fuel and it runs out of fuel /// then this trap will be raised. OutOfFuel, @@ -183,7 +176,6 @@ impl Trap { BadConversionToInteger UnreachableCodeReached Interrupt - AlwaysTrapAdapter OutOfFuel AtomicWaitNonSharedMemory NullReference @@ -230,7 +222,6 @@ impl fmt::Display for Trap { BadConversionToInteger => "invalid conversion to integer", UnreachableCodeReached => "wasm `unreachable` instruction executed", Interrupt => "interrupt", - AlwaysTrapAdapter => "degenerate component adapter called", OutOfFuel => "all fuel consumed by WebAssembly", AtomicWaitNonSharedMemory => "atomic wait on non-shared memory", NullReference => "null reference", diff --git a/crates/misc/component-async-tests/src/round_trip.rs b/crates/misc/component-async-tests/src/round_trip.rs index d8894c5473d3..7308abfecee1 100644 --- a/crates/misc/component-async-tests/src/round_trip.rs +++ b/crates/misc/component-async-tests/src/round_trip.rs @@ -6,6 +6,7 @@ pub mod bindings { wasmtime::component::bindgen!({ path: "wit", world: "round-trip", + imports: { default: trappable }, }); } @@ -18,9 +19,9 @@ pub mod non_concurrent_export_bindings { } impl bindings::local::local::baz::HostWithStore for Ctx { - async fn foo(_: &Accessor, s: String) -> String { + async fn foo(_: &Accessor, s: String) -> wasmtime::Result { crate::util::sleep(Duration::from_millis(10)).await; - format!("{s} - entered host - exited host") + Ok(format!("{s} - entered host - exited host")) } } diff --git a/crates/misc/component-async-tests/tests/scenario/round_trip.rs b/crates/misc/component-async-tests/tests/scenario/round_trip.rs index b2a14c30f1ed..ac4d444de3ec 100644 --- a/crates/misc/component-async-tests/tests/scenario/round_trip.rs +++ b/crates/misc/component-async-tests/tests/scenario/round_trip.rs @@ -12,9 +12,11 @@ use futures::{ channel::oneshot, stream::{FuturesUnordered, TryStreamExt}, }; -use wasmtime::component::{Accessor, AccessorTask, HasSelf, Instance, Linker, ResourceTable, Val}; -use wasmtime::{Engine, Result, Store, format_err}; -use wasmtime_wasi::WasiCtxBuilder; +use wasmtime::component::{ + Accessor, AccessorTask, HasData, HasSelf, Instance, Linker, ResourceTable, Val, +}; +use wasmtime::{Engine, Result, Store, Trap, format_err}; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView}; #[tokio::test] pub async fn async_round_trip_stackful() -> Result<()> { @@ -203,6 +205,143 @@ pub async fn async_round_trip_stackless_sync_import() -> Result<()> { .await } +#[tokio::test] +pub async fn async_round_trip_stackless_recurse() -> Result<()> { + test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_STACKLESS_COMPONENT, + false, + ) + .await +} + +#[tokio::test] +pub async fn async_round_trip_stackless_recurse_trap() -> Result<()> { + let error = test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_STACKLESS_COMPONENT, + true, + ) + .await + .unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +#[tokio::test] +pub async fn async_round_trip_synchronous_recurse() -> Result<()> { + test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_SYNCHRONOUS_COMPONENT, + false, + ) + .await +} + +#[tokio::test] +pub async fn async_round_trip_synchronous_recurse_trap() -> Result<()> { + let error = test_round_trip_recurse( + test_programs_artifacts::ASYNC_ROUND_TRIP_SYNCHRONOUS_COMPONENT, + true, + ) + .await + .unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +async fn test_round_trip_recurse(component: &str, same_instance: bool) -> Result<()> { + pub struct MyCtx { + wasi: WasiCtx, + table: ResourceTable, + instance: Option>, + } + + impl WasiView for MyCtx { + fn ctx(&mut self) -> WasiCtxView<'_> { + WasiCtxView { + ctx: &mut self.wasi, + table: &mut self.table, + } + } + } + + impl HasData for MyCtx { + type Data<'a> = &'a mut Self; + } + + impl component_async_tests::round_trip::bindings::local::local::baz::HostWithStore for MyCtx { + async fn foo(accessor: &Accessor, s: String) -> wasmtime::Result { + if let Some(instance) = accessor.with(|mut access| access.get().instance.take()) { + run(accessor, &instance).await?; + accessor.with(|mut access| access.get().instance = Some(instance)); + } + Ok(format!("{s} - entered host - exited host")) + } + } + + impl component_async_tests::round_trip::bindings::local::local::baz::Host for MyCtx {} + + async fn run(accessor: &Accessor, instance: &Instance) -> Result<()> { + let round_trip = accessor.with(|mut access| { + component_async_tests::round_trip::bindings::RoundTrip::new(&mut access, &instance) + })?; + + let input = "hello, world!"; + let expected = "hello, world! - entered guest - entered host - exited host - exited guest"; + + let actual = round_trip + .local_local_baz() + .call_foo(accessor, input.into()) + .await?; + + assert_eq!(expected, actual); + + Ok(()) + } + + let engine = Engine::new(&config())?; + + let mut linker = Linker::new(&engine); + + wasmtime_wasi::p2::add_to_linker_async(&mut linker)?; + component_async_tests::round_trip::bindings::local::local::baz::add_to_linker::<_, MyCtx>( + &mut linker, + |ctx| ctx, + )?; + + let component = make_component(&engine, &[component]).await?; + + let mut store = Store::new( + &engine, + MyCtx { + wasi: WasiCtxBuilder::new().inherit_stdio().build(), + table: ResourceTable::default(), + instance: None, + }, + ); + + let instance = Arc::new(linker.instantiate_async(&mut store, &component).await?); + store.data_mut().instance = Some(instance.clone()); + + let instance = if same_instance { + instance + } else { + Arc::new(linker.instantiate_async(&mut store, &component).await?) + }; + + store + .run_concurrent(async move |accessor| { + run(&accessor.with_getter(|ctx| ctx), &instance).await + }) + .await??; + + store.assert_concurrent_state_empty(); + + Ok(()) +} + pub async fn test_round_trip( components: &[&str], inputs_and_outputs: &[(&str, &str)], diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs index 2ad06ef271da..0fa6d79d206c 100644 --- a/crates/wasmtime/src/runtime/component/concurrent.rs +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -53,13 +53,11 @@ use crate::component::func::{self, Func}; use crate::component::store::StoreComponentInstanceId; use crate::component::{ - ComponentInstanceId, HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, + HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, RuntimeInstance, }; use crate::fiber::{self, StoreFiber, StoreFiberYield}; use crate::store::{Store, StoreId, StoreInner, StoreOpaque, StoreToken}; -use crate::vm::component::{ - CallContext, ComponentInstance, HandleTable, InstanceFlags, ResourceTables, -}; +use crate::vm::component::{CallContext, ComponentInstance, HandleTable, ResourceTables}; use crate::vm::{AlwaysMut, SendSyncPtr, VMFuncRef, VMMemoryDefinition, VMStore}; use crate::{ AsContext, AsContextMut, FuncType, Result, StoreContext, StoreContextMut, ValRaw, ValType, @@ -444,7 +442,7 @@ where /// Run the specified closure, passing it mutable access to the store. /// /// This function is one of the main building blocks of the [`Accessor`] - /// type. This yields synchronous, blocking, access to store via an + /// type. This yields synchronous, blocking, access to the store via an /// [`Access`]. The [`Access`] implements [`AsContextMut`] in addition to /// providing the ability to access `D` via [`Access::get`]. Note that the /// `fun` here is given only temporary access to the store and `T`/`D` @@ -720,7 +718,7 @@ pub(crate) enum WaitResult { pub(crate) fn poll_and_block( store: &mut dyn VMStore, future: impl Future> + Send + 'static, - caller_instance: RuntimeComponentInstanceIndex, + caller_instance: RuntimeInstance, ) -> Result { let state = store.concurrent_state_mut(); @@ -852,7 +850,7 @@ fn handle_guest_call(store: &mut dyn VMStore, call: GuestCall) -> Result<()> { .take() .unwrap(); - let code = callback(store, runtime_instance.index, event, handle)?; + let code = callback(store, event, handle)?; store .concurrent_state_mut() @@ -1386,13 +1384,85 @@ impl StoreContextMut<'_, T> { } } -#[derive(Debug, Copy, Clone)] -pub struct RuntimeInstance { - pub instance: ComponentInstanceId, - pub index: RuntimeComponentInstanceIndex, -} - impl StoreOpaque { + /// Determine whether the specified instance may be entered from the host. + /// + /// We return `true` here only if all of the following hold: + /// + /// - The top-level instance is not already on the current task's call stack. + /// - The instance is not in need of a post-return function call. + /// - `self` has not been poisoned due to a trap. + pub(crate) fn may_enter(&mut self, instance: RuntimeInstance) -> bool { + let state = self.concurrent_state_mut(); + if let Some(caller) = state.guest_thread { + instance != state.get_mut(caller.task).unwrap().instance + && self.may_enter_from_caller(caller.task, instance) + } else { + self.may_enter_at_all(instance) + } + } + + fn may_enter_at_all(&self, instance: RuntimeInstance) -> bool { + if self.trapped() { + return false; + } + + let flags = StoreComponentInstanceId::new(self.id(), instance.instance) + .get(self) + .instance_flags(instance.index); + + unsafe { !flags.needs_post_return() } + } + + /// Variation of `may_enter` which takes a `TableId` representing + /// the callee. + fn may_enter_task(&mut self, task: TableId) -> bool { + let instance = self.concurrent_state_mut().get_mut(task).unwrap().instance; + self.may_enter_from_caller(task, instance) + } + + /// Variation of `may_enter` which takes a `TableId` representing + /// the caller, plus a `RuntimeInstance` representing the callee. + fn may_enter_from_caller( + &mut self, + mut guest_task: TableId, + instance: RuntimeInstance, + ) -> bool { + self.may_enter_at_all(instance) && { + let state = self.concurrent_state_mut(); + let guest_instance = instance.instance; + loop { + // Note that we only compare top-level instance IDs here. The + // idea is that the host is not allowed to recursively enter a + // top-level instance even if the specific leaf instance is not + // on the stack. This the behavior defined in the spec, and it + // allows us to elide runtime checks in guest-to-guest adapters. + let next_thread = match &state.get_mut(guest_task).unwrap().caller { + Caller::Host { caller: None, .. } => break true, + &Caller::Host { + caller: Some(caller), + .. + } => { + let instance = state.get_mut(caller.task).unwrap().instance; + if instance.instance == guest_instance { + break false; + } else { + caller + } + } + &Caller::Guest { thread, instance } => { + if instance.instance == guest_instance { + break false; + } else { + thread + } + } + }; + guest_task = next_thread.task; + } + } + } + /// Helper function to retrieve the `ConcurrentInstanceState` for the /// specified instance. fn instance_state(&mut self, instance: RuntimeInstance) -> &mut ConcurrentInstanceState { @@ -1894,7 +1964,6 @@ impl Instance { callee: SendSyncPtr, param_count: usize, result_count: usize, - flags: Option, async_: bool, callback: Option>, post_return: Option>, @@ -1919,7 +1988,6 @@ impl Instance { callee: SendSyncPtr, param_count: usize, result_count: usize, - flags: Option, ) -> impl FnOnce(&mut dyn VMStore) -> Result<[MaybeUninit; MAX_FLAT_PARAMS]> + Send + Sync @@ -1934,7 +2002,6 @@ impl Instance { .get_mut(guest_thread.thread)? .state = GuestThreadState::Running; let task = store.concurrent_state_mut().get_mut(guest_thread.task)?; - let may_enter_after_call = task.call_post_return_automatically(); let lower = task.lower_params.take().unwrap(); lower(store, &mut storage[..param_count])?; @@ -1944,9 +2011,6 @@ impl Instance { // SAFETY: Per the contract documented in `make_call's` // documentation, `callee` must be a valid pointer. unsafe { - if let Some(mut flags) = flags { - flags.set_may_enter(false); - } crate::Func::call_unchecked_raw( &mut store, callee.as_non_null(), @@ -1956,9 +2020,6 @@ impl Instance { ) .unwrap(), )?; - if let Some(mut flags) = flags { - flags.set_may_enter(may_enter_after_call); - } } Ok(storage) @@ -1975,7 +2036,6 @@ impl Instance { callee, param_count, result_count, - flags, ) }; @@ -2131,7 +2191,6 @@ impl Instance { unsafe { flags.set_may_leave(true); - flags.set_may_enter(true); } } @@ -2345,11 +2404,16 @@ impl Instance { }, Caller::Guest { thread: old_thread.unwrap(), - instance: caller_instance, + instance: RuntimeInstance { + instance: self.id().instance(), + index: caller_instance, + }, }, None, - self, - callee_instance, + RuntimeInstance { + instance: self.id().instance(), + index: callee_instance, + }, callee_async, )?; @@ -2360,10 +2424,6 @@ impl Instance { let state = store.0.concurrent_state_mut(); if let Some(old_thread) = old_thread { - if !state.may_enter(guest_task) { - bail!(crate::Trap::CannotEnterComponent); - } - state.get_mut(old_thread.task)?.subtasks.insert(guest_task); }; @@ -2387,14 +2447,10 @@ impl Instance { unsafe fn call_callback( self, mut store: StoreContextMut, - callee_instance: RuntimeComponentInstanceIndex, function: SendSyncPtr, event: Event, handle: u32, - may_enter_after_call: bool, ) -> Result { - let mut flags = self.id().get(store.0).instance_flags(callee_instance); - let (ordinal, result) = event.parts(); let params = &mut [ ValRaw::u32(ordinal), @@ -2406,13 +2462,11 @@ impl Instance { // `component::Options`. Per `wasmparser` callback signature // validation, we know it takes three parameters and returns one. unsafe { - flags.set_may_enter(false); crate::Func::call_unchecked_raw( &mut store, function.as_non_null(), params.as_mut_slice().into(), )?; - flags.set_may_enter(may_enter_after_call); } Ok(params[0].get_u32()) } @@ -2445,9 +2499,6 @@ impl Instance { let state = store.0.concurrent_state_mut(); let guest_thread = state.guest_thread.unwrap(); let callee_async = state.get_mut(guest_thread.task)?.async_function; - let may_enter_after_call = state - .get_mut(guest_thread.task)? - .call_post_return_automatically(); let callee = SendSyncPtr::new(NonNull::new(callee).unwrap()); let param_count = usize::try_from(param_count).unwrap(); assert!(param_count <= MAX_FLAT_PARAMS); @@ -2460,18 +2511,9 @@ impl Instance { // the callback and related context as part of the task so we can // call it later when needed. let callback = SendSyncPtr::new(NonNull::new(callback).unwrap()); - task.callback = Some(Box::new(move |store, runtime_instance, event, handle| { + task.callback = Some(Box::new(move |store, event, handle| { let store = token.as_context_mut(store); - unsafe { - self.call_callback::( - store, - runtime_instance, - callback, - event, - handle, - may_enter_after_call, - ) - } + unsafe { self.call_callback::(store, callback, event, handle) } })); } @@ -2487,14 +2529,6 @@ impl Instance { let caller = *caller; let caller_instance = *runtime_instance; - let callee_instance = task.instance; - - let instance_flags = if callback.is_null() { - None - } else { - Some(self.id().get(store.0).instance_flags(callee_instance.index)) - }; - // Queue the call as a "high priority" work item. unsafe { self.queue_call( @@ -2503,7 +2537,6 @@ impl Instance { callee, param_count, result_count, - instance_flags, (flags & START_FLAG_ASYNC_CALLEE) != 0, NonNull::new(callback).map(SendSyncPtr::new), NonNull::new(post_return).map(SendSyncPtr::new), @@ -2567,10 +2600,7 @@ impl Instance { // waitable and return the status. let handle = store .0 - .handle_table(RuntimeInstance { - instance: self.id().instance(), - index: caller_instance, - }) + .handle_table(caller_instance) .subtask_insert_guest(guest_thread.task.rep())?; store .0 @@ -2679,7 +2709,13 @@ impl Instance { // We create a new host task even though it might complete immediately // (in which case we won't need to pass a waitable back to the guest). // If it does complete immediately, we'll remove it before we return. - let task = state.push(HostTask::new(caller_instance, Some(join_handle)))?; + let task = state.push(HostTask::new( + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance, + }, + Some(join_handle), + ))?; log::trace!("new host task child of {caller:?}: {task:?}"); @@ -3034,7 +3070,13 @@ impl Instance { // Since waitables can neither be passed between instances nor forged, // this should never fail unless there's a bug in Wasmtime, but we check // here to be sure: - assert_eq!(expected_caller_instance, caller_instance); + assert_eq!( + expected_caller_instance, + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance + } + ); log::trace!("subtask_drop {waitable:?} (handle {task_id})"); Ok(()) } @@ -3462,7 +3504,13 @@ impl Instance { // Since waitables can neither be passed between instances nor forged, // this should never fail unless there's a bug in Wasmtime, but we check // here to be sure: - assert_eq!(expected_caller_instance, caller_instance); + assert_eq!( + expected_caller_instance, + RuntimeInstance { + instance: self.id().instance(), + index: caller_instance + } + ); log::trace!("subtask_cancel {waitable:?} (handle {task_id})"); @@ -4091,15 +4139,12 @@ type HostTaskFuture = Pin> + Send + 'static>> /// Represents the state of a pending host task. struct HostTask { common: WaitableCommon, - caller_instance: RuntimeComponentInstanceIndex, + caller_instance: RuntimeInstance, join_handle: Option, } impl HostTask { - fn new( - caller_instance: RuntimeComponentInstanceIndex, - join_handle: Option, - ) -> Self { + fn new(caller_instance: RuntimeInstance, join_handle: Option) -> Self { Self { common: WaitableCommon::default(), caller_instance, @@ -4114,12 +4159,7 @@ impl TableDebug for HostTask { } } -type CallbackFn = Box< - dyn Fn(&mut dyn VMStore, RuntimeComponentInstanceIndex, Event, u32) -> Result - + Send - + Sync - + 'static, ->; +type CallbackFn = Box Result + Send + Sync + 'static>; /// Represents the caller of a given guest task. enum Caller { @@ -4139,6 +4179,11 @@ enum Caller { host_future_present: bool, /// If true, call `post-return` function (if any) automatically. call_post_return_automatically: bool, + /// If `Some`, represents the `QualifiedThreadId` caller of the host + /// function which called back into a guest. Note that this thread + /// could belong to an entirely unrelated top-level component instance + /// than the one the host called into. + caller: Option, }, /// Another guest thread called the guest task Guest { @@ -4149,7 +4194,7 @@ enum Caller { /// Note that this might not be the same as the instance the caller task /// started executing in given that one or more synchronous guest->guest /// calls may have occurred involving multiple instances. - instance: RuntimeComponentInstanceIndex, + instance: RuntimeInstance, }, } @@ -4389,8 +4434,7 @@ impl GuestTask { lift_result: LiftResult, caller: Caller, callback: Option, - component_instance: Instance, - instance: RuntimeComponentInstanceIndex, + instance: RuntimeInstance, async_function: bool, ) -> Result { let sync_call_set = state.push(WaitableSet::default())?; @@ -4420,10 +4464,7 @@ impl GuestTask { starting_sent: false, subtasks: HashSet::new(), sync_call_set, - instance: RuntimeInstance { - instance: component_instance.id().instance(), - index: instance, - }, + instance, event: None, function_index: None, exited: false, @@ -4472,7 +4513,9 @@ impl GuestTask { }; } } - Caller::Host { exit_tx, .. } => { + Caller::Host { + exit_tx, caller, .. + } => { for subtask in &self.subtasks { state.get_mut(*subtask)?.caller = Caller::Host { tx: None, @@ -4482,6 +4525,7 @@ impl GuestTask { exit_tx: exit_tx.clone(), host_future_present: false, call_post_return_automatically: true, + caller: *caller, }; } } @@ -4925,40 +4969,6 @@ impl ConcurrentState { } } - /// Determine whether the instance associated with the specified guest task - /// may be entered (i.e. is not already on the async call stack). - /// - /// This is an additional check on top of the "may_enter" instance flag; - /// it's needed because async-lifted exports with callback functions must - /// not call their own instances directly or indirectly, and due to the - /// "stackless" nature of callback-enabled guest tasks this may happen even - /// if there are no activation records on the stack (i.e. the "may_enter" - /// field is `true`) for that instance. - fn may_enter(&mut self, mut guest_task: TableId) -> bool { - let guest_instance = self.get_mut(guest_task).unwrap().instance; - - // Walk the task tree back to the root, looking for potential - // reentrance. - // - // TODO: This could be optimized by maintaining a per-`GuestTask` bitset - // such that each bit represents and instance which has been entered by - // that task or an ancestor of that task, in which case this would be a - // constant time check. - loop { - let next_thread = match &self.get_mut(guest_task).unwrap().caller { - Caller::Host { .. } => break true, - Caller::Guest { thread, instance } => { - if *instance == guest_instance.index { - break false; - } else { - *thread - } - } - }; - guest_task = next_thread.task; - } - } - /// Implements the `context.get` intrinsic. pub(crate) fn context_get(&mut self, slot: u32) -> Result { let thread = self.guest_thread.unwrap(); @@ -5174,6 +5184,7 @@ pub(crate) fn prepare_call( let (tx, rx) = oneshot::channel(); let (exit_tx, exit_rx) = oneshot::channel(); + let caller = state.guest_thread; let mut task = GuestTask::new( state, Box::new(for_any_lower(move |store, params| { @@ -5192,30 +5203,22 @@ pub(crate) fn prepare_call( exit_tx: Arc::new(exit_tx), host_future_present, call_post_return_automatically, + caller, }, callback.map(|callback| { let callback = SendSyncPtr::new(callback); let instance = handle.instance(); - Box::new( - move |store: &mut dyn VMStore, runtime_instance, event, handle| { - let store = token.as_context_mut(store); - // SAFETY: Per the contract of `prepare_call`, the callback - // will remain valid at least as long is this task exists. - unsafe { - instance.call_callback( - store, - runtime_instance, - callback, - event, - handle, - call_post_return_automatically, - ) - } - }, - ) as CallbackFn + Box::new(move |store: &mut dyn VMStore, event, handle| { + let store = token.as_context_mut(store); + // SAFETY: Per the contract of `prepare_call`, the callback + // will remain valid at least as long is this task exists. + unsafe { instance.call_callback(store, callback, event, handle) } + }) as CallbackFn }), - handle.instance(), - component_instance, + RuntimeInstance { + instance: handle.instance().id().instance(), + index: component_instance, + }, async_function, )?; task.function_index = Some(handle.index()); @@ -5224,6 +5227,10 @@ pub(crate) fn prepare_call( let thread = state.push(GuestThread::new_implicit(task))?; state.get_mut(task)?.threads.insert(thread); + if !store.0.may_enter_task(task) { + bail!(crate::Trap::CannotEnterComponent); + } + Ok(PreparedCall { handle, thread: QualifiedThreadId { task, thread }, @@ -5273,7 +5280,7 @@ fn queue_call0( guest_thread: QualifiedThreadId, param_count: usize, ) -> Result<()> { - let (_options, flags, _ty, raw_options) = handle.abi_info(store.0); + let (_options, _, _ty, raw_options) = handle.abi_info(store.0); let is_concurrent = raw_options.async_; let callback = raw_options.callback; let instance = handle.instance(); @@ -5286,12 +5293,6 @@ fn queue_call0( log::trace!("queueing call {guest_thread:?}"); - let instance_flags = if callback.is_none() { - None - } else { - Some(flags) - }; - // SAFETY: `callee`, `callback`, and `post_return` are valid pointers // (with signatures appropriate for this call) and will remain valid as // long as this instance is valid. @@ -5302,7 +5303,6 @@ fn queue_call0( SendSyncPtr::new(callee), param_count, 1, - instance_flags, is_concurrent, callback, post_return.map(SendSyncPtr::new), diff --git a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs index 2843cd5b2ff6..cf0a3ef879ff 100644 --- a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs +++ b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs @@ -1,6 +1,7 @@ use crate::component::func::{LiftContext, LowerContext}; use crate::component::matching::InstanceType; -use crate::component::{ComponentType, Lift, Lower, Val}; +use crate::component::store::StoreComponentInstanceId; +use crate::component::{ComponentType, Lift, Lower, RuntimeInstance, Val}; use crate::store::StoreOpaque; use crate::{Result, bail, error::format_err}; use core::convert::Infallible; @@ -155,4 +156,16 @@ impl StoreOpaque { pub(crate) fn check_blocking(&mut self) -> Result<()> { Ok(()) } + + pub(crate) fn may_enter(&mut self, instance: RuntimeInstance) -> bool { + if self.trapped() { + return false; + } + + let flags = StoreComponentInstanceId::new(self.id(), instance.instance) + .get(self) + .instance_flags(instance.index); + + !unsafe { flags.needs_post_return() } + } } diff --git a/crates/wasmtime/src/runtime/component/func.rs b/crates/wasmtime/src/runtime/component/func.rs index 2abb0b4b8b43..0cbbff714f2f 100644 --- a/crates/wasmtime/src/runtime/component/func.rs +++ b/crates/wasmtime/src/runtime/component/func.rs @@ -1,3 +1,4 @@ +use crate::component::RuntimeInstance; use crate::component::instance::Instance; use crate::component::matching::InstanceType; use crate::component::storage::storage_as_slice; @@ -614,6 +615,15 @@ impl Func { LowerReturn: Copy, { let export = self.lifted_core_func(store.0); + let (_options, _flags, _ty, raw_options) = self.abi_info(store.0); + let instance = RuntimeInstance { + instance: self.instance.id().instance(), + index: raw_options.instance, + }; + + if !store.0.may_enter(instance) { + bail!(crate::Trap::CannotEnterComponent); + } #[repr(C)] union Union { @@ -788,9 +798,6 @@ impl Func { ); let post_return_arg = post_return_arg.expect("calling post_return on wrong function"); - // This is a sanity-check assert which shouldn't ever trip. - assert!(!flags.may_enter()); - // Unset the "needs post return" flag now that post-return is being // processed. This will cause future invocations of this method to // panic, even if the function call below traps. @@ -802,10 +809,6 @@ impl Func { // If the function actually had a `post-return` configured in its // canonical options that's executed here. - // - // Note that if this traps (returns an error) this function - // intentionally leaves the instance in a "poisoned" state where it - // can no longer be entered because `may_enter` is `false`. if let Some(func) = post_return { crate::Func::call_unchecked_raw( &mut store, @@ -816,9 +819,8 @@ impl Func { } // And finally if everything completed successfully then the "may - // enter" and "may leave" flags are set to `true` again here which - // enables further use of the component. - flags.set_may_enter(true); + // leave" flags is set to `true` again here which enables further + // use of the component. flags.set_may_leave(true); let (calls, host_table, _, instance) = store @@ -943,26 +945,12 @@ impl Func { fn with_lower_context( self, mut store: StoreContextMut, - may_enter: bool, + call_post_return_automatically: bool, lower: impl FnOnce(&mut LowerContext, InterfaceType) -> Result<()>, ) -> Result<()> { let (options_idx, mut flags, ty, options) = self.abi_info(store.0); let async_ = options.async_; - // Test the "may enter" flag which is a "lock" on this instance. - // This is immediately set to `false` afterwards and note that - // there's no on-cleanup setting this flag back to true. That's an - // intentional design aspect where if anything goes wrong internally - // from this point on the instance is considered "poisoned" and can - // never be entered again. The only time this flag is set to `true` - // again is after post-return logic has completed successfully. - unsafe { - if !flags.may_enter() { - bail!(crate::Trap::CannotEnterComponent); - } - flags.set_may_enter(false); - } - // Perform the actual lowering, where while this is running the // component is forbidden from calling imports. unsafe { @@ -975,14 +963,10 @@ impl Func { unsafe { flags.set_may_leave(true) }; result?; - // If this is an async function and `may_enter == true` then we're - // allowed to reenter the component at this point, and otherwise flag a - // post-return call being required as we're about to enter wasm and - // afterwards need a post-return. + // If needed, flag a post-return call being required as we're about to + // enter wasm and afterwards need a post-return. unsafe { - if may_enter && async_ { - flags.set_may_enter(true); - } else { + if !(call_post_return_automatically && async_) { flags.set_needs_post_return(true); } } diff --git a/crates/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs index 9c27afef8b31..29de0616532f 100644 --- a/crates/wasmtime/src/runtime/component/func/host.rs +++ b/crates/wasmtime/src/runtime/component/func/host.rs @@ -1,5 +1,7 @@ //! Implementation of calling Rust-defined functions from components. +#[cfg(feature = "component-model-async")] +use crate::component::RuntimeInstance; #[cfg(feature = "component-model-async")] use crate::component::concurrent; #[cfg(feature = "component-model-async")] @@ -339,9 +341,14 @@ where let ret = match self.run(store.as_context_mut(), params) { HostResult::Done(result) => result?, #[cfg(feature = "component-model-async")] - HostResult::Future(future) => { - concurrent::poll_and_block(store.0, future, caller_instance)? - } + HostResult::Future(future) => concurrent::poll_and_block( + store.0, + future, + RuntimeInstance { + instance: instance.id().instance(), + index: caller_instance, + }, + )?, }; let mut lower = LowerContext::new(store, options, instance); diff --git a/crates/wasmtime/src/runtime/component/func/options.rs b/crates/wasmtime/src/runtime/component/func/options.rs index 02a04df69ac0..55df5005cce7 100644 --- a/crates/wasmtime/src/runtime/component/func/options.rs +++ b/crates/wasmtime/src/runtime/component/func/options.rs @@ -2,12 +2,10 @@ use crate::StoreContextMut; use crate::component::concurrent::ConcurrentState; use crate::component::matching::InstanceType; use crate::component::resources::{HostResourceData, HostResourceIndex, HostResourceTables}; -use crate::component::{Instance, ResourceType}; +use crate::component::{Instance, ResourceType, RuntimeInstance}; use crate::prelude::*; use crate::runtime::vm::VMFuncRef; -use crate::runtime::vm::component::{ - CallContexts, ComponentInstance, HandleTable, InstanceFlags, ResourceTables, -}; +use crate::runtime::vm::component::{CallContexts, ComponentInstance, HandleTable, ResourceTables}; use crate::store::{StoreId, StoreOpaque}; use alloc::sync::Arc; use core::pin::Pin; @@ -260,10 +258,10 @@ impl<'a, T: 'static> LowerContext<'a, T> { &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { self.resource_tables() - .host_resource_lower_own(rep, dtor, flags) + .host_resource_lower_own(rep, dtor, instance) } /// Returns the underlying resource type for the `ty` table specified. @@ -422,10 +420,10 @@ impl<'a> LiftContext<'a> { &mut self, ty: TypeResourceTableIndex, idx: u32, - ) -> Result<(u32, Option>, Option)> { + ) -> Result<(u32, Option>, Option)> { let idx = self.resource_tables().guest_resource_lift_own(idx, ty)?; - let (dtor, flags) = self.instance.dtor_and_flags(ty); - Ok((idx, dtor, flags)) + let (dtor, instance) = self.instance.dtor_and_instance(ty); + Ok((idx, dtor, instance)) } /// Lifts a `borrow` resource from the guest at the `idx` specified. @@ -443,10 +441,10 @@ impl<'a> LiftContext<'a> { &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { self.resource_tables() - .host_resource_lower_own(rep, dtor, flags) + .host_resource_lower_own(rep, dtor, instance) } /// Lowers a resource into the host-owned table, returning the index it was diff --git a/crates/wasmtime/src/runtime/component/mod.rs b/crates/wasmtime/src/runtime/component/mod.rs index 38896e2e2a25..a641c02d8dab 100644 --- a/crates/wasmtime/src/runtime/component/mod.rs +++ b/crates/wasmtime/src/runtime/component/mod.rs @@ -139,7 +139,7 @@ pub use self::values::Val; pub(crate) use self::instance::RuntimeImport; pub(crate) use self::resources::HostResourceData; -pub(crate) use self::store::ComponentInstanceId; +pub(crate) use self::store::{ComponentInstanceId, RuntimeInstance}; // Re-export wasm_wave crate so the compatible version of this dep doesn't have to be // tracked separately from wasmtime. diff --git a/crates/wasmtime/src/runtime/component/resources/any.rs b/crates/wasmtime/src/runtime/component/resources/any.rs index 343b331bcc49..052c6ae5b4eb 100644 --- a/crates/wasmtime/src/runtime/component/resources/any.rs +++ b/crates/wasmtime/src/runtime/component/resources/any.rs @@ -192,11 +192,9 @@ impl ResourceAny { // Note that this should be safe because the raw pointer access in // `flags` is valid due to `store` being the owner of the flags and // flags are never destroyed within the store. - if let Some(flags) = slot.flags { - unsafe { - if !flags.may_enter() { - bail!(Trap::CannotEnterComponent); - } + if let Some(instance) = slot.instance { + if !store.0.may_enter(instance) { + bail!(Trap::CannotEnterComponent); } } diff --git a/crates/wasmtime/src/runtime/component/resources/host_tables.rs b/crates/wasmtime/src/runtime/component/resources/host_tables.rs index a5e965688156..3ef7253897f9 100644 --- a/crates/wasmtime/src/runtime/component/resources/host_tables.rs +++ b/crates/wasmtime/src/runtime/component/resources/host_tables.rs @@ -21,9 +21,8 @@ //! the own is removed or otherwise taken out. use crate::prelude::*; -use crate::runtime::vm::component::{ - InstanceFlags, ResourceTables, TypedResource, TypedResourceIndex, -}; +use crate::runtime::component::RuntimeInstance; +use crate::runtime::vm::component::{ResourceTables, TypedResource, TypedResourceIndex}; use crate::runtime::vm::{SendSyncPtr, VMFuncRef}; use crate::store::StoreOpaque; use core::ptr::NonNull; @@ -69,7 +68,7 @@ pub struct HostResourceData { #[derive(Copy, Clone)] pub struct TableSlot { generation: u32, - pub(super) flags: Option, + pub(super) instance: Option, pub(super) dtor: Option>, } @@ -144,16 +143,16 @@ impl<'a> HostResourceTables<'a> { /// will point to the `rep` specified. The returned index is suitable for /// conversion into either [`Resource`] or [`ResourceAny`]. /// - /// The `dtor` and instance `flags` are specified as well to know what + /// The `dtor` and instance `instance` are specified as well to know what /// destructor to run when this resource is destroyed. pub fn host_resource_lower_own( &mut self, rep: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> Result { let idx = self.tables.resource_lower_own(TypedResource::Host(rep))?; - Ok(self.new_host_index(idx, dtor, flags)) + Ok(self.new_host_index(idx, dtor, instance)) } /// See [`HostResourceTables::host_resource_lower_own`]. @@ -208,12 +207,12 @@ impl<'a> HostResourceTables<'a> { &mut self, idx: u32, dtor: Option>, - flags: Option, + instance: Option, ) -> HostResourceIndex { let list = &mut self.host_resource_data.table_slot_metadata; let info = TableSlot { generation: self.host_resource_data.cur_generation, - flags, + instance, dtor: dtor.map(SendSyncPtr::new), }; match list.get_mut(idx as usize) { @@ -225,7 +224,7 @@ impl<'a> HostResourceTables<'a> { assert_eq!(idx, 1); list.push(TableSlot { generation: 0, - flags: None, + instance: None, dtor: None, }); } diff --git a/crates/wasmtime/src/runtime/component/store.rs b/crates/wasmtime/src/runtime/component/store.rs index c24070c7eed2..d12e97d3748a 100644 --- a/crates/wasmtime/src/runtime/component/store.rs +++ b/crates/wasmtime/src/runtime/component/store.rs @@ -6,6 +6,7 @@ use crate::store::{StoreData, StoreId, StoreOpaque}; use alloc::vec::Vec; use core::pin::Pin; use wasmtime_environ::PrimaryMap; +use wasmtime_environ::component::RuntimeComponentInstanceIndex; #[derive(Default)] pub struct ComponentStoreData { @@ -16,6 +17,12 @@ pub struct ComponentStoreData { pub struct ComponentInstanceId(u32); wasmtime_environ::entity_impl!(ComponentInstanceId); +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct RuntimeInstance { + pub instance: ComponentInstanceId, + pub index: RuntimeComponentInstanceIndex, +} + impl StoreData { pub(crate) fn push_component_instance( &mut self, diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs index ae4ec58da371..5d5522d250da 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs @@ -1505,14 +1505,20 @@ pub(crate) fn invoke_wasm_and_catch_traps( // stack-allocated `previous_runtime_state`. let mut previous_runtime_state = EntryStoreContext::enter_wasm(store, &mut initial_stack_csi); - if let Err(trap) = store.0.call_hook(CallHook::CallingWasm) { - // `previous_runtime_state` implicitly dropped here - return Err(trap); - } - let result = crate::runtime::vm::catch_traps(store, &mut previous_runtime_state, closure); - core::mem::drop(previous_runtime_state); - store.0.call_hook(CallHook::ReturningFromWasm)?; - result + (|| { + if let Err(trap) = store.0.call_hook(CallHook::CallingWasm) { + // `previous_runtime_state` implicitly dropped here + return Err(trap); + } + let result = crate::runtime::vm::catch_traps(store, &mut previous_runtime_state, closure); + core::mem::drop(previous_runtime_state); + store.0.call_hook(CallHook::ReturningFromWasm)?; + result + })() + .inspect_err(|_| { + #[cfg(feature = "component-model")] + store.0.set_trapped(); + }) } /// 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 f41c401daf10..f82c8b602e6f 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -545,6 +545,10 @@ pub struct StoreOpaque { #[cfg(feature = "component-model")] concurrent_state: concurrent::ConcurrentState, + /// Whether an instance belonging to this store has trapped. + #[cfg(feature = "component-model")] + trapped: bool, + /// State related to the executor of wasm code. /// /// For example if Pulley is enabled and configured then this will store a @@ -764,6 +768,8 @@ impl Store { wasm_val_raw_storage: Vec::new(), pkey, #[cfg(feature = "component-model")] + trapped: false, + #[cfg(feature = "component-model")] component_host_table: Default::default(), #[cfg(feature = "component-model")] component_calls: Default::default(), @@ -2765,6 +2771,16 @@ at https://bytecodealliance.org/security. pub(crate) fn get_epoch_deadline(&mut self) -> u64 { *self.vm_store_context.epoch_deadline.get_mut() } + + #[cfg(feature = "component-model")] + pub(crate) fn trapped(&self) -> bool { + self.trapped + } + + #[cfg(feature = "component-model")] + pub(crate) fn set_trapped(&mut self) { + self.trapped = true; + } } /// Helper parameter to [`StoreOpaque::allocate_instance`]. diff --git a/crates/wasmtime/src/runtime/vm/component.rs b/crates/wasmtime/src/runtime/vm/component.rs index 35feb448d607..89ebc4796e26 100644 --- a/crates/wasmtime/src/runtime/vm/component.rs +++ b/crates/wasmtime/src/runtime/vm/component.rs @@ -9,9 +9,9 @@ use crate::Result; use crate::component::{Component, Instance, InstancePre, ResourceType, RuntimeImport}; use crate::module::ModuleRegistry; -use crate::runtime::component::ComponentInstanceId; #[cfg(feature = "component-model-async")] use crate::runtime::component::concurrent::ConcurrentInstanceState; +use crate::runtime::component::{ComponentInstanceId, RuntimeInstance}; use crate::runtime::vm::instance::{InstanceLayout, OwnedInstance, OwnedVMContext}; use crate::runtime::vm::vmcontext::VMFunctionBody; use crate::runtime::vm::{ @@ -700,7 +700,7 @@ impl ComponentInstance { // SAFETY: this is a valid initialization of all globals which are // 32-bit values. unsafe { - *def.as_i32_mut() = FLAG_MAY_ENTER | FLAG_MAY_LEAVE; + *def.as_i32_mut() = FLAG_MAY_LEAVE; self.instance_flags(i).as_raw().write(def); } } @@ -880,18 +880,20 @@ impl ComponentInstance { /// /// This will lookup the origin definition of the `ty` table and return the /// destructor/flags for that. - pub fn dtor_and_flags( + pub fn dtor_and_instance( &self, ty: TypeResourceTableIndex, - ) -> (Option>, Option) { + ) -> (Option>, Option) { let resource = self.component.types()[ty].unwrap_concrete_ty(); let dtor = self.resource_destructor(resource); let component = self.component.env_component(); - let flags = component.defined_resource_index(resource).map(|i| { - let instance = component.defined_resource_instances[i]; - self.instance_flags(instance) - }); - (dtor, flags) + let instance = component + .defined_resource_index(resource) + .map(|i| RuntimeInstance { + instance: self.id(), + index: component.defined_resource_instances[i], + }); + (dtor, instance) } /// Returns the store-local id that points to this component. @@ -1121,22 +1123,6 @@ impl InstanceFlags { } } - #[inline] - pub unsafe fn may_enter(&self) -> bool { - unsafe { *self.as_raw().as_ref().as_i32() & FLAG_MAY_ENTER != 0 } - } - - #[inline] - pub unsafe fn set_may_enter(&mut self, val: bool) { - unsafe { - if val { - *self.as_raw().as_mut().as_i32_mut() |= FLAG_MAY_ENTER; - } else { - *self.as_raw().as_mut().as_i32_mut() &= !FLAG_MAY_ENTER; - } - } - } - #[inline] pub unsafe fn needs_post_return(&self) -> bool { unsafe { *self.as_raw().as_ref().as_i32() & FLAG_NEEDS_POST_RETURN != 0 } diff --git a/crates/wasmtime/src/runtime/vm/component/libcalls.rs b/crates/wasmtime/src/runtime/vm/component/libcalls.rs index ae3d18edb635..bb426e98e11a 100644 --- a/crates/wasmtime/src/runtime/vm/component/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/component/libcalls.rs @@ -5,7 +5,9 @@ use crate::component::Instance; use crate::component::concurrent::WaitResult; use crate::prelude::*; #[cfg(feature = "component-model-async")] -use crate::runtime::component::concurrent::{ResourcePair, RuntimeInstance}; +use crate::runtime::component::RuntimeInstance; +#[cfg(feature = "component-model-async")] +use crate::runtime::component::concurrent::ResourcePair; use crate::runtime::vm::component::{ComponentInstance, VMComponentContext}; use crate::runtime::vm::{HostResultHasUnwindSentinel, VMStore, VmSafe}; use core::cell::Cell; diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index 5fd35d7d9db3..426768977f19 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -2636,7 +2636,7 @@ impl<'a> InterfaceGenerator<'a> { if flags.contains(FunctionFlags::STORE | FunctionFlags::ASYNC) { uwrite!( self.src, - "(accessor: &{wt}::component::Accessor, " + "(accessor: &{wt}::component::Accessor, " ); } else if flags.contains(FunctionFlags::STORE) { uwrite!(self.src, "(host: {wt}::component::Access, "); diff --git a/tests/all/component_model/func.rs b/tests/all/component_model/func.rs index d0e8dc924fec..f35a8a1e26a2 100644 --- a/tests/all/component_model/func.rs +++ b/tests/all/component_model/func.rs @@ -183,8 +183,7 @@ fn integers() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; let mut store = Store::new(&engine, ()); - let new_instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component); - let instance = new_instance(&mut store)?; + let instance = Linker::new(&engine).instantiate(&mut store, &component)?; // Passing in 100 is valid for all primitives instance @@ -213,46 +212,62 @@ fn integers() -> Result<()> { .call_and_post_return(&mut store, (100,))?; // This specific wasm instance traps if any value other than 100 is passed - new_instance(&mut store)? - .get_typed_func::<(u8,), ()>(&mut store, "take-u8")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i8,), ()>(&mut store, "take-s8")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u16,), ()>(&mut store, "take-u16")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i16,), ()>(&mut store, "take-s16")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u32,), ()>(&mut store, "take-u32")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i32,), ()>(&mut store, "take-s32")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(u64,), ()>(&mut store, "take-u64")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; - new_instance(&mut store)? - .get_typed_func::<(i64,), ()>(&mut store, "take-s64")? - .call(&mut store, (101,)) - .unwrap_err() - .downcast::()?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u8,), ()>(&mut *store, "take-u8")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i8,), ()>(&mut *store, "take-s8")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u16,), ()>(&mut *store, "take-u16")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i16,), ()>(&mut *store, "take-s16")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u32,), ()>(&mut *store, "take-u32")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i32,), ()>(&mut *store, "take-s32")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(u64,), ()>(&mut *store, "take-u64")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(i64,), ()>(&mut *store, "take-s64")? + .call(store, (101,)) + .unwrap_err() + .downcast::() + })?; // Zero can be returned as any integer assert_eq!( @@ -1991,35 +2006,39 @@ fn some_traps() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component); // This should fail when calling the allocator function for the argument - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")? - .call(&mut store, (&[],)) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-unreachable")? + .call(store, (&[],)) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // This should fail when calling the allocator function for the argument - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")? - .call(&mut store, ("",)) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-unreachable")? + .call(store, ("",)) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // This should fail when calling the allocator function for the space // to store the arguments (before arguments are even lowered) - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-unreachable", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err() - .downcast::()?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-unreachable", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + .unwrap_err() + .downcast::() + })?; assert_eq!(err, Trap::UnreachableCodeReached); // Assert that when the base pointer returned by malloc is out of bounds @@ -2036,87 +2055,115 @@ fn some_traps() -> Result<()> { "{err:?}", ); } - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")? - .call(&mut store, (&[],)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-base-oob")? + .call(store, (&[],)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")? - .call(&mut store, (&[1],)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-base-oob")? + .call(store, (&[1],)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")? - .call(&mut store, ("",)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-base-oob")? + .call(store, ("",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")? - .call(&mut store, ("x",)) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-base-oob")? + .call(store, ("x",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-base-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-base-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); // Test here that when the returned pointer from malloc is one byte from the // end of memory that empty things are fine, but larger things are not. - instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call_and_post_return(&mut store, (&[],))?; - instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?; - let err = instance(&mut store)? - .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")? - .call(&mut store, (&[1, 2, 3, 4, 5],)) - .unwrap_err(); + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call_and_post_return(store, (&[],)) + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call_and_post_return(store, (&[1, 2, 3, 4],)) + })?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&[u8],), ()>(&mut *store, "take-list-end-oob")? + .call(store, (&[1, 2, 3, 4, 5],)) + }) + .unwrap_err(); assert_oob(&err); - instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call_and_post_return(&mut store, ("",))?; - instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call_and_post_return(&mut store, ("abcd",))?; - let err = instance(&mut store)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")? - .call(&mut store, ("abcde",)) - .unwrap_err(); + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call_and_post_return(store, ("",)) + })?; + with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call_and_post_return(store, ("abcd",)) + })?; + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str,), ()>(&mut *store, "take-string-end-oob")? + .call(store, ("abcde",)) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-end-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-end-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); // For this function the first allocation, the space to store all the // arguments, is in-bounds but then all further allocations, such as for // each individual string, are all out of bounds. - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-second-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-second-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "")) + }) + .unwrap_err(); assert_oob(&err); - let err = instance(&mut store)? - .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( - &mut store, - "take-many-second-oob", - )? - .call(&mut store, ("", "", "", "", "", "", "", "", "", "x")) - .unwrap_err(); + let err = with_new_instance(&engine, &component, |store, instance| { + instance + .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>( + &mut *store, + "take-many-second-oob", + )? + .call(store, ("", "", "", "", "", "", "", "", "", "x")) + }) + .unwrap_err(); assert_oob(&err); Ok(()) } @@ -3223,24 +3270,39 @@ fn errors_that_poison_instance() -> Result<()> { let engine = super::engine(); let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); let linker = Linker::new(&engine); - let instance = linker.instantiate(&mut store, &component)?; - let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?; - let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?; - assert_unreachable(f1.call(&mut store, ())); - assert_poisoned(f1.call(&mut store, ())); - assert_poisoned(f2.call(&mut store, ())); - let instance = linker.instantiate(&mut store, &component)?; - let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; - assert_unreachable(f3.call(&mut store, ("x",))); - assert_poisoned(f3.call(&mut store, ("x",))); + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?; + let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?; + assert_unreachable(f1.call(&mut store, ())); + assert_poisoned(f1.call(&mut store, ())); + assert_poisoned(f2.call(&mut store, ())); + } - let instance = linker.instantiate(&mut store, &component)?; - let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?; - assert!(f4.call(&mut store, ()).is_err()); - assert_poisoned(f4.call(&mut store, ())); + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; + assert_unreachable(f3.call(&mut store, ("x",))); + assert_poisoned(f3.call(&mut store, ("x",))); + + // Since we actually poison the store, even an unrelated instance will + // be considered poisoned: + let instance = linker.instantiate(&mut store, &component)?; + let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?; + assert_poisoned(f3.call(&mut store, ("x",))); + } + + { + let mut store = Store::new(&engine, ()); + let instance = linker.instantiate(&mut store, &component)?; + let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?; + assert!(f4.call(&mut store, ()).is_err()); + assert_poisoned(f4.call(&mut store, ())); + } return Ok(()); @@ -3316,3 +3378,98 @@ fn run_export_with_internal_adapter() -> Result<()> { assert_eq!(run.call(&mut store, ())?, (5,)); Ok(()) } + +enum RecurseKind { + AThenA, + AThenB, + AThenBThenA, +} + +#[test] +fn recurse() -> Result<()> { + test_recurse(RecurseKind::AThenB) +} + +#[test] +fn recurse_trap() -> Result<()> { + let error = test_recurse(RecurseKind::AThenA).unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +#[test] +fn recurse_more_trap() -> Result<()> { + let error = test_recurse(RecurseKind::AThenBThenA).unwrap_err(); + + assert_eq!(error.downcast::()?, Trap::CannotEnterComponent); + + Ok(()) +} + +fn test_recurse(kind: RecurseKind) -> Result<()> { + #[derive(Default)] + struct Ctx { + instances: Vec>, + } + + let component = r#" +(component + (import "import" (func $import)) + (core func $import (canon lower (func $import))) + (core module $m + (func $import (import "" "import")) + (func (export "export") call $import) + ) + (core instance $m (instantiate $m (with "" (instance + (export "import" (func $import)) + )))) + (func (export "export") (canon lift (core func $m "export"))) +) +"#; + let engine = super::engine(); + let component = Component::new(&engine, component)?; + let mut store = Store::new(&engine, Ctx::default()); + let mut linker = Linker::::new(&engine); + linker.root().func_wrap("import", |mut store, (): ()| { + if let Some(instance) = store.data_mut().instances.pop() { + let run = instance.get_typed_func::<(), ()>(&mut store, "export")?; + run.call(&mut store, ())?; + store.data_mut().instances.push(instance); + } + Ok(()) + })?; + let instance = Arc::new(linker.instantiate(&mut store, &component)?); + let instance = match kind { + RecurseKind::AThenA => { + store.data_mut().instances.push(instance.clone()); + instance + } + RecurseKind::AThenB => { + let other = Arc::new(linker.instantiate(&mut store, &component)?); + store.data_mut().instances.push(other); + instance + } + RecurseKind::AThenBThenA => { + store.data_mut().instances.push(instance.clone()); + let other = Arc::new(linker.instantiate(&mut store, &component)?); + store.data_mut().instances.push(other); + instance + } + }; + + let run = instance.get_typed_func::<(), ()>(&mut store, "export")?; + run.call(&mut store, ())?; + Ok(()) +} + +fn with_new_instance( + engine: &Engine, + component: &Component, + fun: impl Fn(&mut Store<()>, Instance) -> wasmtime::Result, +) -> wasmtime::Result { + let mut store = Store::new(engine, ()); + let instance = Linker::new(engine).instantiate(&mut store, component)?; + fun(&mut store, instance) +} diff --git a/tests/all/component_model/import.rs b/tests/all/component_model/import.rs index 3ab9c50d8188..b83e0cd95d21 100644 --- a/tests/all/component_model/import.rs +++ b/tests/all/component_model/import.rs @@ -348,55 +348,63 @@ fn attempt_to_leave_during_malloc() -> Result<()> { Ok(("hello".to_string(),)) })?; let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - // Assert that during a host import if we return values to wasm that a trap - // happens if we try to leave the instance. - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "run")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("cannot leave component instance"), - "bad trap: {trap:?}", - ); + { + let mut store = Store::new(&engine, ()); + + // Assert that during a host import if we return values to wasm that a trap + // happens if we try to leave the instance. + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "run")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("cannot leave component instance"), + "bad trap: {trap:?}", + ); + + let trace = trap.downcast_ref::().unwrap().frames(); + assert_eq!(trace.len(), 4); + + // This was our entry point... + assert_eq!(trace[3].module().name(), Some("m")); + assert_eq!(trace[3].func_name(), Some("run")); + + // ... which called an imported function which ends up being originally + // defined by the shim instance. The shim instance then does an indirect + // call through a table which goes to the `canon.lower`'d host function + assert_eq!(trace[2].module().name(), Some("host_shim")); + assert_eq!(trace[2].func_name(), Some("shim_ret_string")); + + // ... and the lowered host function will call realloc to allocate space for + // the result + assert_eq!(trace[1].module().name(), Some("m")); + assert_eq!(trace[1].func_name(), Some("realloc")); + + // ... but realloc calls the shim instance and tries to exit the + // component, triggering a dynamic trap + assert_eq!(trace[0].module().name(), Some("host_shim")); + assert_eq!(trace[0].func_name(), Some("shim_thunk")); + } + + { + let mut store = Store::new(&engine, ()); + + // In addition to the above trap also ensure that when we enter a wasm + // component if we try to leave while lowering then that's also a dynamic + // trap. + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(&str,), ()>(&mut store, "take-string")? + .call(&mut store, ("x",)) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("cannot leave component instance"), + "bad trap: {trap:?}", + ); + } - let trace = trap.downcast_ref::().unwrap().frames(); - assert_eq!(trace.len(), 4); - - // This was our entry point... - assert_eq!(trace[3].module().name(), Some("m")); - assert_eq!(trace[3].func_name(), Some("run")); - - // ... which called an imported function which ends up being originally - // defined by the shim instance. The shim instance then does an indirect - // call through a table which goes to the `canon.lower`'d host function - assert_eq!(trace[2].module().name(), Some("host_shim")); - assert_eq!(trace[2].func_name(), Some("shim_ret_string")); - - // ... and the lowered host function will call realloc to allocate space for - // the result - assert_eq!(trace[1].module().name(), Some("m")); - assert_eq!(trace[1].func_name(), Some("realloc")); - - // ... but realloc calls the shim instance and tries to exit the - // component, triggering a dynamic trap - assert_eq!(trace[0].module().name(), Some("host_shim")); - assert_eq!(trace[0].func_name(), Some("shim_thunk")); - - // In addition to the above trap also ensure that when we enter a wasm - // component if we try to leave while lowering then that's also a dynamic - // trap. - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(&str,), ()>(&mut store, "take-string")? - .call(&mut store, ("x",)) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("cannot leave component instance"), - "bad trap: {trap:?}", - ); Ok(()) } @@ -1048,28 +1056,34 @@ fn bad_import_alignment() -> Result<()> { -> Result<()> { unreachable!() }, )?; let component = Component::new(&engine, component)?; - let mut store = Store::new(&engine, ()); - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "unaligned-retptr2")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("pointer not aligned"), - "{}", - trap - ); - let trap = linker - .instantiate(&mut store, &component)? - .get_typed_func::<(), ()>(&mut store, "unaligned-argptr2")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - format!("{trap:?}").contains("pointer not aligned"), - "{}", - trap - ); + { + let mut store = Store::new(&engine, ()); + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "unaligned-retptr2")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("pointer not aligned"), + "{}", + trap + ); + } + + { + let mut store = Store::new(&engine, ()); + let trap = linker + .instantiate(&mut store, &component)? + .get_typed_func::<(), ()>(&mut store, "unaligned-argptr2")? + .call(&mut store, ()) + .unwrap_err(); + assert!( + format!("{trap:?}").contains("pointer not aligned"), + "{}", + trap + ); + } Ok(()) } diff --git a/tests/all/component_model/strings.rs b/tests/all/component_model/strings.rs index 3caabf432531..ce60ea10fdb8 100644 --- a/tests/all/component_model/strings.rs +++ b/tests/all/component_model/strings.rs @@ -314,10 +314,10 @@ fn test_ptr_overflow(engine: &Engine, src: &str, dst: &str) -> Result<()> { ); let component = Component::new(engine, &component)?; - let mut store = Store::new(engine, ()); - let mut test_overflow = |size: u32| -> Result<()> { + let test_overflow = |size: u32| -> Result<()> { println!("src={src} dst={dst} size={size:#x}"); + let mut store = Store::new(engine, ()); let instance = Linker::new(engine).instantiate(&mut store, &component)?; let func = instance.get_typed_func::<(u32,), ()>(&mut store, "f")?; let trap = func diff --git a/tests/component-model b/tests/component-model index 48603cbc04db..ac37fe92a218 160000 --- a/tests/component-model +++ b/tests/component-model @@ -1 +1 @@ -Subproject commit 48603cbc04dbb3e69cefba5b259941876459fb8d +Subproject commit ac37fe92a21865aa8ca84b5bcbeb2da3746b6dc8 diff --git a/tests/misc_testsuite/component-model/adapter.wast b/tests/misc_testsuite/component-model/adapter.wast index 0ca70a1dc63e..8432d5841a73 100644 --- a/tests/misc_testsuite/component-model/adapter.wast +++ b/tests/misc_testsuite/component-model/adapter.wast @@ -112,7 +112,7 @@ (with "" (instance (export "" (func $f2)))) )) ) - "degenerate component adapter called") + "cannot enter component instance") ;; fiddling with 0-sized lists (component $c diff --git a/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast b/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast index 5a45f89302a6..06e6df3df447 100644 --- a/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast +++ b/tests/misc_testsuite/component-model/async/backpressure-deadlock.wast @@ -38,60 +38,71 @@ ) (instance $A (instantiate $A)) - (core module $libc (memory (export "mem") 1)) - (core instance $libc (instantiate $libc)) - - (core func $f (canon lower (func $A "f") async (memory $libc "mem"))) - (core func $turn-on-backpressure (canon lower (func $A "turn-on-backpressure"))) - (core func $waitable-set.new (canon waitable-set.new)) - (core func $waitable.join (canon waitable.join)) - (core func $waitable-set.wait (canon waitable-set.wait (memory $libc "mem"))) - - (core module $m - (import "" "f" (func $f (result i32))) - (import "" "turn-on-backpressure" (func $turn-on-backpressure)) - (import "" "waitable-set.new" (func $waitable-set.new (result i32))) - (import "" "waitable.join" (func $waitable.join (param i32 i32))) - (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32))) - - (func (export "f") - (local $status i32) - (local $set i32) - call $turn-on-backpressure - - (local.set $status (call $f)) - - ;; low 4 bits should be "STARTING == 0" - (i32.ne - (i32.const 0) - (i32.and - (local.get $status) - (i32.const 0xf))) - if unreachable end - - ;; make a new waitable set and join our subtask into it - (local.set $set (call $waitable-set.new)) - (call $waitable.join - (i32.shr_u (local.get $status) (i32.const 4)) - (local.get $set)) - - ;; block waiting for our task, which should deadlock (?) - (call $waitable-set.wait (local.get $set) (i32.const 0)) - unreachable + (component $B + (import "A" (instance $A + (export "f" (func)) + (export "turn-on-backpressure" (func)) + )) + + (core module $libc (memory (export "mem") 1)) + (core instance $libc (instantiate $libc)) + + (core func $f (canon lower (func $A "f") async (memory $libc "mem"))) + (core func $turn-on-backpressure (canon lower (func $A "turn-on-backpressure"))) + (core func $waitable-set.new (canon waitable-set.new)) + (core func $waitable.join (canon waitable.join)) + (core func $waitable-set.wait (canon waitable-set.wait (memory $libc "mem"))) + + (core module $m + (import "" "f" (func $f (result i32))) + (import "" "turn-on-backpressure" (func $turn-on-backpressure)) + (import "" "waitable-set.new" (func $waitable-set.new (result i32))) + (import "" "waitable.join" (func $waitable.join (param i32 i32))) + (import "" "waitable-set.wait" (func $waitable-set.wait (param i32 i32) (result i32))) + + (func (export "f") + (local $status i32) + (local $set i32) + call $turn-on-backpressure + + (local.set $status (call $f)) + + ;; low 4 bits should be "STARTING == 0" + (i32.ne + (i32.const 0) + (i32.and + (local.get $status) + (i32.const 0xf))) + if unreachable end + + ;; make a new waitable set and join our subtask into it + (local.set $set (call $waitable-set.new)) + (call $waitable.join + (i32.shr_u (local.get $status) (i32.const 4)) + (local.get $set)) + + ;; block waiting for our task, which should deadlock (?) + (call $waitable-set.wait (local.get $set) (i32.const 0)) + unreachable + ) ) + + (core instance $i (instantiate $m + (with "" (instance + (export "f" (func $f)) + (export "turn-on-backpressure" (func $turn-on-backpressure)) + (export "waitable-set.new" (func $waitable-set.new)) + (export "waitable.join" (func $waitable.join)) + (export "waitable-set.wait" (func $waitable-set.wait)) + )) + )) + + (func (export "f") async (canon lift (core func $i "f"))) ) - (core instance $i (instantiate $m - (with "" (instance - (export "f" (func $f)) - (export "turn-on-backpressure" (func $turn-on-backpressure)) - (export "waitable-set.new" (func $waitable-set.new)) - (export "waitable.join" (func $waitable.join)) - (export "waitable-set.wait" (func $waitable-set.wait)) - )) - )) + (instance $B (instantiate $B (with "A" (instance $A)))) - (func (export "f") async (canon lift (core func $i "f"))) + (func (export "f") (alias export $B "f")) ) (assert_trap (invoke "f") "deadlock detected") diff --git a/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast b/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast index 82a689baaf70..40a15db92fb4 100644 --- a/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast +++ b/tests/misc_testsuite/component-model/async/future-cancel-write-completed.wast @@ -42,55 +42,64 @@ ) (instance $c (instantiate $c)) - (core func $new (canon future.new $f)) - (core module $libc (memory (export "mem") 1)) - (core instance $libc (instantiate $libc)) - (core func $write (canon future.write $f async (memory $libc "mem"))) - (core func $cancel (canon future.cancel-write $f)) - (core func $drain (canon lower (func $c "f"))) - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "write" (func $write (param i32 i32) (result i32))) - (import "" "cancel" (func $cancel (param i32) (result i32))) - (import "" "drain" (func $drain (param i32))) - - (func (export "f") (result i32) - (local $read i32) - (local $write i32) - (local $new i64) - - (local.set $new (call $new)) - (local.set $read (i32.wrap_i64 (local.get $new))) - (local.set $write (i32.wrap_i64 (i64.shr_u (local.get $new) (i64.const 32)))) - - ;; start a write - local.get $write - i32.const 0 - call $write - i32.const -1 - i32.ne - if unreachable end - - ;; drain the read end - local.get $read - call $drain - - ;; cancel the write, returning the result - local.get $write - call $cancel + (component $d + (import "c" (instance $c + (export "f" (func (param "x" $f))) + )) + + (core func $new (canon future.new $f)) + (core module $libc (memory (export "mem") 1)) + (core instance $libc (instantiate $libc)) + (core func $write (canon future.write $f async (memory $libc "mem"))) + (core func $cancel (canon future.cancel-write $f)) + (core func $drain (canon lower (func $c "f"))) + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "write" (func $write (param i32 i32) (result i32))) + (import "" "cancel" (func $cancel (param i32) (result i32))) + (import "" "drain" (func $drain (param i32))) + + (func (export "f") (result i32) + (local $read i32) + (local $write i32) + (local $new i64) + + (local.set $new (call $new)) + (local.set $read (i32.wrap_i64 (local.get $new))) + (local.set $write (i32.wrap_i64 (i64.shr_u (local.get $new) (i64.const 32)))) + + ;; start a write + local.get $write + i32.const 0 + call $write + i32.const -1 + i32.ne + if unreachable end + + ;; drain the read end + local.get $read + call $drain + + ;; cancel the write, returning the result + local.get $write + call $cancel + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "write" (func $write)) - (export "cancel" (func $cancel)) - (export "drain" (func $drain)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "write" (func $write)) + (export "cancel" (func $cancel)) + (export "drain" (func $drain)) + )) )) - )) - (func (export "f") async (result u32) (canon lift (core func $i "f"))) + (func (export "f") async (result u32) (canon lift (core func $i "f"))) + ) + (instance $d (instantiate $d (with "c" (instance $c)))) + + (func (export "f") (alias export $d "f")) ) (assert_return (invoke "f") (u32.const 0)) diff --git a/tests/misc_testsuite/component-model/async/future-read.wast b/tests/misc_testsuite/component-model/async/future-read.wast index ec80f85796b7..523dfb3f2c3a 100644 --- a/tests/misc_testsuite/component-model/async/future-read.wast +++ b/tests/misc_testsuite/component-model/async/future-read.wast @@ -30,27 +30,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func async (param "x" $future))) + )) + + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) ;; We expect deadlock since the write end is leaked: @@ -83,27 +91,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_return (invoke "run")) @@ -139,27 +155,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func async (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) ;; We expect deadlock since the write end is leaked: @@ -200,27 +224,35 @@ ) (instance $child (instantiate $child)) - (type $future (future)) - (core func $new (canon future.new $future)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "new" (func $new (result i64))) - (import "" "child-run" (func $child-run (param i32))) - - (func (export "run") - (call $child-run (i32.wrap_i64 (call $new))) + (component $other-child + (type $future (future)) + (import "child" (instance $child + (export "run" (func (param "x" $future))) + )) + (core func $new (canon future.new $future)) + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "new" (func $new (result i64))) + (import "" "child-run" (func $child-run (param i32))) + + (func (export "run") + (call $child-run (i32.wrap_i64 (call $new))) + ) ) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "new" (func $new)) - (export "child-run" (func $child-run)) + (core instance $i (instantiate $m + (with "" (instance + (export "new" (func $new)) + (export "child-run" (func $child-run)) + )) )) - )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_return (invoke "run")) diff --git a/tests/misc_testsuite/component-model/async/reenter-during-yield.wast b/tests/misc_testsuite/component-model/async/reenter-during-yield.wast new file mode 100644 index 000000000000..61fcb12ae107 --- /dev/null +++ b/tests/misc_testsuite/component-model/async/reenter-during-yield.wast @@ -0,0 +1,82 @@ +;;! component_model_async = true +;;! reference_types = true +;;! gc_types = true +;;! multi_memory = true + +(component + (component $a + (core module $a + (import "" "yield" (func $yield (result i32))) + + (func (export "yield-loop") (result i32) + ;; simulate `waitable-set.poll` with a yield loop + (loop + call $yield + drop + br 0 + ) + unreachable + ) + + ;; not reached + (func (export "callback") (param i32 i32 i32) (result i32) unreachable) + + (func (export "noop")) + ) + (core func $yield (canon thread.yield)) + (core instance $a (instantiate $a + (with "" (instance + (export "yield" (func $yield)) + )) + )) + (func (export "yield-loop") async + (canon lift + (core func $a "yield-loop") + async + (callback (func $a "callback")) + ) + ) + (func (export "noop") (canon lift (core func $a "noop"))) + ) + (instance $a (instantiate $a)) + + (component $b + (import "yield-loop" (func $yield-loop async)) + (import "noop" (func $noop)) + + (core func $yield-loop (canon lower (func $yield-loop) async)) + (core func $noop (canon lower (func $noop))) + + (core module $b + (import "" "yield-loop" (func $yield-loop (result i32))) + (import "" "noop" (func $noop)) + + (func (export "run") + ;; call `yield-loop`, double-check it's in the "started" state. + call $yield-loop + i32.const 0xf + i32.and + i32.const 1 + i32.ne + if unreachable end + + ;; now try to reenter the other component with some other function. + call $noop + ) + ) + (core instance $b (instantiate $b + (with "" (instance + (export "yield-loop" (func $yield-loop)) + (export "noop" (func $noop)) + )) + )) + (func (export "run") async (canon lift (core func $b "run"))) + ) + (instance $b (instantiate $b + (with "yield-loop" (func $a "yield-loop")) + (with "noop" (func $a "noop")) + )) + (export "run" (func $b "run")) +) + +(assert_return (invoke "run")) diff --git a/tests/misc_testsuite/component-model/async/wait-forever.wast b/tests/misc_testsuite/component-model/async/wait-forever.wast index 7f73f2ee995f..718fd3142d77 100644 --- a/tests/misc_testsuite/component-model/async/wait-forever.wast +++ b/tests/misc_testsuite/component-model/async/wait-forever.wast @@ -35,22 +35,30 @@ ) (instance $child (instantiate $child)) - (core func $child-run (canon lower (func $child "run"))) - - (core module $m - (import "" "child-run" (func $child-run)) - - (func (export "run") - (call $child-run)) - ) - (core instance $i (instantiate $m - (with "" (instance - (export "child-run" (func $child-run)) + (component $other-child + (import "child" (instance $child + (export "run" (func async)) )) - )) + + (core func $child-run (canon lower (func $child "run"))) + (core module $m + (import "" "child-run" (func $child-run)) + + (func (export "run") + (call $child-run)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "child-run" (func $child-run)) + )) + )) + + (func (export "run") async + (canon lift (core func $i "run"))) + ) + (instance $other-child (instantiate $other-child (with "child" (instance $child)))) - (func (export "run") async - (canon lift (core func $i "run"))) + (func (export "run") (alias export $other-child "run")) ) (assert_trap (invoke "run") "deadlock detected") From 7665ddce9b925a55b614d2bed9f003aa6d24ac84 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Jan 2026 11:21:58 -0700 Subject: [PATCH 2/5] bless bindgen expansions --- .../tests/expanded/char_concurrent.rs | 4 +- .../tests/expanded/conventions_concurrent.rs | 24 ++++---- .../tests/expanded/dead-code_concurrent.rs | 2 +- .../expanded/direct-import_concurrent.rs | 2 +- .../tests/expanded/flags_concurrent.rs | 14 ++--- .../tests/expanded/floats_concurrent.rs | 8 +-- .../tests/expanded/host-world_concurrent.rs | 2 +- .../tests/expanded/integers_concurrent.rs | 36 ++++++------ .../tests/expanded/lists_concurrent.rs | 58 +++++++++---------- .../expanded/many-arguments_concurrent.rs | 4 +- .../tests/expanded/multiversion_concurrent.rs | 4 +- .../tests/expanded/records_concurrent.rs | 22 +++---- .../tests/expanded/rename_concurrent.rs | 2 +- .../expanded/resources-import_concurrent.rs | 56 +++++++++--------- .../tests/expanded/share-types_concurrent.rs | 2 +- .../expanded/simple-functions_concurrent.rs | 12 ++-- .../tests/expanded/simple-lists_concurrent.rs | 8 +-- .../tests/expanded/simple-wasi_concurrent.rs | 4 +- .../expanded/small-anonymous_concurrent.rs | 2 +- .../tests/expanded/smoke_concurrent.rs | 2 +- .../tests/expanded/strings_concurrent.rs | 6 +- .../expanded/unstable-features_concurrent.rs | 8 +-- .../expanded/unversioned-foo_concurrent.rs | 2 +- .../tests/expanded/use-paths_concurrent.rs | 8 +-- .../tests/expanded/variants_concurrent.rs | 40 ++++++------- 25 files changed, 166 insertions(+), 166 deletions(-) diff --git a/crates/component-macro/tests/expanded/char_concurrent.rs b/crates/component-macro/tests/expanded/char_concurrent.rs index cd266fa9b8de..41963cad8457 100644 --- a/crates/component-macro/tests/expanded/char_concurrent.rs +++ b/crates/component-macro/tests/expanded/char_concurrent.rs @@ -191,12 +191,12 @@ pub mod foo { use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { /// A function that accepts a character - fn take_char( + fn take_char( accessor: &wasmtime::component::Accessor, x: char, ) -> impl ::core::future::Future + Send; /// A function that returns a character - fn return_char( + fn return_char( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/conventions_concurrent.rs b/crates/component-macro/tests/expanded/conventions_concurrent.rs index 73061589895e..a5678bed85d4 100644 --- a/crates/component-macro/tests/expanded/conventions_concurrent.rs +++ b/crates/component-macro/tests/expanded/conventions_concurrent.rs @@ -224,29 +224,29 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn kebab_case( + fn kebab_case( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, x: LudicrousSpeed, ) -> impl ::core::future::Future + Send; - fn function_with_dashes( + fn function_with_dashes( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn function_with_no_weird_characters( + fn function_with_no_weird_characters( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple( + fn apple( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple_pear( + fn apple_pear( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn apple_pear_grape( + fn apple_pear_grape( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn a0( + fn a0( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; /// Comment out identifiers that collide when mapped to snake_case, for now; see @@ -254,17 +254,17 @@ pub mod foo { /// APPLE: func() /// APPLE-pear-GRAPE: func() /// apple-PEAR-grape: func() - fn is_xml( + fn is_xml( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn explicit( + fn explicit( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn explicit_kebab( + fn explicit_kebab( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; /// Identifiers with the same name as keywords are quoted. - fn bool( + fn bool( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/dead-code_concurrent.rs b/crates/component-macro/tests/expanded/dead-code_concurrent.rs index a277b8c7dec2..b1277ba78c33 100644 --- a/crates/component-macro/tests/expanded/dead-code_concurrent.rs +++ b/crates/component-macro/tests/expanded/dead-code_concurrent.rs @@ -206,7 +206,7 @@ pub mod a { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f( + fn f( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/direct-import_concurrent.rs b/crates/component-macro/tests/expanded/direct-import_concurrent.rs index 81606a4d8e92..b2da9df1ec20 100644 --- a/crates/component-macro/tests/expanded/direct-import_concurrent.rs +++ b/crates/component-macro/tests/expanded/direct-import_concurrent.rs @@ -99,7 +99,7 @@ pub struct FooIndices {} /// [`Linker`]: wasmtime::component::Linker pub struct Foo {} pub trait FooImportsWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/flags_concurrent.rs b/crates/component-macro/tests/expanded/flags_concurrent.rs index fa3e3b8906e4..6830b9702938 100644 --- a/crates/component-macro/tests/expanded/flags_concurrent.rs +++ b/crates/component-macro/tests/expanded/flags_concurrent.rs @@ -304,31 +304,31 @@ pub mod foo { assert!(4 == < Flag64 as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn roundtrip_flag1( + fn roundtrip_flag1( accessor: &wasmtime::component::Accessor, x: Flag1, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag2( + fn roundtrip_flag2( accessor: &wasmtime::component::Accessor, x: Flag2, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag4( + fn roundtrip_flag4( accessor: &wasmtime::component::Accessor, x: Flag4, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag8( + fn roundtrip_flag8( accessor: &wasmtime::component::Accessor, x: Flag8, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag16( + fn roundtrip_flag16( accessor: &wasmtime::component::Accessor, x: Flag16, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag32( + fn roundtrip_flag32( accessor: &wasmtime::component::Accessor, x: Flag32, ) -> impl ::core::future::Future + Send; - fn roundtrip_flag64( + fn roundtrip_flag64( accessor: &wasmtime::component::Accessor, x: Flag64, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/floats_concurrent.rs b/crates/component-macro/tests/expanded/floats_concurrent.rs index 14361bf3d49d..1d9a72f092fc 100644 --- a/crates/component-macro/tests/expanded/floats_concurrent.rs +++ b/crates/component-macro/tests/expanded/floats_concurrent.rs @@ -192,18 +192,18 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f32_param( + fn f32_param( accessor: &wasmtime::component::Accessor, x: f32, ) -> impl ::core::future::Future + Send; - fn f64_param( + fn f64_param( accessor: &wasmtime::component::Accessor, x: f64, ) -> impl ::core::future::Future + Send; - fn f32_result( + fn f32_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f64_result( + fn f64_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/host-world_concurrent.rs b/crates/component-macro/tests/expanded/host-world_concurrent.rs index a5e3b741ac25..8e49386e3c10 100644 --- a/crates/component-macro/tests/expanded/host-world_concurrent.rs +++ b/crates/component-macro/tests/expanded/host-world_concurrent.rs @@ -99,7 +99,7 @@ pub struct Host_Indices {} /// [`Linker`]: wasmtime::component::Linker pub struct Host_ {} pub trait Host_ImportsWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/integers_concurrent.rs b/crates/component-macro/tests/expanded/integers_concurrent.rs index aceff239d6bd..43959402cdb9 100644 --- a/crates/component-macro/tests/expanded/integers_concurrent.rs +++ b/crates/component-macro/tests/expanded/integers_concurrent.rs @@ -192,39 +192,39 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a1( + fn a1( accessor: &wasmtime::component::Accessor, x: u8, ) -> impl ::core::future::Future + Send; - fn a2( + fn a2( accessor: &wasmtime::component::Accessor, x: i8, ) -> impl ::core::future::Future + Send; - fn a3( + fn a3( accessor: &wasmtime::component::Accessor, x: u16, ) -> impl ::core::future::Future + Send; - fn a4( + fn a4( accessor: &wasmtime::component::Accessor, x: i16, ) -> impl ::core::future::Future + Send; - fn a5( + fn a5( accessor: &wasmtime::component::Accessor, x: u32, ) -> impl ::core::future::Future + Send; - fn a6( + fn a6( accessor: &wasmtime::component::Accessor, x: i32, ) -> impl ::core::future::Future + Send; - fn a7( + fn a7( accessor: &wasmtime::component::Accessor, x: u64, ) -> impl ::core::future::Future + Send; - fn a8( + fn a8( accessor: &wasmtime::component::Accessor, x: i64, ) -> impl ::core::future::Future + Send; - fn a9( + fn a9( accessor: &wasmtime::component::Accessor, p1: u8, p2: i8, @@ -235,31 +235,31 @@ pub mod foo { p7: u64, p8: i64, ) -> impl ::core::future::Future + Send; - fn r1( + fn r1( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r2( + fn r2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r3( + fn r3( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r4( + fn r4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r5( + fn r5( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r6( + fn r6( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r7( + fn r7( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn r8( + fn r8( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn pair_ret( + fn pair_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/lists_concurrent.rs b/crates/component-macro/tests/expanded/lists_concurrent.rs index 13a868eba225..1739476f6bc1 100644 --- a/crates/component-macro/tests/expanded/lists_concurrent.rs +++ b/crates/component-macro/tests/expanded/lists_concurrent.rs @@ -370,116 +370,116 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn list_u8_param( + fn list_u8_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u16_param( + fn list_u16_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u32_param( + fn list_u32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u64_param( + fn list_u64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s8_param( + fn list_s8_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s16_param( + fn list_s16_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s32_param( + fn list_s32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_s64_param( + fn list_s64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_f32_param( + fn list_f32_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_f64_param( + fn list_f64_param( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn list_u8_ret( + fn list_u8_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u16_ret( + fn list_u16_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u32_ret( + fn list_u32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_u64_ret( + fn list_u64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s8_ret( + fn list_s8_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s16_ret( + fn list_s16_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s32_ret( + fn list_s32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_s64_ret( + fn list_s64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_f32_ret( + fn list_f32_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn list_f64_ret( + fn list_f64_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn tuple_list( + fn tuple_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec<(u8, i8)>, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec<(i64, u32)>, > + Send; - fn string_list_arg( + fn string_list_arg( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, ) -> impl ::core::future::Future + Send; - fn string_list_ret( + fn string_list_ret( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, >, > + Send; - fn tuple_string_list( + fn tuple_string_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< (u8, wasmtime::component::__internal::String), @@ -489,7 +489,7 @@ pub mod foo { (wasmtime::component::__internal::String, u8), >, > + Send; - fn string_list( + fn string_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::__internal::String, @@ -499,25 +499,25 @@ pub mod foo { wasmtime::component::__internal::String, >, > + Send; - fn record_list( + fn record_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn record_list_reverse( + fn record_list_reverse( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn variant_list( + fn variant_list( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn load_store_everything( + fn load_store_everything( accessor: &wasmtime::component::Accessor, a: LoadStoreAllSizes, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/many-arguments_concurrent.rs b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs index 32b4e7ab57e7..2eb2eab78860 100644 --- a/crates/component-macro/tests/expanded/many-arguments_concurrent.rs +++ b/crates/component-macro/tests/expanded/many-arguments_concurrent.rs @@ -273,7 +273,7 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn many_args( + fn many_args( accessor: &wasmtime::component::Accessor, a1: u64, a2: u64, @@ -292,7 +292,7 @@ pub mod foo { a15: u64, a16: u64, ) -> impl ::core::future::Future + Send; - fn big_argument( + fn big_argument( accessor: &wasmtime::component::Accessor, x: BigStruct, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/multiversion_concurrent.rs b/crates/component-macro/tests/expanded/multiversion_concurrent.rs index 0153166b6af9..e7451285c055 100644 --- a/crates/component-macro/tests/expanded/multiversion_concurrent.rs +++ b/crates/component-macro/tests/expanded/multiversion_concurrent.rs @@ -201,7 +201,7 @@ pub mod my { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn x( + fn x( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -237,7 +237,7 @@ pub mod my { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn x( + fn x( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/records_concurrent.rs b/crates/component-macro/tests/expanded/records_concurrent.rs index 2c78b2450054..dd97f8e22d48 100644 --- a/crates/component-macro/tests/expanded/records_concurrent.rs +++ b/crates/component-macro/tests/expanded/records_concurrent.rs @@ -347,42 +347,42 @@ pub mod foo { ); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn tuple_arg( + fn tuple_arg( accessor: &wasmtime::component::Accessor, x: (char, u32), ) -> impl ::core::future::Future + Send; - fn tuple_result( + fn tuple_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn empty_arg( + fn empty_arg( accessor: &wasmtime::component::Accessor, x: Empty, ) -> impl ::core::future::Future + Send; - fn empty_result( + fn empty_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn scalar_arg( + fn scalar_arg( accessor: &wasmtime::component::Accessor, x: Scalars, ) -> impl ::core::future::Future + Send; - fn scalar_result( + fn scalar_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn flags_arg( + fn flags_arg( accessor: &wasmtime::component::Accessor, x: ReallyFlags, ) -> impl ::core::future::Future + Send; - fn flags_result( + fn flags_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn aggregate_arg( + fn aggregate_arg( accessor: &wasmtime::component::Accessor, x: Aggregates, ) -> impl ::core::future::Future + Send; - fn aggregate_result( + fn aggregate_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn typedef_inout( + fn typedef_inout( accessor: &wasmtime::component::Accessor, e: TupleTypedef2, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/rename_concurrent.rs b/crates/component-macro/tests/expanded/rename_concurrent.rs index 5f036f6cddc9..45bea9853835 100644 --- a/crates/component-macro/tests/expanded/rename_concurrent.rs +++ b/crates/component-macro/tests/expanded/rename_concurrent.rs @@ -216,7 +216,7 @@ pub mod foo { assert!(4 == < Thing as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/resources-import_concurrent.rs b/crates/component-macro/tests/expanded/resources-import_concurrent.rs index ea6347bc068d..8b77ffc65b87 100644 --- a/crates/component-macro/tests/expanded/resources-import_concurrent.rs +++ b/crates/component-macro/tests/expanded/resources-import_concurrent.rs @@ -6,16 +6,16 @@ pub trait HostWorldResourceWithStore: wasmtime::component::HasData + Send { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn static_foo( + fn static_foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -128,7 +128,7 @@ pub struct TheWorld { some_world_func2: wasmtime::component::Func, } pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostWorldResourceWithStore + Send { - fn some_world_func( + fn some_world_func( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, @@ -391,15 +391,15 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn static_a( + fn static_a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn method_a( + fn method_a( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -469,7 +469,7 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn new( + fn new( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result< @@ -481,89 +481,89 @@ pub mod foo { pub trait HostFallible: Send {} impl<_T: HostFallible + ?Sized + Send> HostFallible for &mut _T {} pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + HostFallibleWithStore + Send { - fn bar_own_arg( + fn bar_own_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn bar_borrow_arg( + fn bar_borrow_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; - fn bar_result( + fn bar_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, > + Send; - fn tuple_own_arg( + fn tuple_own_arg( accessor: &wasmtime::component::Accessor, x: (wasmtime::component::Resource, u32), ) -> impl ::core::future::Future + Send; - fn tuple_borrow_arg( + fn tuple_borrow_arg( accessor: &wasmtime::component::Accessor, x: (wasmtime::component::Resource, u32), ) -> impl ::core::future::Future + Send; - fn tuple_result( + fn tuple_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = (wasmtime::component::Resource, u32), > + Send; - fn option_own_arg( + fn option_own_arg( accessor: &wasmtime::component::Accessor, x: Option>, ) -> impl ::core::future::Future + Send; - fn option_borrow_arg( + fn option_borrow_arg( accessor: &wasmtime::component::Accessor, x: Option>, ) -> impl ::core::future::Future + Send; - fn option_result( + fn option_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Option>, > + Send; - fn result_own_arg( + fn result_own_arg( accessor: &wasmtime::component::Accessor, x: Result, ()>, ) -> impl ::core::future::Future + Send; - fn result_borrow_arg( + fn result_borrow_arg( accessor: &wasmtime::component::Accessor, x: Result, ()>, ) -> impl ::core::future::Future + Send; - fn result_result( + fn result_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, ()>, > + Send; - fn list_own_arg( + fn list_own_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, ) -> impl ::core::future::Future + Send; - fn list_borrow_arg( + fn list_borrow_arg( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, ) -> impl ::core::future::Future + Send; - fn list_result( + fn list_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec< wasmtime::component::Resource, >, > + Send; - fn record_own_arg( + fn record_own_arg( accessor: &wasmtime::component::Accessor, x: NestedOwn, ) -> impl ::core::future::Future + Send; - fn record_borrow_arg( + fn record_borrow_arg( accessor: &wasmtime::component::Accessor, x: NestedBorrow, ) -> impl ::core::future::Future + Send; - fn record_result( + fn record_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn func_with_handle_typedef( + fn func_with_handle_typedef( accessor: &wasmtime::component::Accessor, x: SomeHandle, ) -> impl ::core::future::Future + Send; @@ -1014,7 +1014,7 @@ pub mod foo { use wasmtime::component::__internal::Box; pub type A = super::super::super::foo::foo::long_use_chain3::A; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::Resource, diff --git a/crates/component-macro/tests/expanded/share-types_concurrent.rs b/crates/component-macro/tests/expanded/share-types_concurrent.rs index 8d2d4e406bbc..4966d78fb646 100644 --- a/crates/component-macro/tests/expanded/share-types_concurrent.rs +++ b/crates/component-macro/tests/expanded/share-types_concurrent.rs @@ -265,7 +265,7 @@ pub mod http_fetch { assert!(4 == < Response as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn fetch_request( + fn fetch_request( accessor: &wasmtime::component::Accessor, request: Request, ) -> impl ::core::future::Future + Send; diff --git a/crates/component-macro/tests/expanded/simple-functions_concurrent.rs b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs index bab73ac4a359..f7b043e72162 100644 --- a/crates/component-macro/tests/expanded/simple-functions_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-functions_concurrent.rs @@ -192,25 +192,25 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn f1( + fn f1( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f2( + fn f2( accessor: &wasmtime::component::Accessor, a: u32, ) -> impl ::core::future::Future + Send; - fn f3( + fn f3( accessor: &wasmtime::component::Accessor, a: u32, b: u32, ) -> impl ::core::future::Future + Send; - fn f4( + fn f4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f5( + fn f5( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn f6( + fn f6( accessor: &wasmtime::component::Accessor, a: u32, b: u32, diff --git a/crates/component-macro/tests/expanded/simple-lists_concurrent.rs b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs index 8eaf44b90ce6..8e0c428b1dba 100644 --- a/crates/component-macro/tests/expanded/simple-lists_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-lists_concurrent.rs @@ -192,16 +192,16 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn simple_list1( + fn simple_list1( accessor: &wasmtime::component::Accessor, l: wasmtime::component::__internal::Vec, ) -> impl ::core::future::Future + Send; - fn simple_list2( + fn simple_list2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::Vec, > + Send; - fn simple_list3( + fn simple_list3( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::Vec, b: wasmtime::component::__internal::Vec, @@ -211,7 +211,7 @@ pub mod foo { wasmtime::component::__internal::Vec, ), > + Send; - fn simple_list4( + fn simple_list4( accessor: &wasmtime::component::Accessor, l: wasmtime::component::__internal::Vec< wasmtime::component::__internal::Vec, diff --git a/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs index 94cd4b0c7a28..629d6b81eb2d 100644 --- a/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs +++ b/crates/component-macro/tests/expanded/simple-wasi_concurrent.rs @@ -246,10 +246,10 @@ pub mod foo { assert!(1 == < Errno as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn create_directory_at( + fn create_directory_at( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn stat( + fn stat( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, diff --git a/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs index c33b98a1f5cc..10033c54a968 100644 --- a/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs +++ b/crates/component-macro/tests/expanded/small-anonymous_concurrent.rs @@ -235,7 +235,7 @@ pub mod foo { assert!(1 == < Error as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn option_test( + fn option_test( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result< diff --git a/crates/component-macro/tests/expanded/smoke_concurrent.rs b/crates/component-macro/tests/expanded/smoke_concurrent.rs index db37d59b587a..2754c31736a4 100644 --- a/crates/component-macro/tests/expanded/smoke_concurrent.rs +++ b/crates/component-macro/tests/expanded/smoke_concurrent.rs @@ -179,7 +179,7 @@ pub mod imports { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn y( + fn y( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/strings_concurrent.rs b/crates/component-macro/tests/expanded/strings_concurrent.rs index 40ece95cc2c8..190835af96c7 100644 --- a/crates/component-macro/tests/expanded/strings_concurrent.rs +++ b/crates/component-macro/tests/expanded/strings_concurrent.rs @@ -192,16 +192,16 @@ pub mod foo { #[allow(unused_imports)] use wasmtime::component::__internal::Box; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, x: wasmtime::component::__internal::String, ) -> impl ::core::future::Future + Send; - fn b( + fn b( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = wasmtime::component::__internal::String, > + Send; - fn c( + fn c( accessor: &wasmtime::component::Accessor, a: wasmtime::component::__internal::String, b: wasmtime::component::__internal::String, diff --git a/crates/component-macro/tests/expanded/unstable-features_concurrent.rs b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs index 10fa5d11c89a..14157466b2a9 100644 --- a/crates/component-macro/tests/expanded/unstable-features_concurrent.rs +++ b/crates/component-macro/tests/expanded/unstable-features_concurrent.rs @@ -86,7 +86,7 @@ pub trait HostBazWithStore: wasmtime::component::HasData + Send { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -194,7 +194,7 @@ pub struct TheWorldIndices {} /// [`Linker`]: wasmtime::component::Linker pub struct TheWorld {} pub trait TheWorldImportsWithStore: wasmtime::component::HasData + HostBazWithStore + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -399,7 +399,7 @@ pub mod foo { ) -> impl ::core::future::Future> + Send where Self: Sized; - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, self_: wasmtime::component::Resource, ) -> impl ::core::future::Future + Send; @@ -407,7 +407,7 @@ pub mod foo { pub trait HostBar: Send {} impl<_T: HostBar + ?Sized + Send> HostBar for &mut _T {} pub trait HostWithStore: wasmtime::component::HasData + HostBarWithStore + Send { - fn foo( + fn foo( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs index 1ec481afba6b..c658c7b0dd81 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo_concurrent.rs @@ -209,7 +209,7 @@ pub mod foo { assert!(4 == < Error as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn g( + fn g( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; } diff --git a/crates/component-macro/tests/expanded/use-paths_concurrent.rs b/crates/component-macro/tests/expanded/use-paths_concurrent.rs index a275a676c154..0cc1d8b81346 100644 --- a/crates/component-macro/tests/expanded/use-paths_concurrent.rs +++ b/crates/component-macro/tests/expanded/use-paths_concurrent.rs @@ -203,7 +203,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -242,7 +242,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -281,7 +281,7 @@ pub mod foo { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn a( + fn a( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } @@ -322,7 +322,7 @@ pub mod d { assert!(1 == < Foo as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn b( + fn b( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } diff --git a/crates/component-macro/tests/expanded/variants_concurrent.rs b/crates/component-macro/tests/expanded/variants_concurrent.rs index 25e0b0d62346..10c7ca604cf2 100644 --- a/crates/component-macro/tests/expanded/variants_concurrent.rs +++ b/crates/component-macro/tests/expanded/variants_concurrent.rs @@ -464,28 +464,28 @@ pub mod foo { assert!(4 == < IsClone as wasmtime::component::ComponentType >::ALIGN32); }; pub trait HostWithStore: wasmtime::component::HasData + Send { - fn e1_arg( + fn e1_arg( accessor: &wasmtime::component::Accessor, x: E1, ) -> impl ::core::future::Future + Send; - fn e1_result( + fn e1_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn v1_arg( + fn v1_arg( accessor: &wasmtime::component::Accessor, x: V1, ) -> impl ::core::future::Future + Send; - fn v1_result( + fn v1_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn bool_arg( + fn bool_arg( accessor: &wasmtime::component::Accessor, x: bool, ) -> impl ::core::future::Future + Send; - fn bool_result( + fn bool_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; - fn option_arg( + fn option_arg( accessor: &wasmtime::component::Accessor, a: Option, b: Option<()>, @@ -494,7 +494,7 @@ pub mod foo { e: Option, g: Option>, ) -> impl ::core::future::Future + Send; - fn option_result( + fn option_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = ( @@ -506,7 +506,7 @@ pub mod foo { Option>, ), > + Send; - fn casts( + fn casts( accessor: &wasmtime::component::Accessor, a: Casts1, b: Casts2, @@ -517,7 +517,7 @@ pub mod foo { ) -> impl ::core::future::Future< Output = (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6), > + Send; - fn result_arg( + fn result_arg( accessor: &wasmtime::component::Accessor, a: Result<(), ()>, b: Result<(), E1>, @@ -529,7 +529,7 @@ pub mod foo { wasmtime::component::__internal::Vec, >, ) -> impl ::core::future::Future + Send; - fn result_result( + fn result_result( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = ( @@ -544,36 +544,36 @@ pub mod foo { >, ), > + Send; - fn return_result_sugar( + fn return_result_sugar( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_result_sugar2( + fn return_result_sugar2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_result_sugar3( + fn return_result_sugar3( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result, > + Send; - fn return_result_sugar4( + fn return_result_sugar4( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future< Output = Result<(i32, u32), MyErrno>, > + Send; - fn return_option_sugar( + fn return_option_sugar( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn return_option_sugar2( + fn return_option_sugar2( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn result_simple( + fn result_simple( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future> + Send; - fn is_clone_arg( + fn is_clone_arg( accessor: &wasmtime::component::Accessor, a: IsClone, ) -> impl ::core::future::Future + Send; - fn is_clone_return( + fn is_clone_return( accessor: &wasmtime::component::Accessor, ) -> impl ::core::future::Future + Send; } From e6fab83143356ad7eda2b7915f8bc9ef7ef77516 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Jan 2026 12:21:22 -0700 Subject: [PATCH 3/5] bless disas tests --- .../direct-adapter-calls-inlining.wat | 85 +++++++------------ .../direct-adapter-calls-x64.wat | 76 +++++++---------- .../component-model/direct-adapter-calls.wat | 77 ++++++----------- tests/disas/gc/drc/array-fill.wat | 6 +- tests/disas/gc/drc/array-get-s.wat | 4 +- tests/disas/gc/drc/array-get-u.wat | 4 +- tests/disas/gc/drc/array-get.wat | 4 +- tests/disas/gc/drc/array-len.wat | 2 +- tests/disas/gc/drc/array-new.wat | 4 +- tests/disas/gc/drc/array-set.wat | 4 +- tests/disas/gc/drc/funcref-in-gc-heap-get.wat | 2 +- tests/disas/gc/drc/funcref-in-gc-heap-set.wat | 2 +- tests/disas/gc/drc/multiple-array-get.wat | 6 +- tests/disas/gc/drc/multiple-struct-get.wat | 2 +- tests/disas/gc/drc/ref-cast.wat | 2 +- tests/disas/gc/drc/struct-get.wat | 8 +- tests/disas/gc/drc/struct-set.wat | 6 +- tests/disas/gc/null/array-fill.wat | 6 +- tests/disas/gc/null/array-get-s.wat | 4 +- tests/disas/gc/null/array-get-u.wat | 4 +- tests/disas/gc/null/array-get.wat | 4 +- tests/disas/gc/null/array-len.wat | 2 +- .../gc/null/array-new-fixed-of-gc-refs.wat | 4 +- tests/disas/gc/null/array-new-fixed.wat | 4 +- tests/disas/gc/null/array-new.wat | 10 +-- tests/disas/gc/null/array-set.wat | 4 +- .../disas/gc/null/funcref-in-gc-heap-get.wat | 2 +- .../disas/gc/null/funcref-in-gc-heap-new.wat | 4 +- .../disas/gc/null/funcref-in-gc-heap-set.wat | 2 +- tests/disas/gc/null/multiple-array-get.wat | 6 +- tests/disas/gc/null/multiple-struct-get.wat | 2 +- tests/disas/gc/null/ref-cast.wat | 2 +- tests/disas/gc/null/struct-get.wat | 8 +- tests/disas/gc/null/struct-new-default.wat | 4 +- tests/disas/gc/null/struct-new.wat | 4 +- tests/disas/gc/null/struct-set.wat | 6 +- tests/disas/gc/null/v128-fields.wat | 2 +- .../resume-suspend-data-passing.wat | 8 +- .../disas/stack-switching/resume-suspend.wat | 8 +- .../stack-switching/symmetric-switch.wat | 14 +-- tests/disas/typed-funcrefs-eager-init.wat | 8 +- tests/disas/typed-funcrefs.wat | 8 +- 42 files changed, 182 insertions(+), 242 deletions(-) diff --git a/tests/disas/component-model/direct-adapter-calls-inlining.wat b/tests/disas/component-model/direct-adapter-calls-inlining.wat index 6c8f4fb6d8ba..5ebe6f42abce 100644 --- a/tests/disas/component-model/direct-adapter-calls-inlining.wat +++ b/tests/disas/component-model/direct-adapter-calls-inlining.wat @@ -64,8 +64,8 @@ ;; gv6 = load.i64 notrap aligned gv5+16 ;; gv7 = vmctx ;; gv8 = load.i64 notrap aligned readonly can_move gv7+120 -;; gv9 = load.i64 notrap aligned readonly can_move gv7+96 -;; gv10 = load.i64 notrap aligned readonly can_move gv7+144 +;; gv9 = load.i64 notrap aligned readonly can_move gv7+144 +;; gv10 = load.i64 notrap aligned readonly can_move gv7+96 ;; gv11 = vmctx ;; gv12 = load.i64 notrap aligned readonly gv11+8 ;; gv13 = load.i64 notrap aligned gv12+16 @@ -91,74 +91,51 @@ ;; brif v18, block4, block5 ;; ;; block4: -;; v92 = load.i64 notrap aligned readonly can_move v5+72 -;; v93 = load.i64 notrap aligned readonly can_move v5+88 -;; v19 = iconst.i32 24 -;; call_indirect sig1, v92(v93, v5, v19) ; v19 = 24 +;; v21 = load.i64 notrap aligned readonly can_move v5+72 +;; v20 = load.i64 notrap aligned readonly can_move v5+88 +;; v19 = iconst.i32 23 +;; call_indirect sig1, v21(v20, v5, v19) ; v19 = 23 ;; trap user11 ;; ;; block5: -;; v22 = load.i64 notrap aligned readonly can_move v5+96 +;; v22 = load.i64 notrap aligned readonly can_move v5+144 ;; v23 = load.i32 notrap aligned table v22 -;; v24 = iconst.i32 2 -;; v25 = band v23, v24 ; v24 = 2 -;; v81 = iconst.i32 0 -;; v82 = icmp eq v25, v81 ; v81 = 0 -;; v28 = uextend.i32 v82 -;; brif v28, block6, block7 +;; v61 = iconst.i32 0 +;; store notrap aligned table v61, v22 ; v61 = 0 +;; v26 = load.i64 notrap aligned readonly can_move v5+96 +;; v27 = load.i32 notrap aligned table v26 +;; v28 = iconst.i32 -2 +;; v29 = band v27, v28 ; v28 = -2 +;; store notrap aligned table v29, v26 +;; v62 = iconst.i32 1 +;; v63 = bor v27, v62 ; v62 = 1 +;; store notrap aligned table v63, v26 +;; jump block6 ;; ;; block6: -;; v21 = load.i64 notrap aligned readonly can_move v5+72 -;; v20 = load.i64 notrap aligned readonly can_move v5+88 -;; v29 = iconst.i32 18 -;; call_indirect sig1, v21(v20, v5, v29) ; v29 = 18 -;; trap user11 +;; jump block7 ;; ;; block7: -;; v34 = iconst.i32 -3 -;; v35 = band.i32 v23, v34 ; v34 = -3 -;; store notrap aligned table v35, v22 -;; v37 = load.i64 notrap aligned readonly can_move v5+144 -;; v38 = load.i32 notrap aligned table v37 -;; v83 = iconst.i32 0 -;; store notrap aligned table v83, v37 ; v83 = 0 -;; v42 = load.i32 notrap aligned table v22 -;; v43 = iconst.i32 -2 -;; v44 = band v42, v43 ; v43 = -2 -;; store notrap aligned table v44, v22 -;; v84 = iconst.i32 1 -;; v85 = bor v42, v84 ; v84 = 1 -;; store notrap aligned table v85, v22 ;; jump block8 ;; ;; block8: -;; jump block9 -;; -;; block9: -;; jump block10 -;; -;; block10: -;; v55 = load.i32 notrap aligned table v12 -;; v86 = iconst.i32 -2 -;; v87 = band v55, v86 ; v86 = -2 -;; store notrap aligned table v87, v12 -;; v88 = iconst.i32 1 -;; v89 = bor v55, v88 ; v88 = 1 -;; store notrap aligned table v89, v12 -;; v65 = load.i32 notrap aligned table v22 -;; v90 = iconst.i32 2 -;; v91 = bor v65, v90 ; v90 = 2 -;; store notrap aligned table v91, v22 -;; store.i32 notrap aligned table v38, v37 +;; v40 = load.i32 notrap aligned table v12 +;; v64 = iconst.i32 -2 +;; v65 = band v40, v64 ; v64 = -2 +;; store notrap aligned table v65, v12 +;; v66 = iconst.i32 1 +;; v67 = bor v40, v66 ; v66 = 1 +;; store notrap aligned table v67, v12 +;; store.i32 notrap aligned table v23, v22 ;; jump block3 ;; ;; block3: -;; jump block11 +;; jump block9 ;; -;; block11: +;; block9: ;; @00f0 jump block1 ;; ;; block1: -;; v72 = iconst.i32 1276 -;; @00f0 return v72 ; v72 = 1276 +;; v52 = iconst.i32 1276 +;; @00f0 return v52 ; v52 = 1276 ;; } diff --git a/tests/disas/component-model/direct-adapter-calls-x64.wat b/tests/disas/component-model/direct-adapter-calls-x64.wat index e1ef652561c1..d6d1684ba1eb 100644 --- a/tests/disas/component-model/direct-adapter-calls-x64.wat +++ b/tests/disas/component-model/direct-adapter-calls-x64.wat @@ -87,61 +87,47 @@ ;; movq 0x10(%r10), %r10 ;; addq $0x30, %r10 ;; cmpq %rsp, %r10 -;; ja 0x14e +;; ja 0x113 ;; 79: subq $0x20, %rsp ;; movq %rbx, (%rsp) ;; movq %r12, 8(%rsp) ;; movq %r14, 0x10(%rsp) -;; movq %r15, 0x18(%rsp) -;; movq 0x78(%rdi), %r12 -;; movl (%r12), %r8d -;; testl $1, %r8d -;; je 0x13a -;; a5: movq 0x60(%rdi), %rbx -;; movl (%rbx), %r9d -;; testl $2, %r9d -;; je 0x126 -;; b9: andl $0xfffffffd, %r9d -;; movl %r9d, (%rbx) -;; movq 0x90(%rdi), %r14 -;; movq %rdi, %r10 -;; movl (%r14), %r15d -;; movl $0, (%r14) -;; movl (%rbx), %esi -;; movq %rsi, %rax -;; andl $0xfffffffe, %eax -;; movl %eax, (%rbx) -;; orl $1, %esi -;; movl %esi, (%rbx) -;; movq 0x40(%r10), %rdi -;; movq %r10, %rsi +;; movq 0x78(%rdi), %r14 +;; movl (%r14), %esi +;; testl $1, %esi +;; je 0xff +;; 9e: movq 0x90(%rdi), %rbx +;; movl (%rbx), %r12d +;; movl $0, (%rbx) +;; movq 0x60(%rdi), %rcx +;; movq %rdi, %r9 +;; movl (%rcx), %eax +;; movq %rax, %r8 +;; andl $0xfffffffe, %r8d +;; movl %r8d, (%rcx) +;; orl $1, %eax +;; movl %eax, (%rcx) +;; movq 0x40(%r9), %rdi +;; movq %r9, %rsi ;; callq 0 -;; movl (%r12), %ecx -;; movq %rcx, %rdx -;; andl $0xfffffffe, %edx -;; movl %edx, (%r12) +;; movl (%r14), %ecx +;; movq %rcx, %r8 +;; andl $0xfffffffe, %r8d +;; movl %r8d, (%r14) ;; orl $1, %ecx -;; movl %ecx, (%r12) -;; orl $2, (%rbx) -;; movl %r15d, (%r14) +;; movl %ecx, (%r14) +;; movl %r12d, (%rbx) ;; movq (%rsp), %rbx ;; movq 8(%rsp), %r12 ;; movq 0x10(%rsp), %r14 -;; movq 0x18(%rsp), %r15 ;; addq $0x20, %rsp ;; movq %rbp, %rsp ;; popq %rbp ;; retq -;; 126: movq %rdi, %rsi -;; 129: movq 0x48(%rsi), %rax -;; 12d: movq 0x58(%rsi), %rdi -;; 131: movl $0x12, %edx -;; 136: callq *%rax -;; 138: ud2 -;; 13a: movq %rdi, %rsi -;; 13d: movq 0x48(%rsi), %rcx -;; 141: movq 0x58(%rsi), %rdi -;; 145: movl $0x18, %edx -;; 14a: callq *%rcx -;; 14c: ud2 -;; 14e: ud2 +;; ff: movq %rdi, %rsi +;; 102: movq 0x48(%rsi), %rax +;; 106: movq 0x58(%rsi), %rdi +;; 10a: movl $0x17, %edx +;; 10f: callq *%rax +;; 111: ud2 +;; 113: ud2 diff --git a/tests/disas/component-model/direct-adapter-calls.wat b/tests/disas/component-model/direct-adapter-calls.wat index ef9478ab57eb..26d94affea67 100644 --- a/tests/disas/component-model/direct-adapter-calls.wat +++ b/tests/disas/component-model/direct-adapter-calls.wat @@ -97,8 +97,8 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly can_move gv3+120 -;; gv5 = load.i64 notrap aligned readonly can_move gv3+96 -;; gv6 = load.i64 notrap aligned readonly can_move gv3+144 +;; gv5 = load.i64 notrap aligned readonly can_move gv3+144 +;; gv6 = load.i64 notrap aligned readonly can_move gv3+96 ;; sig0 = (i64 vmctx, i64, i32) tail ;; sig1 = (i64 vmctx, i64, i32) -> i32 tail ;; fn0 = colocated u0:0 sig1 @@ -115,58 +115,35 @@ ;; @0098 brif v10, block2, block3 ;; ;; block2: -;; v94 = load.i64 notrap aligned readonly can_move v0+72 -;; v95 = load.i64 notrap aligned readonly can_move v0+88 -;; @009a v11 = iconst.i32 24 -;; @009c call_indirect sig0, v94(v95, v0, v11) ; v11 = 24 +;; @009c v14 = load.i64 notrap aligned readonly can_move v0+72 +;; @009c v13 = load.i64 notrap aligned readonly can_move v0+88 +;; @009a v11 = iconst.i32 23 +;; @009c call_indirect sig0, v14(v13, v0, v11) ; v11 = 23 ;; @009e trap user11 ;; ;; block3: -;; @00a0 v15 = load.i64 notrap aligned readonly can_move v0+96 +;; @00a0 v15 = load.i64 notrap aligned readonly can_move v0+144 ;; @00a0 v16 = load.i32 notrap aligned table v15 -;; @00a2 v17 = iconst.i32 2 -;; @00a4 v18 = band v16, v17 ; v17 = 2 -;; v86 = iconst.i32 0 -;; v87 = icmp eq v18, v86 ; v86 = 0 -;; @00a5 v20 = uextend.i32 v87 -;; @00a6 brif v20, block4, block5 -;; -;; block4: -;; @009c v14 = load.i64 notrap aligned readonly can_move v0+72 -;; @009c v13 = load.i64 notrap aligned readonly can_move v0+88 -;; @00a8 v21 = iconst.i32 18 -;; @00aa call_indirect sig0, v14(v13, v0, v21) ; v21 = 18 -;; @00ac trap user11 -;; -;; block5: -;; @00b0 v27 = iconst.i32 -3 -;; @00b2 v28 = band.i32 v16, v27 ; v27 = -3 -;; @00b3 store notrap aligned table v28, v15 -;; @00b5 v30 = load.i64 notrap aligned readonly can_move v0+144 -;; @00b5 v31 = load.i32 notrap aligned table v30 -;; v88 = iconst.i32 0 -;; @00bb store notrap aligned table v88, v30 ; v88 = 0 -;; @00bd v35 = load.i32 notrap aligned table v15 -;; @00bf v36 = iconst.i32 -2 -;; @00c1 v37 = band v35, v36 ; v36 = -2 -;; @00c2 store notrap aligned table v37, v15 -;; v89 = iconst.i32 1 -;; v90 = bor v35, v89 ; v89 = 1 -;; @00cb store notrap aligned table v90, v15 -;; @00cd v45 = load.i64 notrap aligned readonly can_move v0+64 -;; @00cd v46 = call fn0(v45, v0, v2) -;; @00d1 v48 = load.i32 notrap aligned table v5 -;; @00d5 v50 = band v48, v36 ; v36 = -2 -;; @00d6 store notrap aligned table v50, v5 -;; v91 = bor v48, v89 ; v89 = 1 -;; @00df store notrap aligned table v91, v5 -;; @00e1 v58 = load.i32 notrap aligned table v15 -;; v92 = iconst.i32 2 -;; v93 = bor v58, v92 ; v92 = 2 -;; @00e6 store notrap aligned table v93, v15 -;; @00ea store notrap aligned table v31, v30 -;; @00ec jump block1 +;; v60 = iconst.i32 0 +;; @00a6 store notrap aligned table v60, v15 ; v60 = 0 +;; @00a8 v19 = load.i64 notrap aligned readonly can_move v0+96 +;; @00a8 v20 = load.i32 notrap aligned table v19 +;; @00aa v21 = iconst.i32 -2 +;; @00ac v22 = band v20, v21 ; v21 = -2 +;; @00ad store notrap aligned table v22, v19 +;; v61 = iconst.i32 1 +;; v62 = bor v20, v61 ; v61 = 1 +;; @00b6 store notrap aligned table v62, v19 +;; @00b8 v30 = load.i64 notrap aligned readonly can_move v0+64 +;; @00b8 v31 = call fn0(v30, v0, v2) +;; @00bc v33 = load.i32 notrap aligned table v5 +;; @00c0 v35 = band v33, v21 ; v21 = -2 +;; @00c1 store notrap aligned table v35, v5 +;; v63 = bor v33, v61 ; v61 = 1 +;; @00ca store notrap aligned table v63, v5 +;; @00ce store notrap aligned table v16, v15 +;; @00d0 jump block1 ;; ;; block1: -;; @00ec return v46 +;; @00d0 return v31 ;; } diff --git a/tests/disas/gc/drc/array-fill.wat b/tests/disas/gc/drc/array-fill.wat index c29a4de19477..f11bbf32353c 100644 --- a/tests/disas/gc/drc/array-fill.wat +++ b/tests/disas/gc/drc/array-fill.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64, v5: i32): -;; @0027 trapz v2, user16 +;; @0027 trapz v2, user15 ;; @0027 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0027 v7 = load.i64 notrap aligned readonly can_move v41+24 ;; @0027 v6 = uextend.i64 v2 @@ -28,9 +28,9 @@ ;; @0027 v9 = iconst.i64 24 ;; @0027 v10 = iadd v8, v9 ; v9 = 24 ;; @0027 v11 = load.i32 notrap aligned readonly v10 -;; @0027 v12 = uadd_overflow_trap v3, v5, user17 +;; @0027 v12 = uadd_overflow_trap v3, v5, user16 ;; @0027 v13 = icmp ugt v12, v11 -;; @0027 trapnz v13, user17 +;; @0027 trapnz v13, user16 ;; @0027 v15 = uextend.i64 v11 ;; v43 = iconst.i64 3 ;; v44 = ishl v15, v43 ; v43 = 3 diff --git a/tests/disas/gc/drc/array-get-s.wat b/tests/disas/gc/drc/array-get-s.wat index 65a77207b1a2..518306068922 100644 --- a/tests/disas/gc/drc/array-get-s.wat +++ b/tests/disas/gc/drc/array-get-s.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/drc/array-get-u.wat b/tests/disas/gc/drc/array-get-u.wat index 6d8a36878e65..8c9ce0a97985 100644 --- a/tests/disas/gc/drc/array-get-u.wat +++ b/tests/disas/gc/drc/array-get-u.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/drc/array-get.wat b/tests/disas/gc/drc/array-get.wat index 306faaf2af32..8aaf3770c34f 100644 --- a/tests/disas/gc/drc/array-get.wat +++ b/tests/disas/gc/drc/array-get.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v33 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v33+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 24 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v35 = iconst.i64 3 ;; v36 = ishl v13, v35 ; v35 = 3 diff --git a/tests/disas/gc/drc/array-len.wat b/tests/disas/gc/drc/array-len.wat index 58f535721345..444db28ad6a1 100644 --- a/tests/disas/gc/drc/array-len.wat +++ b/tests/disas/gc/drc/array-len.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @001f trapz v2, user16 +;; @001f trapz v2, user15 ;; @001f v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @001f v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @001f v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/array-new.wat b/tests/disas/gc/drc/array-new.wat index f2edee849f50..fd30585c07c4 100644 --- a/tests/disas/gc/drc/array-new.wat +++ b/tests/disas/gc/drc/array-new.wat @@ -26,11 +26,11 @@ ;; v36 = ishl v6, v35 ; v35 = 3 ;; v33 = iconst.i64 32 ;; @0022 v8 = ushr v36, v33 ; v33 = 32 -;; @0022 trapnz v8, user18 +;; @0022 trapnz v8, user17 ;; @0022 v5 = iconst.i32 32 ;; v42 = iconst.i32 3 ;; v43 = ishl v3, v42 ; v42 = 3 -;; @0022 v10 = uadd_overflow_trap v5, v43, user18 ; v5 = 32 +;; @0022 v10 = uadd_overflow_trap v5, v43, user17 ; v5 = 32 ;; @0022 v12 = iconst.i32 -1476395008 ;; @0022 v13 = iconst.i32 0 ;; v40 = iconst.i32 8 diff --git a/tests/disas/gc/drc/array-set.wat b/tests/disas/gc/drc/array-set.wat index b053ebb23bc4..c88b12650218 100644 --- a/tests/disas/gc/drc/array-set.wat +++ b/tests/disas/gc/drc/array-set.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v32 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v6 = load.i64 notrap aligned readonly can_move v32+24 ;; @0024 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0024 v9 = iadd v7, v8 ; v8 = 24 ;; @0024 v10 = load.i32 notrap aligned readonly v9 ;; @0024 v11 = icmp ult v3, v10 -;; @0024 trapz v11, user17 +;; @0024 trapz v11, user16 ;; @0024 v13 = uextend.i64 v10 ;; v34 = iconst.i64 3 ;; v35 = ishl v13, v34 ; v34 = 3 diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat index a0752b7806e9..d0dd4fe7e989 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0020 trapz v2, user16 +;; @0020 trapz v2, user15 ;; @0020 v13 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v5 = load.i64 notrap aligned readonly can_move v13+24 ;; @0020 v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat index 2cd534a9a214..7f82110b0ba1 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v10 = call fn0(v0, v3) ;; @0022 v11 = ireduce.i32 v10 ;; @0022 v12 = load.i64 notrap aligned readonly can_move v0+8 diff --git a/tests/disas/gc/drc/multiple-array-get.wat b/tests/disas/gc/drc/multiple-array-get.wat index 04159cf15663..4b4cabdf1c05 100644 --- a/tests/disas/gc/drc/multiple-array-get.wat +++ b/tests/disas/gc/drc/multiple-array-get.wat @@ -21,7 +21,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v65 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v8 = load.i64 notrap aligned readonly can_move v65+24 ;; @0024 v7 = uextend.i64 v2 @@ -30,7 +30,7 @@ ;; @0024 v11 = iadd v9, v10 ; v10 = 24 ;; @0024 v12 = load.i32 notrap aligned readonly v11 ;; @0024 v13 = icmp ult v3, v12 -;; @0024 trapz v13, user17 +;; @0024 trapz v13, user16 ;; @0024 v15 = uextend.i64 v12 ;; v67 = iconst.i64 3 ;; v68 = ishl v15, v67 ; v67 = 3 @@ -51,7 +51,7 @@ ;; @0024 v30 = isub v27, v29 ;; @0024 v31 = load.i64 notrap aligned little v30 ;; @002b v38 = icmp ult v4, v12 -;; @002b trapz v38, user17 +;; @002b trapz v38, user16 ;; v86 = ishl v4, v77 ; v77 = 3 ;; @002b v48 = iadd v86, v19 ; v19 = 32 ;; @002b v53 = isub v20, v48 diff --git a/tests/disas/gc/drc/multiple-struct-get.wat b/tests/disas/gc/drc/multiple-struct-get.wat index 35ef796ac449..bc1f3bc782ee 100644 --- a/tests/disas/gc/drc/multiple-struct-get.wat +++ b/tests/disas/gc/drc/multiple-struct-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0023 trapz v2, user16 +;; @0023 trapz v2, user15 ;; @0023 v20 = load.i64 notrap aligned readonly can_move v0+8 ;; @0023 v6 = load.i64 notrap aligned readonly can_move v20+24 ;; @0023 v5 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/ref-cast.wat b/tests/disas/gc/drc/ref-cast.wat index 83fad1e6c005..4056ef24b30a 100644 --- a/tests/disas/gc/drc/ref-cast.wat +++ b/tests/disas/gc/drc/ref-cast.wat @@ -57,7 +57,7 @@ ;; @001e jump block4(v23) ;; ;; block4(v24: i32): -;; @001e trapz v24, user19 +;; @001e trapz v24, user18 ;; v25 = load.i32 notrap v36 ;; @0021 jump block1 ;; diff --git a/tests/disas/gc/drc/struct-get.wat b/tests/disas/gc/drc/struct-get.wat index c0221c3e1f6d..0c87b1bf42ab 100644 --- a/tests/disas/gc/drc/struct-get.wat +++ b/tests/disas/gc/drc/struct-get.wat @@ -34,7 +34,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0033 trapz v2, user16 +;; @0033 trapz v2, user15 ;; @0033 v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @0033 v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @0033 v4 = uextend.i64 v2 @@ -59,7 +59,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @003c trapz v2, user16 +;; @003c trapz v2, user15 ;; @003c v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @003c v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @003c v4 = uextend.i64 v2 @@ -85,7 +85,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0045 trapz v2, user16 +;; @0045 trapz v2, user15 ;; @0045 v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @0045 v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @0045 v4 = uextend.i64 v2 @@ -111,7 +111,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @004e trapz v2, user16 +;; @004e trapz v2, user15 ;; @004e v58 = load.i64 notrap aligned readonly can_move v0+8 ;; @004e v5 = load.i64 notrap aligned readonly can_move v58+24 ;; @004e v4 = uextend.i64 v2 diff --git a/tests/disas/gc/drc/struct-set.wat b/tests/disas/gc/drc/struct-set.wat index a762954a46c6..118899ecbc59 100644 --- a/tests/disas/gc/drc/struct-set.wat +++ b/tests/disas/gc/drc/struct-set.wat @@ -30,7 +30,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: f32): -;; @0034 trapz v2, user16 +;; @0034 trapz v2, user15 ;; @0034 v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @0034 v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @0034 v4 = uextend.i64 v2 @@ -55,7 +55,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @003f trapz v2, user16 +;; @003f trapz v2, user15 ;; @003f v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @003f v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @003f v4 = uextend.i64 v2 @@ -82,7 +82,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @004a trapz v2, user16 +;; @004a trapz v2, user15 ;; @004a v59 = load.i64 notrap aligned readonly can_move v0+8 ;; @004a v5 = load.i64 notrap aligned readonly can_move v59+24 ;; @004a v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/array-fill.wat b/tests/disas/gc/null/array-fill.wat index 2ddc505ea823..2dd07bec4326 100644 --- a/tests/disas/gc/null/array-fill.wat +++ b/tests/disas/gc/null/array-fill.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64, v5: i32): -;; @0027 trapz v2, user16 +;; @0027 trapz v2, user15 ;; @0027 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0027 v7 = load.i64 notrap aligned readonly can_move v41+24 ;; @0027 v6 = uextend.i64 v2 @@ -28,9 +28,9 @@ ;; @0027 v9 = iconst.i64 8 ;; @0027 v10 = iadd v8, v9 ; v9 = 8 ;; @0027 v11 = load.i32 notrap aligned readonly v10 -;; @0027 v12 = uadd_overflow_trap v3, v5, user17 +;; @0027 v12 = uadd_overflow_trap v3, v5, user16 ;; @0027 v13 = icmp ugt v12, v11 -;; @0027 trapnz v13, user17 +;; @0027 trapnz v13, user16 ;; @0027 v15 = uextend.i64 v11 ;; v43 = iconst.i64 3 ;; v44 = ishl v15, v43 ; v43 = 3 diff --git a/tests/disas/gc/null/array-get-s.wat b/tests/disas/gc/null/array-get-s.wat index d33eb7715b82..0a04f752e7e1 100644 --- a/tests/disas/gc/null/array-get-s.wat +++ b/tests/disas/gc/null/array-get-s.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/null/array-get-u.wat b/tests/disas/gc/null/array-get-u.wat index de64885a7dc1..8f2f564f7f82 100644 --- a/tests/disas/gc/null/array-get-u.wat +++ b/tests/disas/gc/null/array-get-u.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v34 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v34+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v33 = iconst.i64 32 ;; @0022 v15 = ushr v13, v33 ; v33 = 32 diff --git a/tests/disas/gc/null/array-get.wat b/tests/disas/gc/null/array-get.wat index f03c2b8d1cee..4037eb150dd9 100644 --- a/tests/disas/gc/null/array-get.wat +++ b/tests/disas/gc/null/array-get.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v33 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v6 = load.i64 notrap aligned readonly can_move v33+24 ;; @0022 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0022 v9 = iadd v7, v8 ; v8 = 8 ;; @0022 v10 = load.i32 notrap aligned readonly v9 ;; @0022 v11 = icmp ult v3, v10 -;; @0022 trapz v11, user17 +;; @0022 trapz v11, user16 ;; @0022 v13 = uextend.i64 v10 ;; v35 = iconst.i64 3 ;; v36 = ishl v13, v35 ; v35 = 3 diff --git a/tests/disas/gc/null/array-len.wat b/tests/disas/gc/null/array-len.wat index 31ac5e588bed..e551e1e92136 100644 --- a/tests/disas/gc/null/array-len.wat +++ b/tests/disas/gc/null/array-len.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @001f trapz v2, user16 +;; @001f trapz v2, user15 ;; @001f v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @001f v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @001f v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat index 59623535efad..57f8d27b2570 100644 --- a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat +++ b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat @@ -34,11 +34,11 @@ ;; @0025 v17 = load.i64 notrap aligned readonly v0+32 ;; @0025 v18 = load.i32 notrap aligned v17 ;; v82 = iconst.i32 7 -;; @0025 v21 = uadd_overflow_trap v18, v82, user18 ; v82 = 7 +;; @0025 v21 = uadd_overflow_trap v18, v82, user17 ; v82 = 7 ;; v89 = iconst.i32 -8 ;; @0025 v23 = band v21, v89 ; v89 = -8 ;; v74 = iconst.i32 24 -;; @0025 v24 = uadd_overflow_trap v23, v74, user18 ; v74 = 24 +;; @0025 v24 = uadd_overflow_trap v23, v74, user17 ; v74 = 24 ;; @0025 v56 = load.i64 notrap aligned readonly can_move v0+8 ;; @0025 v26 = load.i64 notrap aligned v56+32 ;; @0025 v25 = uextend.i64 v24 diff --git a/tests/disas/gc/null/array-new-fixed.wat b/tests/disas/gc/null/array-new-fixed.wat index 4c96c8c34f19..36422419ee1d 100644 --- a/tests/disas/gc/null/array-new-fixed.wat +++ b/tests/disas/gc/null/array-new-fixed.wat @@ -25,11 +25,11 @@ ;; @0025 v17 = load.i64 notrap aligned readonly v0+32 ;; @0025 v18 = load.i32 notrap aligned v17 ;; v73 = iconst.i32 7 -;; @0025 v21 = uadd_overflow_trap v18, v73, user18 ; v73 = 7 +;; @0025 v21 = uadd_overflow_trap v18, v73, user17 ; v73 = 7 ;; v80 = iconst.i32 -8 ;; @0025 v23 = band v21, v80 ; v80 = -8 ;; v65 = iconst.i32 40 -;; @0025 v24 = uadd_overflow_trap v23, v65, user18 ; v65 = 40 +;; @0025 v24 = uadd_overflow_trap v23, v65, user17 ; v65 = 40 ;; @0025 v50 = load.i64 notrap aligned readonly can_move v0+8 ;; @0025 v26 = load.i64 notrap aligned v50+32 ;; @0025 v25 = uextend.i64 v24 diff --git a/tests/disas/gc/null/array-new.wat b/tests/disas/gc/null/array-new.wat index d7d430bfe8aa..cd144cbb97a4 100644 --- a/tests/disas/gc/null/array-new.wat +++ b/tests/disas/gc/null/array-new.wat @@ -27,21 +27,21 @@ ;; v56 = ishl v6, v55 ; v55 = 3 ;; v53 = iconst.i64 32 ;; @0022 v8 = ushr v56, v53 ; v53 = 32 -;; @0022 trapnz v8, user18 +;; @0022 trapnz v8, user17 ;; @0022 v5 = iconst.i32 16 ;; v62 = iconst.i32 3 ;; v63 = ishl v3, v62 ; v62 = 3 -;; @0022 v10 = uadd_overflow_trap v5, v63, user18 ; v5 = 16 +;; @0022 v10 = uadd_overflow_trap v5, v63, user17 ; v5 = 16 ;; @0022 v12 = iconst.i32 -67108864 ;; @0022 v13 = band v10, v12 ; v12 = -67108864 -;; @0022 trapnz v13, user18 +;; @0022 trapnz v13, user17 ;; @0022 v15 = load.i64 notrap aligned readonly v0+32 ;; @0022 v16 = load.i32 notrap aligned v15 ;; v66 = iconst.i32 7 -;; @0022 v19 = uadd_overflow_trap v16, v66, user18 ; v66 = 7 +;; @0022 v19 = uadd_overflow_trap v16, v66, user17 ; v66 = 7 ;; v73 = iconst.i32 -8 ;; @0022 v21 = band v19, v73 ; v73 = -8 -;; @0022 v22 = uadd_overflow_trap v21, v10, user18 +;; @0022 v22 = uadd_overflow_trap v21, v10, user17 ;; @0022 v51 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v24 = load.i64 notrap aligned v51+32 ;; @0022 v23 = uextend.i64 v22 diff --git a/tests/disas/gc/null/array-set.wat b/tests/disas/gc/null/array-set.wat index 0c13a75c47a5..2f2540d42e54 100644 --- a/tests/disas/gc/null/array-set.wat +++ b/tests/disas/gc/null/array-set.wat @@ -20,7 +20,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i64): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v32 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v6 = load.i64 notrap aligned readonly can_move v32+24 ;; @0024 v5 = uextend.i64 v2 @@ -29,7 +29,7 @@ ;; @0024 v9 = iadd v7, v8 ; v8 = 8 ;; @0024 v10 = load.i32 notrap aligned readonly v9 ;; @0024 v11 = icmp ult v3, v10 -;; @0024 trapz v11, user17 +;; @0024 trapz v11, user16 ;; @0024 v13 = uextend.i64 v10 ;; v34 = iconst.i64 3 ;; v35 = ishl v13, v34 ; v34 = 3 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-get.wat b/tests/disas/gc/null/funcref-in-gc-heap-get.wat index 417531ae00be..78e4178a670d 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0020 trapz v2, user16 +;; @0020 trapz v2, user15 ;; @0020 v13 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v5 = load.i64 notrap aligned readonly can_move v13+24 ;; @0020 v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-new.wat b/tests/disas/gc/null/funcref-in-gc-heap-new.wat index d2f8b7f83c90..baef7b3e99ad 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-new.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-new.wat @@ -27,11 +27,11 @@ ;; @0020 v9 = load.i64 notrap aligned readonly v0+32 ;; @0020 v10 = load.i32 notrap aligned v9 ;; v47 = iconst.i32 7 -;; @0020 v13 = uadd_overflow_trap v10, v47, user18 ; v47 = 7 +;; @0020 v13 = uadd_overflow_trap v10, v47, user17 ; v47 = 7 ;; v54 = iconst.i32 -8 ;; @0020 v15 = band v13, v54 ; v54 = -8 ;; @0020 v4 = iconst.i32 16 -;; @0020 v16 = uadd_overflow_trap v15, v4, user18 ; v4 = 16 +;; @0020 v16 = uadd_overflow_trap v15, v4, user17 ; v4 = 16 ;; @0020 v38 = load.i64 notrap aligned readonly can_move v0+8 ;; @0020 v18 = load.i64 notrap aligned v38+32 ;; @0020 v17 = uextend.i64 v16 diff --git a/tests/disas/gc/null/funcref-in-gc-heap-set.wat b/tests/disas/gc/null/funcref-in-gc-heap-set.wat index aeed15a95b27..02f060375cae 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-set.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v10 = call fn0(v0, v3) ;; @0022 v11 = ireduce.i32 v10 ;; @0022 v12 = load.i64 notrap aligned readonly can_move v0+8 diff --git a/tests/disas/gc/null/multiple-array-get.wat b/tests/disas/gc/null/multiple-array-get.wat index dfe6fe665640..0e7fc6d46961 100644 --- a/tests/disas/gc/null/multiple-array-get.wat +++ b/tests/disas/gc/null/multiple-array-get.wat @@ -21,7 +21,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): -;; @0024 trapz v2, user16 +;; @0024 trapz v2, user15 ;; @0024 v65 = load.i64 notrap aligned readonly can_move v0+8 ;; @0024 v8 = load.i64 notrap aligned readonly can_move v65+24 ;; @0024 v7 = uextend.i64 v2 @@ -30,7 +30,7 @@ ;; @0024 v11 = iadd v9, v10 ; v10 = 8 ;; @0024 v12 = load.i32 notrap aligned readonly v11 ;; @0024 v13 = icmp ult v3, v12 -;; @0024 trapz v13, user17 +;; @0024 trapz v13, user16 ;; @0024 v15 = uextend.i64 v12 ;; v67 = iconst.i64 3 ;; v68 = ishl v15, v67 ; v67 = 3 @@ -51,7 +51,7 @@ ;; @0024 v30 = isub v27, v29 ;; @0024 v31 = load.i64 notrap aligned little v30 ;; @002b v38 = icmp ult v4, v12 -;; @002b trapz v38, user17 +;; @002b trapz v38, user16 ;; v86 = ishl v4, v77 ; v77 = 3 ;; @002b v48 = iadd v86, v19 ; v19 = 16 ;; @002b v53 = isub v20, v48 diff --git a/tests/disas/gc/null/multiple-struct-get.wat b/tests/disas/gc/null/multiple-struct-get.wat index 9896429ba224..dce103bd7b49 100644 --- a/tests/disas/gc/null/multiple-struct-get.wat +++ b/tests/disas/gc/null/multiple-struct-get.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0023 trapz v2, user16 +;; @0023 trapz v2, user15 ;; @0023 v20 = load.i64 notrap aligned readonly can_move v0+8 ;; @0023 v6 = load.i64 notrap aligned readonly can_move v20+24 ;; @0023 v5 = uextend.i64 v2 diff --git a/tests/disas/gc/null/ref-cast.wat b/tests/disas/gc/null/ref-cast.wat index 12e19ab58731..ce6c41a8d3f5 100644 --- a/tests/disas/gc/null/ref-cast.wat +++ b/tests/disas/gc/null/ref-cast.wat @@ -57,7 +57,7 @@ ;; @001e jump block4(v23) ;; ;; block4(v24: i32): -;; @001e trapz v24, user19 +;; @001e trapz v24, user18 ;; v25 = load.i32 notrap v36 ;; @0021 jump block1 ;; diff --git a/tests/disas/gc/null/struct-get.wat b/tests/disas/gc/null/struct-get.wat index 87a6dff893d2..ef75daf799e3 100644 --- a/tests/disas/gc/null/struct-get.wat +++ b/tests/disas/gc/null/struct-get.wat @@ -34,7 +34,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0033 trapz v2, user16 +;; @0033 trapz v2, user15 ;; @0033 v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @0033 v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @0033 v4 = uextend.i64 v2 @@ -59,7 +59,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @003c trapz v2, user16 +;; @003c trapz v2, user15 ;; @003c v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @003c v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @003c v4 = uextend.i64 v2 @@ -85,7 +85,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0045 trapz v2, user16 +;; @0045 trapz v2, user15 ;; @0045 v11 = load.i64 notrap aligned readonly can_move v0+8 ;; @0045 v5 = load.i64 notrap aligned readonly can_move v11+24 ;; @0045 v4 = uextend.i64 v2 @@ -111,7 +111,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @004e trapz v2, user16 +;; @004e trapz v2, user15 ;; @004e v10 = load.i64 notrap aligned readonly can_move v0+8 ;; @004e v5 = load.i64 notrap aligned readonly can_move v10+24 ;; @004e v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/struct-new-default.wat b/tests/disas/gc/null/struct-new-default.wat index 537dbde6d0ba..092c3deda1fc 100644 --- a/tests/disas/gc/null/struct-new-default.wat +++ b/tests/disas/gc/null/struct-new-default.wat @@ -27,11 +27,11 @@ ;; @0021 v11 = load.i64 notrap aligned readonly v0+32 ;; @0021 v12 = load.i32 notrap aligned v11 ;; v49 = iconst.i32 7 -;; @0021 v15 = uadd_overflow_trap v12, v49, user18 ; v49 = 7 +;; @0021 v15 = uadd_overflow_trap v12, v49, user17 ; v49 = 7 ;; v56 = iconst.i32 -8 ;; @0021 v17 = band v15, v56 ; v56 = -8 ;; @0021 v6 = iconst.i32 24 -;; @0021 v18 = uadd_overflow_trap v17, v6, user18 ; v6 = 24 +;; @0021 v18 = uadd_overflow_trap v17, v6, user17 ; v6 = 24 ;; @0021 v41 = load.i64 notrap aligned readonly can_move v0+8 ;; @0021 v20 = load.i64 notrap aligned v41+32 ;; @0021 v19 = uextend.i64 v18 diff --git a/tests/disas/gc/null/struct-new.wat b/tests/disas/gc/null/struct-new.wat index 679780701556..e9f75c07b4d8 100644 --- a/tests/disas/gc/null/struct-new.wat +++ b/tests/disas/gc/null/struct-new.wat @@ -30,11 +30,11 @@ ;; @002a v11 = load.i64 notrap aligned readonly v0+32 ;; @002a v12 = load.i32 notrap aligned v11 ;; v53 = iconst.i32 7 -;; @002a v15 = uadd_overflow_trap v12, v53, user18 ; v53 = 7 +;; @002a v15 = uadd_overflow_trap v12, v53, user17 ; v53 = 7 ;; v60 = iconst.i32 -8 ;; @002a v17 = band v15, v60 ; v60 = -8 ;; @002a v6 = iconst.i32 24 -;; @002a v18 = uadd_overflow_trap v17, v6, user18 ; v6 = 24 +;; @002a v18 = uadd_overflow_trap v17, v6, user17 ; v6 = 24 ;; @002a v43 = load.i64 notrap aligned readonly can_move v0+8 ;; @002a v20 = load.i64 notrap aligned v43+32 ;; @002a v19 = uextend.i64 v18 diff --git a/tests/disas/gc/null/struct-set.wat b/tests/disas/gc/null/struct-set.wat index fc82d6e27d85..f4677896664a 100644 --- a/tests/disas/gc/null/struct-set.wat +++ b/tests/disas/gc/null/struct-set.wat @@ -30,7 +30,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: f32): -;; @0034 trapz v2, user16 +;; @0034 trapz v2, user15 ;; @0034 v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @0034 v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @0034 v4 = uextend.i64 v2 @@ -55,7 +55,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @003f trapz v2, user16 +;; @003f trapz v2, user15 ;; @003f v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @003f v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @003f v4 = uextend.i64 v2 @@ -80,7 +80,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @004a trapz v2, user16 +;; @004a trapz v2, user15 ;; @004a v9 = load.i64 notrap aligned readonly can_move v0+8 ;; @004a v5 = load.i64 notrap aligned readonly can_move v9+24 ;; @004a v4 = uextend.i64 v2 diff --git a/tests/disas/gc/null/v128-fields.wat b/tests/disas/gc/null/v128-fields.wat index 9f08bb73563a..f721d0f21623 100644 --- a/tests/disas/gc/null/v128-fields.wat +++ b/tests/disas/gc/null/v128-fields.wat @@ -22,7 +22,7 @@ ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @0022 trapz v2, user16 +;; @0022 trapz v2, user15 ;; @0022 v19 = load.i64 notrap aligned readonly can_move v0+8 ;; @0022 v5 = load.i64 notrap aligned readonly can_move v19+24 ;; @0022 v4 = uextend.i64 v2 diff --git a/tests/disas/stack-switching/resume-suspend-data-passing.wat b/tests/disas/stack-switching/resume-suspend-data-passing.wat index b24ba2288e9b..95d4d42a7026 100644 --- a/tests/disas/stack-switching/resume-suspend-data-passing.wat +++ b/tests/disas/stack-switching/resume-suspend-data-passing.wat @@ -68,7 +68,7 @@ ;; block4(v11: i64, v12: i64, v52: i32): ;; v73 = iconst.i64 1 ;; v74 = icmp eq v11, v73 ; v73 = 1 -;; @0044 trapnz v74, user22 +;; @0044 trapnz v74, user21 ;; @0044 jump block5 ;; ;; block5: @@ -159,7 +159,7 @@ ;; block0(v0: i64, v1: i64): ;; @0056 v2 = iconst.i32 0 ;; @0056 v4 = call fn0(v0, v2) ; v2 = 0 -;; @0058 trapz v4, user16 +;; @0058 trapz v4, user15 ;; @0058 v8 = call fn1(v0, v4, v2, v2) ; v2 = 0, v2 = 0 ;; @0058 v9 = load.i64 notrap aligned v8+72 ;; @0058 v11 = uextend.i128 v9 @@ -188,13 +188,13 @@ ;; ;; block5: ;; @0062 v18 = ireduce.i64 v16 -;; @0062 trapz v18, user16 +;; @0062 trapz v18, user15 ;; @0062 v21 = load.i64 notrap aligned v18+72 ;; v128 = iconst.i64 64 ;; v129 = ushr.i128 v16, v128 ; v128 = 64 ;; @0062 v20 = ireduce.i64 v129 ;; @0062 v22 = icmp eq v21, v20 -;; @0062 trapz v22, user23 +;; @0062 trapz v22, user22 ;; v130 = iconst.i64 1 ;; v131 = iadd v21, v130 ; v130 = 1 ;; @0062 store notrap aligned v131, v18+72 diff --git a/tests/disas/stack-switching/resume-suspend.wat b/tests/disas/stack-switching/resume-suspend.wat index 1f09b66632f2..2600a0c36a86 100644 --- a/tests/disas/stack-switching/resume-suspend.wat +++ b/tests/disas/stack-switching/resume-suspend.wat @@ -41,7 +41,7 @@ ;; block2(v8: i64, v9: i64): ;; v62 = iconst.i64 1 ;; v63 = icmp eq v8, v62 ; v62 = 1 -;; @003b trapnz v63, user22 +;; @003b trapnz v63, user21 ;; @003b jump block3 ;; ;; block3: @@ -120,7 +120,7 @@ ;; block0(v0: i64, v1: i64): ;; @0043 v7 = iconst.i32 0 ;; @0043 v9 = call fn0(v0, v7) ; v7 = 0 -;; @0045 trapz v9, user16 +;; @0045 trapz v9, user15 ;; @0045 v13 = call fn1(v0, v9, v7, v7) ; v7 = 0, v7 = 0 ;; @0045 v14 = load.i64 notrap aligned v13+72 ;; @004e jump block3 @@ -131,14 +131,14 @@ ;; v134 = ishl v16, v130 ; v130 = 64 ;; v136 = ireduce.i64 v134 ;; v138 = bor v136, v13 -;; @004e trapz v138, user16 +;; @004e trapz v138, user15 ;; @004e v24 = load.i64 notrap aligned v138+72 ;; @0045 v15 = uextend.i128 v13 ;; @0045 v18 = bor v134, v15 ;; v140 = ushr v18, v130 ; v130 = 64 ;; @004e v23 = ireduce.i64 v140 ;; @004e v25 = icmp eq v24, v23 -;; @004e trapz v25, user23 +;; @004e trapz v25, user22 ;; v125 = iconst.i64 1 ;; @004e v26 = iadd v24, v125 ; v125 = 1 ;; @004e store notrap aligned v26, v138+72 diff --git a/tests/disas/stack-switching/symmetric-switch.wat b/tests/disas/stack-switching/symmetric-switch.wat index 666fcd8406ad..8423e68e50a3 100644 --- a/tests/disas/stack-switching/symmetric-switch.wat +++ b/tests/disas/stack-switching/symmetric-switch.wat @@ -40,7 +40,7 @@ ;; block0(v0: i64, v1: i64): ;; @003a v2 = iconst.i32 1 ;; @003a v4 = call fn0(v0, v2) ; v2 = 1 -;; @003c trapz v4, user16 +;; @003c trapz v4, user15 ;; @003c v5 = iconst.i32 1 ;; @003c v6 = iconst.i32 0 ;; @003c v8 = call fn1(v0, v4, v5, v6) ; v5 = 1, v6 = 0 @@ -56,10 +56,10 @@ ;; v137 = uextend.i128 v136 ; v136 = 64 ;; @003e v16 = ushr v13, v137 ;; @003e v17 = ireduce.i64 v16 -;; @003e trapz v15, user16 +;; @003e trapz v15, user15 ;; @003e v18 = load.i64 notrap aligned v15+72 ;; @003e v19 = icmp eq v18, v17 -;; @003e trapz v19, user23 +;; @003e trapz v19, user22 ;; v135 = iconst.i64 1 ;; @003e v20 = iadd v18, v135 ; v135 = 1 ;; @003e store notrap aligned v20, v15+72 @@ -73,7 +73,7 @@ ;; block2(v26: i64, v27: i64): ;; v133 = iconst.i64 1 ;; @003e v28 = icmp eq v26, v133 ; v133 = 1 -;; @003e trapnz v28, user22 +;; @003e trapnz v28, user21 ;; @003e jump block3 ;; ;; block3: @@ -255,7 +255,7 @@ ;; block0(v0: i64, v1: i64): ;; @0047 v2 = iconst.i32 0 ;; @0047 v4 = call fn0(v0, v2) ; v2 = 0 -;; @0049 trapz v4, user16 +;; @0049 trapz v4, user15 ;; @0049 v5 = iconst.i32 0 ;; @0049 v6 = iconst.i32 0 ;; @0049 v8 = call fn1(v0, v4, v5, v6) ; v5 = 0, v6 = 0 @@ -274,10 +274,10 @@ ;; v110 = uextend.i128 v109 ; v109 = 64 ;; @004b v16 = ushr.i128 v13, v110 ;; @004b v17 = ireduce.i64 v16 -;; @004b trapz v15, user16 +;; @004b trapz v15, user15 ;; @004b v18 = load.i64 notrap aligned v15+72 ;; @004b v19 = icmp eq v18, v17 -;; @004b trapz v19, user23 +;; @004b trapz v19, user22 ;; v108 = iconst.i64 1 ;; @004b v20 = iadd v18, v108 ; v108 = 1 ;; @004b store notrap aligned v20, v15+72 diff --git a/tests/disas/typed-funcrefs-eager-init.wat b/tests/disas/typed-funcrefs-eager-init.wat index 94b71da01a39..a2011f17c1d7 100644 --- a/tests/disas/typed-funcrefs-eager-init.wat +++ b/tests/disas/typed-funcrefs-eager-init.wat @@ -140,13 +140,13 @@ ;; v48 = iconst.i64 8 ;; @0048 v14 = iadd v12, v48 ; v48 = 8 ;; @0048 v17 = load.i64 user5 aligned table v14 -;; @004a v18 = load.i64 user16 aligned readonly v17+8 +;; @004a v18 = load.i64 user15 aligned readonly v17+8 ;; @004a v19 = load.i64 notrap aligned readonly v17+24 ;; @004a v20 = call_indirect sig0, v18(v19, v0, v2, v3, v4, v5) ;; v56 = iconst.i64 16 ;; @005b v28 = iadd v12, v56 ; v56 = 16 ;; @005b v31 = load.i64 user5 aligned table v28 -;; @005d v32 = load.i64 user16 aligned readonly v31+8 +;; @005d v32 = load.i64 user15 aligned readonly v31+8 ;; @005d v33 = load.i64 notrap aligned readonly v31+24 ;; @005d v34 = call_indirect sig0, v32(v33, v0, v2, v3, v4, v5) ;; @0066 jump block1 @@ -196,11 +196,11 @@ ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @009e v9 = load.i64 notrap aligned table v0+64 -;; @00a0 v10 = load.i64 user16 aligned readonly v9+8 +;; @00a0 v10 = load.i64 user15 aligned readonly v9+8 ;; @00a0 v11 = load.i64 notrap aligned readonly v9+24 ;; @00a0 v12 = call_indirect sig0, v10(v11, v0, v2, v3, v4, v5) ;; @00af v15 = load.i64 notrap aligned table v0+80 -;; @00b1 v16 = load.i64 user16 aligned readonly v15+8 +;; @00b1 v16 = load.i64 user15 aligned readonly v15+8 ;; @00b1 v17 = load.i64 notrap aligned readonly v15+24 ;; @00b1 v18 = call_indirect sig0, v16(v17, v0, v2, v3, v4, v5) ;; @00ba jump block1 diff --git a/tests/disas/typed-funcrefs.wat b/tests/disas/typed-funcrefs.wat index 32082555f273..bfed93b39dcd 100644 --- a/tests/disas/typed-funcrefs.wat +++ b/tests/disas/typed-funcrefs.wat @@ -153,7 +153,7 @@ ;; @0048 jump block3(v23) ;; ;; block3(v19: i64): -;; @004a v24 = load.i64 user16 aligned readonly v19+8 +;; @004a v24 = load.i64 user15 aligned readonly v19+8 ;; @004a v25 = load.i64 notrap aligned readonly v19+24 ;; @004a v26 = call_indirect sig1, v24(v25, v0, v2, v3, v4, v5) ;; v76 = iconst.i64 16 @@ -170,7 +170,7 @@ ;; @005b jump block5(v48) ;; ;; block5(v44: i64): -;; @005d v49 = load.i64 user16 aligned readonly v44+8 +;; @005d v49 = load.i64 user15 aligned readonly v44+8 ;; @005d v50 = load.i64 notrap aligned readonly v44+24 ;; @005d v51 = call_indirect sig1, v49(v50, v0, v2, v3, v4, v5) ;; @0066 jump block1 @@ -244,11 +244,11 @@ ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @009e v9 = load.i64 notrap aligned table v0+64 -;; @00a0 v10 = load.i64 user16 aligned readonly v9+8 +;; @00a0 v10 = load.i64 user15 aligned readonly v9+8 ;; @00a0 v11 = load.i64 notrap aligned readonly v9+24 ;; @00a0 v12 = call_indirect sig0, v10(v11, v0, v2, v3, v4, v5) ;; @00af v15 = load.i64 notrap aligned table v0+80 -;; @00b1 v16 = load.i64 user16 aligned readonly v15+8 +;; @00b1 v16 = load.i64 user15 aligned readonly v15+8 ;; @00b1 v17 = load.i64 notrap aligned readonly v15+24 ;; @00b1 v18 = call_indirect sig0, v16(v17, v0, v2, v3, v4, v5) ;; @00ba jump block1 From a60e7f724f0f08b269460227f7c04070aa996a7a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Jan 2026 13:21:31 -0700 Subject: [PATCH 4/5] address review feedback --- .../src/runtime/component/concurrent.rs | 21 ++++++---------- .../runtime/component/concurrent_disabled.rs | 7 +++--- .../wasmtime/src/runtime/component/store.rs | 21 ++++++++++++++++ crates/wasmtime/src/runtime/func.rs | 24 +++++++++---------- crates/wasmtime/src/runtime/store.rs | 16 ------------- 5 files changed, 42 insertions(+), 47 deletions(-) diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs index 0fa6d79d206c..e8198a4a38e8 100644 --- a/crates/wasmtime/src/runtime/component/concurrent.rs +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -51,7 +51,6 @@ //! in host functions. use crate::component::func::{self, Func}; -use crate::component::store::StoreComponentInstanceId; use crate::component::{ HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError, RuntimeInstance, }; @@ -1407,8 +1406,8 @@ impl StoreOpaque { return false; } - let flags = StoreComponentInstanceId::new(self.id(), instance.instance) - .get(self) + let flags = self + .component_instance(instance.instance) .instance_flags(instance.index); unsafe { !flags.needs_post_return() } @@ -1466,8 +1465,7 @@ impl StoreOpaque { /// Helper function to retrieve the `ConcurrentInstanceState` for the /// specified instance. fn instance_state(&mut self, instance: RuntimeInstance) -> &mut ConcurrentInstanceState { - StoreComponentInstanceId::new(self.id(), instance.instance) - .get_mut(self) + self.component_instance_mut(instance.instance) .instance_state(instance.index) .concurrent_state() } @@ -1475,8 +1473,7 @@ impl StoreOpaque { /// Helper function to retrieve the `HandleTable` for the specified /// instance. fn handle_table(&mut self, instance: RuntimeInstance) -> &mut HandleTable { - StoreComponentInstanceId::new(self.id(), instance.instance) - .get_mut(self) + self.component_instance_mut(instance.instance) .instance_state(instance.index) .handle_table() } @@ -1490,8 +1487,7 @@ impl StoreOpaque { let old_thread = state.guest_thread.take(); if let Some(old_thread) = old_thread { let instance = state.get_mut(old_thread.task).unwrap().instance.instance; - StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) + self.component_instance_mut(instance) .set_task_may_block(false) } @@ -1513,8 +1509,7 @@ impl StoreOpaque { let guest_thread = state.guest_thread.unwrap(); let instance = state.get_mut(guest_thread.task).unwrap().instance.instance; let may_block = self.concurrent_state_mut().may_block(guest_thread.task); - StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) + self.component_instance_mut(instance) .set_task_may_block(may_block) } @@ -1522,9 +1517,7 @@ impl StoreOpaque { let state = self.concurrent_state_mut(); let task = state.guest_thread.unwrap().task; let instance = state.get_mut(task).unwrap().instance.instance; - let task_may_block = StoreComponentInstanceId::new(self.id(), instance) - .get_mut(self) - .get_task_may_block(); + let task_may_block = self.component_instance(instance).get_task_may_block(); if task_may_block { Ok(()) diff --git a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs index cf0a3ef879ff..0437c1f540d7 100644 --- a/crates/wasmtime/src/runtime/component/concurrent_disabled.rs +++ b/crates/wasmtime/src/runtime/component/concurrent_disabled.rs @@ -1,6 +1,5 @@ use crate::component::func::{LiftContext, LowerContext}; use crate::component::matching::InstanceType; -use crate::component::store::StoreComponentInstanceId; use crate::component::{ComponentType, Lift, Lower, RuntimeInstance, Val}; use crate::store::StoreOpaque; use crate::{Result, bail, error::format_err}; @@ -162,10 +161,10 @@ impl StoreOpaque { return false; } - let flags = StoreComponentInstanceId::new(self.id(), instance.instance) - .get(self) + let flags = self + .component_instance(instance.instance) .instance_flags(instance.index); - !unsafe { flags.needs_post_return() } + unsafe { !flags.needs_post_return() } } } diff --git a/crates/wasmtime/src/runtime/component/store.rs b/crates/wasmtime/src/runtime/component/store.rs index d12e97d3748a..0b2d571aa52d 100644 --- a/crates/wasmtime/src/runtime/component/store.rs +++ b/crates/wasmtime/src/runtime/component/store.rs @@ -11,6 +11,9 @@ use wasmtime_environ::component::RuntimeComponentInstanceIndex; #[derive(Default)] pub struct ComponentStoreData { instances: PrimaryMap>, + + /// Whether an instance belonging to this store has trapped. + trapped: bool, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -23,6 +26,16 @@ pub struct RuntimeInstance { pub index: RuntimeComponentInstanceIndex, } +impl StoreOpaque { + pub(crate) fn trapped(&self) -> bool { + self.store_data().components.trapped + } + + pub(crate) fn set_trapped(&mut self) { + self.store_data_mut().components.trapped = true; + } +} + impl StoreData { pub(crate) fn push_component_instance( &mut self, @@ -92,6 +105,14 @@ impl StoreOpaque { pub(crate) fn component_instance(&self, id: ComponentInstanceId) -> &ComponentInstance { self.store_data().component_instance(id) } + + #[cfg(feature = "component-model-async")] + pub(crate) fn component_instance_mut( + &mut self, + id: ComponentInstanceId, + ) -> Pin<&mut ComponentInstance> { + self.store_data_mut().component_instance_mut(id) + } } /// A type used to represent an allocated `ComponentInstance` located within a diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs index 5d5522d250da..dd347a11b569 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs @@ -1505,20 +1505,18 @@ pub(crate) fn invoke_wasm_and_catch_traps( // stack-allocated `previous_runtime_state`. let mut previous_runtime_state = EntryStoreContext::enter_wasm(store, &mut initial_stack_csi); - (|| { - if let Err(trap) = store.0.call_hook(CallHook::CallingWasm) { - // `previous_runtime_state` implicitly dropped here - return Err(trap); - } - let result = crate::runtime::vm::catch_traps(store, &mut previous_runtime_state, closure); - core::mem::drop(previous_runtime_state); - store.0.call_hook(CallHook::ReturningFromWasm)?; - result - })() - .inspect_err(|_| { - #[cfg(feature = "component-model")] + if let Err(trap) = store.0.call_hook(CallHook::CallingWasm) { + // `previous_runtime_state` implicitly dropped here + return Err(trap); + } + let result = crate::runtime::vm::catch_traps(store, &mut previous_runtime_state, closure); + #[cfg(feature = "component-model")] + if result.is_err() { store.0.set_trapped(); - }) + } + core::mem::drop(previous_runtime_state); + store.0.call_hook(CallHook::ReturningFromWasm)?; + result } /// 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 f82c8b602e6f..f41c401daf10 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -545,10 +545,6 @@ pub struct StoreOpaque { #[cfg(feature = "component-model")] concurrent_state: concurrent::ConcurrentState, - /// Whether an instance belonging to this store has trapped. - #[cfg(feature = "component-model")] - trapped: bool, - /// State related to the executor of wasm code. /// /// For example if Pulley is enabled and configured then this will store a @@ -768,8 +764,6 @@ impl Store { wasm_val_raw_storage: Vec::new(), pkey, #[cfg(feature = "component-model")] - trapped: false, - #[cfg(feature = "component-model")] component_host_table: Default::default(), #[cfg(feature = "component-model")] component_calls: Default::default(), @@ -2771,16 +2765,6 @@ at https://bytecodealliance.org/security. pub(crate) fn get_epoch_deadline(&mut self) -> u64 { *self.vm_store_context.epoch_deadline.get_mut() } - - #[cfg(feature = "component-model")] - pub(crate) fn trapped(&self) -> bool { - self.trapped - } - - #[cfg(feature = "component-model")] - pub(crate) fn set_trapped(&mut self) { - self.trapped = true; - } } /// Helper parameter to [`StoreOpaque::allocate_instance`]. From 1ffadaa38451a4485cc632d5f0d2d5a426f7e0c2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Jan 2026 14:58:35 -0700 Subject: [PATCH 5/5] sync `trap.h` with `trap_encoding.rs` ...and add const assertions to `trap.rs` to help avoid future divergence. --- crates/c-api/include/wasmtime/trap.h | 44 ++++++++++++++++++++++++---- crates/c-api/src/trap.rs | 40 +++++++++++++++++++++++++ crates/c-api/tests/trap.cc | 1 - crates/environ/src/trap_encoding.rs | 14 ++------- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/crates/c-api/include/wasmtime/trap.h b/crates/c-api/include/wasmtime/trap.h index 51c0d211470d..9f251363e7b2 100644 --- a/crates/c-api/include/wasmtime/trap.h +++ b/crates/c-api/include/wasmtime/trap.h @@ -47,12 +47,6 @@ enum wasmtime_trap_code_enum { WASMTIME_TRAP_CODE_UNREACHABLE_CODE_REACHED, /// Execution has potentially run too long and may be interrupted. WASMTIME_TRAP_CODE_INTERRUPT, - /// When the `component-model` feature is enabled this trap represents a - /// function that was `canon lift`'d, then `canon lower`'d, then called. - /// This combination of creation of a function in the component model - /// generates a function that always traps and, when called, produces this - /// flavor of trap. - WASMTIME_TRAP_CODE_ALWAYS_TRAP_ADAPTER, /// Execution has run out of the configured fuel amount. WASMTIME_TRAP_CODE_OUT_OF_FUEL, /// Used to indicate that a trap was raised by atomic wait operations on non @@ -74,9 +68,47 @@ enum wasmtime_trap_code_enum { /// Async-lifted export failed to produce a result by calling `task.return` /// before returning `STATUS_DONE` and/or after all host tasks completed. WASMTIME_TRAP_CODE_NO_ASYNC_RESULT, + /// We are suspending to a tag for which there is no active handler. + WASMTIME_TRAP_CODE_UNHANDLED_TAG, + /// Attempt to resume a continuation twice. + WASMTIME_TRAP_CODE_CONTINUATION_ALREADY_CONSUMED, /// A Pulley opcode was executed at runtime when the opcode was disabled at /// compile time. WASMTIME_TRAP_CODE_DISABLED_OPCODE, + /// Async event loop deadlocked; i.e. it cannot make further progress given + /// that all host tasks have completed and any/all host-owned stream/future + /// handles have been dropped. + WASMTIME_TRAP_CODE_ASYNC_DEADLOCK, + /// When the `component-model` feature is enabled this trap represents a + /// scenario where a component instance tried to call an import or intrinsic + /// when it wasn't allowed to, e.g. from a post-return function. + WASMTIME_TRAP_CODE_CANNOT_LEAVE_COMPONENT, + /// A synchronous task attempted to make a potentially blocking call prior + /// to returning. + WASMTIME_TRAP_CODE_CANNOT_BLOCK_SYNC_TASK, + /// A component tried to lift a `char` with an invalid bit pattern. + WASMTIME_TRAP_CODE_INVALID_CHAR, + /// Debug assertion generated for a fused adapter regarding the expected + /// completion of a string encoding operation. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_STRING_ENCODING_FINISHED, + /// Debug assertion generated for a fused adapter regarding a string + /// encoding operation. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_EQUAL_CODE_UNITS, + /// Debug assertion generated for a fused adapter regarding the alignment of + /// a pointer. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_POINTER_ALIGNED, + /// Debug assertion generated for a fused adapter regarding the upper bits + /// of a 64-bit value. + WASMTIME_TRAP_CODE_DEBUG_ASSERT_UPPER_BITS_UNSET, + /// A component tried to lift or lower a string past the end of its memory. + WASMTIME_TRAP_CODE_STRING_OUT_OF_BOUNDS, + /// A component tried to lift or lower a list past the end of its memory. + WASMTIME_TRAP_CODE_LIST_OUT_OF_BOUNDS, + /// A component used an invalid discriminant when lowering a variant value. + WASMTIME_TRAP_CODE_INVALID_DISCRIMINANT, + /// A component passed an unaligned pointer when lifting or lowering a + /// value. + WASMTIME_TRAP_CODE_UNALIGNED_POINTER, }; /** diff --git a/crates/c-api/src/trap.rs b/crates/c-api/src/trap.rs index 9a8b6b7f864e..1eb3a1c508de 100644 --- a/crates/c-api/src/trap.rs +++ b/crates/c-api/src/trap.rs @@ -2,6 +2,46 @@ use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t}; use std::cell::OnceCell; use wasmtime::{Error, Trap, WasmBacktrace, format_err}; +// Help ensure the Rust enum matches the C one. If any of these assertions +// fail, please update both this code and `trap.h` to sync them with +// `trap_encoding.rs`. +const _: () = { + assert!(Trap::StackOverflow as u8 == 0); + assert!(Trap::MemoryOutOfBounds as u8 == 1); + assert!(Trap::HeapMisaligned as u8 == 2); + assert!(Trap::TableOutOfBounds as u8 == 3); + assert!(Trap::IndirectCallToNull as u8 == 4); + assert!(Trap::BadSignature as u8 == 5); + assert!(Trap::IntegerOverflow as u8 == 6); + assert!(Trap::IntegerDivisionByZero as u8 == 7); + assert!(Trap::BadConversionToInteger as u8 == 8); + assert!(Trap::UnreachableCodeReached as u8 == 9); + assert!(Trap::Interrupt as u8 == 10); + assert!(Trap::OutOfFuel as u8 == 11); + assert!(Trap::AtomicWaitNonSharedMemory as u8 == 12); + assert!(Trap::NullReference as u8 == 13); + assert!(Trap::ArrayOutOfBounds as u8 == 14); + assert!(Trap::AllocationTooLarge as u8 == 15); + assert!(Trap::CastFailure as u8 == 16); + assert!(Trap::CannotEnterComponent as u8 == 17); + assert!(Trap::NoAsyncResult as u8 == 18); + assert!(Trap::UnhandledTag as u8 == 19); + assert!(Trap::ContinuationAlreadyConsumed as u8 == 20); + assert!(Trap::DisabledOpcode as u8 == 21); + assert!(Trap::AsyncDeadlock as u8 == 22); + assert!(Trap::CannotLeaveComponent as u8 == 23); + assert!(Trap::CannotBlockSyncTask as u8 == 24); + assert!(Trap::InvalidChar as u8 == 25); + assert!(Trap::DebugAssertStringEncodingFinished as u8 == 26); + assert!(Trap::DebugAssertEqualCodeUnits as u8 == 27); + assert!(Trap::DebugAssertPointerAligned as u8 == 28); + assert!(Trap::DebugAssertUpperBitsUnset as u8 == 29); + assert!(Trap::StringOutOfBounds as u8 == 30); + assert!(Trap::ListOutOfBounds as u8 == 31); + assert!(Trap::InvalidDiscriminant as u8 == 32); + assert!(Trap::UnalignedPointer as u8 == 33); +}; + #[repr(C)] pub struct wasm_trap_t { pub(crate) error: Error, diff --git a/crates/c-api/tests/trap.cc b/crates/c-api/tests/trap.cc index ec059d792972..7b41e37190ae 100644 --- a/crates/c-api/tests/trap.cc +++ b/crates/c-api/tests/trap.cc @@ -60,7 +60,6 @@ TEST(Trap, Codes) { TEST_CODE(BAD_CONVERSION_TO_INTEGER); TEST_CODE(UNREACHABLE_CODE_REACHED); TEST_CODE(INTERRUPT); - TEST_CODE(ALWAYS_TRAP_ADAPTER); TEST_CODE(OUT_OF_FUEL); TEST_CODE(ATOMIC_WAIT_NON_SHARED_MEMORY); TEST_CODE(NULL_REFERENCE); diff --git a/crates/environ/src/trap_encoding.rs b/crates/environ/src/trap_encoding.rs index be083aea73fc..f9d22368eb85 100644 --- a/crates/environ/src/trap_encoding.rs +++ b/crates/environ/src/trap_encoding.rs @@ -16,7 +16,7 @@ pub struct TrapInformation { // The code can be accessed from the c-api, where the possible values are // translated into enum values defined there: // -// * `wasm_trap_code` in c-api/src/trap.rs, and +// * the const assertions in c-api/src/trap.rs, and // * `wasmtime_trap_code_enum` in c-api/include/wasmtime/trap.h. // // These need to be kept in sync. @@ -121,13 +121,6 @@ pub enum Trap { /// encoding operation. DebugAssertEqualCodeUnits, - /// Debug assertion generated for a fused adapter regarding the expected - /// value of the `may_enter` flag for an instance. - /// - /// TODO: Remove this once - /// https://github.com/bytecodealliance/wasmtime/pull/12153 has been merged. - DebugAssertMayEnterUnset, - /// Debug assertion generated for a fused adapter regarding the alignment of /// a pointer. DebugAssertPointerAligned, @@ -148,7 +141,8 @@ pub enum Trap { /// A component passed an unaligned pointer when lifting or lowering a /// value. UnalignedPointer, - // if adding a variant here be sure to update the `check!` macro below + // 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 } impl Trap { @@ -193,7 +187,6 @@ impl Trap { InvalidChar DebugAssertStringEncodingFinished DebugAssertEqualCodeUnits - DebugAssertMayEnterUnset DebugAssertPointerAligned DebugAssertUpperBitsUnset StringOutOfBounds @@ -239,7 +232,6 @@ impl fmt::Display for Trap { InvalidChar => "invalid `char` bit pattern", DebugAssertStringEncodingFinished => "should have finished string encoding", DebugAssertEqualCodeUnits => "code units should be equal", - DebugAssertMayEnterUnset => "`may_enter` flag should be unset", DebugAssertPointerAligned => "pointer should be aligned", DebugAssertUpperBitsUnset => "upper bits should be unset", StringOutOfBounds => "string content out-of-bounds",