(&self, mut store: impl AsContextMut, params: Params)
| 204 | } |
| 205 | |
| 206 | fn call_impl(&self, mut store: impl AsContextMut, params: Params) -> Result<Return> { |
| 207 | let mut store = store.as_context_mut(); |
| 208 | |
| 209 | if self.func.abi_async(store.0) { |
| 210 | bail!("must enable the `component-model-async` feature to call async-lifted exports") |
| 211 | } |
| 212 | |
| 213 | // Note that this is in theory simpler than it might read at this time. |
| 214 | // Here we're doing a runtime dispatch on the `flatten_count` for the |
| 215 | // params/results to see whether they're inbounds. This creates 4 cases |
| 216 | // to handle. In reality this is a highly optimizable branch where LLVM |
| 217 | // will easily figure out that only one branch here is taken. |
| 218 | // |
| 219 | // Otherwise this current construction is done to ensure that the stack |
| 220 | // space reserved for the params/results is always of the appropriate |
| 221 | // size (as the params/results needed differ depending on the "flatten" |
| 222 | // count) |
| 223 | // |
| 224 | // SAFETY: the safety of these invocations of `call_raw` depends on the |
| 225 | // correctness of the ascription of the `LowerParams` and `LowerReturn` |
| 226 | // types on the `call_raw` function. That's upheld here through the |
| 227 | // safety requirements of `Lift` and `Lower` on `Params` and `Return` in |
| 228 | // combination with checking the various possible branches here and |
| 229 | // dispatching to appropriately typed functions. |
| 230 | let (result, post_return_arg) = unsafe { |
| 231 | // This type is used as `LowerParams` for `call_raw` which is either |
| 232 | // `Params::Lower` or `ValRaw` representing it's either on the stack |
| 233 | // or it's on the heap. This allocates 1 extra `ValRaw` on the stack |
| 234 | // if `Params` is empty and `Return` is also empty, but that's a |
| 235 | // reasonable enough price to pay for now given the current code |
| 236 | // organization. |
| 237 | #[derive(Copy, Clone)] |
| 238 | union Union<T: Copy, U: Copy> { |
| 239 | _a: T, |
| 240 | _b: U, |
| 241 | } |
| 242 | |
| 243 | if Return::flatten_count() <= MAX_FLAT_RESULTS { |
| 244 | self.func.call_raw( |
| 245 | store.as_context_mut(), |
| 246 | |cx, ty, dst: &mut MaybeUninit<Union<Params::Lower, ValRaw>>| { |
| 247 | let dst = storage_as_slice_mut(dst); |
| 248 | Self::lower_args(cx, ty, dst, ¶ms) |
| 249 | }, |
| 250 | Self::lift_stack_result, |
| 251 | ) |
| 252 | } else { |
| 253 | self.func.call_raw( |
| 254 | store.as_context_mut(), |
| 255 | |cx, ty, dst: &mut MaybeUninit<Union<Params::Lower, ValRaw>>| { |
| 256 | let dst = storage_as_slice_mut(dst); |
| 257 | Self::lower_args(cx, ty, dst, ¶ms) |
| 258 | }, |
| 259 | Self::lift_heap_result, |
| 260 | ) |
| 261 | } |
| 262 | }?; |
| 263 |
no test coverage detected