diff --git a/crates/compiler/test_gen/src/gen_refcount.rs b/crates/compiler/test_gen/src/gen_refcount.rs index bc1e29266b..5e8933dbc9 100644 --- a/crates/compiler/test_gen/src/gen_refcount.rs +++ b/crates/compiler/test_gen/src/gen_refcount.rs @@ -96,13 +96,34 @@ fn list_str_inc() { ), RocList>, &[ - Live(6), // s + Live(3), // s Live(2), // list Live(1) // result ] ); } +#[test] +#[cfg(feature = "gen-wasm")] +fn list_str_slice() { + assert_refcounts!( + indoc!( + r#" + s = Str.concat "A long enough string " "to be heap-allocated" + list = [s, s, s] + List.dropFirst list 1 + "# + ), + RocList>, + &[ + // Still has 3 refcounts cause the slice holds onto the list. + // So nothing in the list is freed yet. + Live(3), // s + Live(1) // result + ] + ); +} + #[test] #[cfg(feature = "gen-wasm")] fn list_str_dealloc() { diff --git a/crates/compiler/test_gen/src/helpers/wasm.rs b/crates/compiler/test_gen/src/helpers/wasm.rs index 148bd7f251..8919342033 100644 --- a/crates/compiler/test_gen/src/helpers/wasm.rs +++ b/crates/compiler/test_gen/src/helpers/wasm.rs @@ -310,7 +310,14 @@ where RefCount::Deallocated } else { // Dereference the RC pointer and decode its value from the negative number format - let rc_encoded = read_i32(&inst.memory, rc_ptr); + let mut rc_encoded = read_i32(&inst.memory, rc_ptr); + if rc_encoded > 0 { + // We happen to be reading a list that is refcounted. + // This is the size on heap. + // Shift over 4 to and load the real RC. + rc_encoded = read_i32(&inst.memory, rc_ptr + 4); + } + if rc_encoded == 0 { RefCount::Constant } else { diff --git a/crates/compiler/test_gen/src/helpers/wasm_test_platform.c b/crates/compiler/test_gen/src/helpers/wasm_test_platform.c index dc430d33c0..60b6e429e3 100644 --- a/crates/compiler/test_gen/src/helpers/wasm_test_platform.c +++ b/crates/compiler/test_gen/src/helpers/wasm_test_platform.c @@ -53,9 +53,11 @@ size_t *alloc_ptr_to_rc_ptr(void *ptr, unsigned int alignment) //-------------------------- +size_t RC_LIST_INDICATOR = 1; + void *roc_alloc(size_t size, unsigned int alignment) { - void *allocated = calloc(size, 1); + void *allocated = malloc(size); if (rc_pointers) { @@ -64,6 +66,7 @@ void *roc_alloc(size_t size, unsigned int alignment) ASSERT(num_alloc <= rc_pointers_capacity, "Too many allocations %zd > %zd", num_alloc, rc_pointers_capacity); size_t *rc_ptr = alloc_ptr_to_rc_ptr(allocated, alignment); + *rc_ptr = RC_LIST_INDICATOR; rc_pointers->elements[rc_pointers->length] = rc_ptr; rc_pointers->length++; }