mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
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:
parent
cefbf3aa51
commit
15ef517cf2
2 changed files with 74 additions and 9 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue