gen-wasm: box captured data before passing it to a higher-order lowlevel

Previously, when it existed, captured data would always be represented
as a struct, and hence implicitly boxed. That meant that passing
captured data would always pass a pointer. However, now, captured data
can live unwrapped. This poses a challenge for the higher-order
lowlevels, which always expect captures data to be passed as an opaque
pointer. As such, always box captured data.

It's possible to optimize this so that only unwrapped captures data
needs to be boxed; however, that is not attempted in this patch.
This commit is contained in:
Ayaz Hafiz 2022-08-15 09:31:54 -05:00
parent cefbf3aa51
commit 15ef517cf2
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 74 additions and 9 deletions

View file

@ -517,7 +517,7 @@ impl<'a> WasmBackend<'a> {
// Load all the arguments for the inner function
for (i, wrapper_arg) in wrapper_arg_layouts.iter().enumerate() {
let is_closure_data = i == 0; // Skip closure data (first for wrapper, last for inner)
let is_closure_data = i == 0; // Skip closure data (first for wrapper, last for inner). We'll handle it below.
let is_return_pointer = i == wrapper_arg_layouts.len() - 1; // Skip return pointer (may not be an arg for inner. And if it is, swaps from end to start)
if is_closure_data || is_return_pointer {
continue;
@ -540,7 +540,16 @@ impl<'a> WasmBackend<'a> {
// If the inner function has closure data, it's the last arg of the inner fn
let closure_data_layout = wrapper_arg_layouts[0];
if closure_data_layout.stack_size(TARGET_INFO) > 0 {
// The closure data exists, and will have been passed in to the wrapper as boxed.
let inner_closure_data_layout = match closure_data_layout {
Layout::Boxed(inner) => inner,
other => internal_error!(
"Expected a boxed layout for wrapped closure data, got {:?}",
other
),
};
self.code_builder.get_local(LocalId(0));
self.dereference_boxed_value(inner_closure_data_layout);
}
// Call the wrapped inner function
@ -1870,7 +1879,7 @@ impl<'a> WasmBackend<'a> {
/// If the data size is known at compile time, pass it in comptime_data_size.
/// If size is only known at runtime, push *data* size to the VM stack first.
/// Leaves the *data* address on the VM stack
fn allocate_with_refcount(
pub fn allocate_with_refcount(
&mut self,
comptime_data_size: Option<u32>,
alignment_bytes: u32,