alexcrichton opened issue #11188:
Wasmtime's current modeling of canonical ABI options is quite messy and quite
unsafe-prone. We should improve this on both axes ideally.One example of how things are messy right now is that while there's an
Optionstype within Wasmtime that's not used pervasively. That means that modeling a call to a lowered function has no "options identifier" to pass along meaning that all options are passed individually. This means that the type signature of a host-lowered function in Wasmtime has no less than 11 function parameter. This is messy because it's onerous to add more parameters over time just to get plumbed around and it means that passing around options is unnecessarily expensive.Passing all of these options individually is additionally quite
unsafe-heavy because it's a bunch of raw pointers getting thrown around. This means that all users effectively have no ability to be safe and are required to be tagged asunsafefunctions. Everywhere from the entrypoint to the creation ofOptionsis effectively unsafe with the documentation being "hey I'm just the messenger don't shoot me". Connecting these two across large distances is not always easy to do.
A solution I would propose would look something like:
- Change the compilation process to "intern" canonical ABI options. Compiled component metadata would then have
PrimaryMap<OptionsIndex, Options>or something like that.- Change
VMLoweringCalleetofn(vmctx: NonNull<VMOpaqueContext>, data: NonNull<u8>, options: u32, args_and_results: NonNull<mem::MaybeUninit<ValRaw>>, nargs_and_results: usize) -> bool;. Effectively compress almost everything intooptions: u32which is anOptionsIndex.- Change the constructor of
Optionstoday to take anOptionsIndexinstead of a bunch of parameters individually. This means that internallyOptionswill have someunsafecode, but it will be scoped to just that set of options andOptionsadditionally now carries "proof" that it's valid (it came from a trusted location, the compiler, it's not a bunch of arbitrary values).There might be further cleanup from there perhaps? This is particularly going to affect component model async bits as well, but it may not make sense to intern all options there just yet. Some information present in lowered host functions is irrelevant for async bits, for example the component model type doesn't exist for intrinsics. Ideally though everything would use the same interning system.
alexcrichton added the wasm-proposal:component-model label to Issue #11188.
alexcrichton added the wasm-proposal:component-model-async label to Issue #11188.
alexcrichton added the wasmtime:unsafe-code label to Issue #11188.
fitzgen closed issue #11188:
Wasmtime's current modeling of canonical ABI options is quite messy and quite
unsafe-prone. We should improve this on both axes ideally.One example of how things are messy right now is that while there's an
Optionstype within Wasmtime that's not used pervasively. That means that modeling a call to a lowered function has no "options identifier" to pass along meaning that all options are passed individually. This means that the type signature of a host-lowered function in Wasmtime has no less than 11 function parameter. This is messy because it's onerous to add more parameters over time just to get plumbed around and it means that passing around options is unnecessarily expensive.Passing all of these options individually is additionally quite
unsafe-heavy because it's a bunch of raw pointers getting thrown around. This means that all users effectively have no ability to be safe and are required to be tagged asunsafefunctions. Everywhere from the entrypoint to the creation ofOptionsis effectively unsafe with the documentation being "hey I'm just the messenger don't shoot me". Connecting these two across large distances is not always easy to do.
A solution I would propose would look something like:
- Change the compilation process to "intern" canonical ABI options. Compiled component metadata would then have
PrimaryMap<OptionsIndex, Options>or something like that.- Change
VMLoweringCalleetofn(vmctx: NonNull<VMOpaqueContext>, data: NonNull<u8>, options: u32, args_and_results: NonNull<mem::MaybeUninit<ValRaw>>, nargs_and_results: usize) -> bool;. Effectively compress almost everything intooptions: u32which is anOptionsIndex.- Change the constructor of
Optionstoday to take anOptionsIndexinstead of a bunch of parameters individually. This means that internallyOptionswill have someunsafecode, but it will be scoped to just that set of options andOptionsadditionally now carries "proof" that it's valid (it came from a trusted location, the compiler, it's not a bunch of arbitrary values).There might be further cleanup from there perhaps? This is particularly going to affect component model async bits as well, but it may not make sense to intern all options there just yet. Some information present in lowered host functions is irrelevant for async bits, for example the component model type doesn't exist for intrinsics. Ideally though everything would use the same interning system.
Last updated: Dec 06 2025 at 06:05 UTC