make box decrement its contents when free'ing

This commit is contained in:
Folkert 2023-04-28 18:11:39 +02:00
parent 2ea69f07ef
commit 25d2d090e8
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 51 additions and 5 deletions

View file

@ -878,7 +878,14 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
let basic_type = basic_type_from_layout(env, layout_interner, boxed_layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_box_help(env, layout_interner, mode, inner_layout, function_value);
modify_refcount_box_help(
env,
layout_interner,
layout_ids,
mode,
inner_layout,
function_value,
);
function_value
}
@ -893,6 +900,7 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
fn modify_refcount_box_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
inner_layout: InLayout<'a>,
fn_val: FunctionValue<'ctx>,
@ -916,10 +924,49 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
let call_mode = mode_to_call_mode(fn_val, mode);
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
// this function returns void
builder.build_return(None);
match mode {
Mode::Inc => {
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
builder.build_return(None);
}
Mode::Dec => {
// if the box is unique, also decrement its inner value
let do_recurse_block = env.context.append_basic_block(fn_val, "do_recurse");
let no_recurse_block = env.context.append_basic_block(fn_val, "no_recurse");
builder.build_conditional_branch(
refcount_ptr.is_1(env),
do_recurse_block,
no_recurse_block,
);
{
env.builder.position_at_end(do_recurse_block);
let inner = load_roc_value(env, layout_interner, inner_layout, boxed, "inner");
modify_refcount_layout(
env,
layout_interner,
layout_ids,
call_mode,
inner,
inner_layout,
);
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
env.builder.build_return(None);
}
{
env.builder.position_at_end(no_recurse_block);
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
env.builder.build_return(None);
}
}
}
}
/// Build an increment or decrement function for a specific layout