mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
wasm backend call into zig to allocate with refcount correctly
This commit is contained in:
parent
54d0409396
commit
669daad33d
1 changed files with 16 additions and 37 deletions
|
@ -1562,7 +1562,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
||||||
// Allocate heap space and store its address in a local variable
|
// Allocate heap space and store its address in a local variable
|
||||||
let heap_local_id = self.storage.create_anonymous_local(PTR_TYPE);
|
let heap_local_id = self.storage.create_anonymous_local(PTR_TYPE);
|
||||||
let heap_alignment = self.layout_interner.alignment_bytes(elem_layout);
|
let heap_alignment = self.layout_interner.alignment_bytes(elem_layout);
|
||||||
self.allocate_with_refcount(Some(size), heap_alignment, 1);
|
let elems_refcounted = self.layout_interner.contains_refcounted(elem_layout);
|
||||||
|
self.allocate_with_refcount(size, heap_alignment, elems_refcounted);
|
||||||
self.code_builder.set_local(heap_local_id);
|
self.code_builder.set_local(heap_local_id);
|
||||||
|
|
||||||
let (stack_local_id, stack_offset) =
|
let (stack_local_id, stack_offset) =
|
||||||
|
@ -1676,13 +1677,13 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
||||||
}
|
}
|
||||||
self.code_builder.else_();
|
self.code_builder.else_();
|
||||||
{
|
{
|
||||||
self.allocate_with_refcount(Some(data_size), data_alignment, 1);
|
self.allocate_with_refcount(data_size, data_alignment, false);
|
||||||
self.code_builder.set_local(*local_id);
|
self.code_builder.set_local(*local_id);
|
||||||
}
|
}
|
||||||
self.code_builder.end();
|
self.code_builder.end();
|
||||||
} else {
|
} else {
|
||||||
// Call the allocator to get a memory address.
|
// Call the allocator to get a memory address.
|
||||||
self.allocate_with_refcount(Some(data_size), data_alignment, 1);
|
self.allocate_with_refcount(data_size, data_alignment, false);
|
||||||
self.code_builder.set_local(*local_id);
|
self.code_builder.set_local(*local_id);
|
||||||
}
|
}
|
||||||
(*local_id, 0)
|
(*local_id, 0)
|
||||||
|
@ -1965,53 +1966,31 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
||||||
* Refcounting & Heap allocation
|
* Refcounting & Heap allocation
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
|
|
||||||
/// Allocate heap space and write an initial refcount
|
/// Allocates heap space and write an initial refcount of 1.
|
||||||
/// 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
|
/// Leaves the *data* address on the VM stack
|
||||||
|
///
|
||||||
|
/// elements_refcounted should only ever be set for lists.
|
||||||
fn allocate_with_refcount(
|
fn allocate_with_refcount(
|
||||||
&mut self,
|
&mut self,
|
||||||
comptime_data_size: Option<u32>,
|
data_size: u32,
|
||||||
alignment_bytes: u32,
|
alignment_bytes: u32,
|
||||||
initial_refcount: u32,
|
elements_refcounted: bool,
|
||||||
) {
|
) {
|
||||||
if !self.can_relocate_heap {
|
if !self.can_relocate_heap {
|
||||||
// This will probably only happen for test hosts.
|
// This will probably only happen for test hosts.
|
||||||
panic!("The app tries to allocate heap memory but the host doesn't support that. It needs to export symbols __heap_base and __heap_end");
|
panic!("The app tries to allocate heap memory but the host doesn't support that. It needs to export symbols __heap_base and __heap_end");
|
||||||
}
|
}
|
||||||
// Add extra bytes for the refcount
|
|
||||||
let extra_bytes = alignment_bytes.max(PTR_SIZE);
|
|
||||||
|
|
||||||
if let Some(data_size) = comptime_data_size {
|
// Zig arguments Wasm types
|
||||||
// Data size known at compile time and passed as an argument
|
// data_bytes: usize i32
|
||||||
self.code_builder
|
// element_alignment: u32 i32
|
||||||
.i32_const((data_size + extra_bytes) as i32);
|
// element_refcounted: bool i32
|
||||||
} else {
|
|
||||||
// Data size known only at runtime and is on top of VM stack
|
|
||||||
self.code_builder.i32_const(extra_bytes as i32);
|
|
||||||
self.code_builder.i32_add();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provide a constant for the alignment argument
|
self.code_builder.i32_const(data_size as i32);
|
||||||
self.code_builder.i32_const(alignment_bytes as i32);
|
self.code_builder.i32_const(alignment_bytes as i32);
|
||||||
|
self.code_builder.i32_const(elements_refcounted as i32);
|
||||||
|
|
||||||
// Call the foreign function. (Zig and C calling conventions are the same for this signature)
|
self.call_host_fn_after_loading_args(bitcode::UTILS_ALLOCATE_WITH_REFCOUNT);
|
||||||
self.call_host_fn_after_loading_args("roc_alloc");
|
|
||||||
|
|
||||||
// Save the allocation address to a temporary local variable
|
|
||||||
let local_id = self.storage.create_anonymous_local(ValueType::I32);
|
|
||||||
self.code_builder.tee_local(local_id);
|
|
||||||
|
|
||||||
// Write the initial refcount
|
|
||||||
let refcount_offset = extra_bytes - PTR_SIZE;
|
|
||||||
let encoded_refcount = (initial_refcount as i32) - 1 + i32::MIN;
|
|
||||||
self.code_builder.i32_const(encoded_refcount);
|
|
||||||
self.code_builder.i32_store(Align::Bytes4, refcount_offset);
|
|
||||||
|
|
||||||
// Put the data address on the VM stack
|
|
||||||
self.code_builder.get_local(local_id);
|
|
||||||
self.code_builder.i32_const(extra_bytes as i32);
|
|
||||||
self.code_builder.i32_add();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_reset(&mut self, argument: Symbol, ret_symbol: Symbol, ret_storage: &StoredValue) {
|
fn expr_reset(&mut self, argument: Symbol, ret_symbol: Symbol, ret_storage: &StoredValue) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue