mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 16:51:53 +03:00
mono: generate refcounting helper functions for Boxed layout
This commit is contained in:
parent
7c7e450756
commit
6b1e9c75c8
@ -76,7 +76,7 @@ pub fn insert_wrapper_for_layout<'a>(
|
||||
bool::insert_wrapper(arena, module, wrapper_name, main_fn_index);
|
||||
}
|
||||
Layout::Union(UnionLayout::NonRecursive(_)) => stack_data_structure(),
|
||||
Layout::Union(_) => {
|
||||
Layout::Union(_) | Layout::Boxed(_) => {
|
||||
i32::insert_wrapper(arena, module, wrapper_name, main_fn_index);
|
||||
}
|
||||
_ => stack_data_structure(),
|
||||
|
@ -129,7 +129,9 @@ pub fn refcount_generic<'a>(
|
||||
Layout::RecursivePointer => unreachable!(
|
||||
"We should never call a refcounting helper on a RecursivePointer layout directly"
|
||||
),
|
||||
Layout::Boxed(_) => rc_todo(),
|
||||
Layout::Boxed(inner_layout) => {
|
||||
refcount_boxed(root, ident_ids, ctx, &layout, inner_layout, structure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +345,7 @@ pub fn is_rc_implemented_yet(layout: &Layout) -> bool {
|
||||
is_rc_implemented_yet(&lambda_set.runtime_representation())
|
||||
}
|
||||
Layout::RecursivePointer => true,
|
||||
Layout::Boxed(_) => false,
|
||||
Layout::Boxed(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1465,3 +1467,66 @@ fn refcount_tag_fields<'a>(
|
||||
|
||||
stmt
|
||||
}
|
||||
|
||||
fn refcount_boxed<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
ctx: &mut Context<'a>,
|
||||
layout: &Layout,
|
||||
inner_layout: &'a Layout,
|
||||
outer: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
let arena = root.arena;
|
||||
|
||||
//
|
||||
// modify refcount of the inner and outer structures
|
||||
// RC on inner first, to avoid use-after-free for Dec
|
||||
// We're defining statements in reverse, so define outer first
|
||||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = layout.alignment_bytes(root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_outer = modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
alignment,
|
||||
arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
let get_rc_and_modify_outer = rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
outer,
|
||||
rc_ptr,
|
||||
false,
|
||||
arena.alloc(modify_outer),
|
||||
);
|
||||
|
||||
if inner_layout.is_refcounted() && !ctx.op.is_decref() {
|
||||
let inner = root.create_symbol(ident_ids, "inner");
|
||||
let inner_expr = Expr::ExprUnbox { symbol: outer };
|
||||
|
||||
let mod_inner_unit = root.create_symbol(ident_ids, "mod_inner_unit");
|
||||
let mod_inner_args = refcount_args(root, ctx, inner);
|
||||
let mod_inner_expr = root
|
||||
.call_specialized_op(ident_ids, ctx, *inner_layout, mod_inner_args)
|
||||
.unwrap();
|
||||
|
||||
Stmt::Let(
|
||||
inner,
|
||||
inner_expr,
|
||||
*inner_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
mod_inner_unit,
|
||||
mod_inner_expr,
|
||||
LAYOUT_UNIT,
|
||||
arena.alloc(get_rc_and_modify_outer),
|
||||
)),
|
||||
)
|
||||
} else {
|
||||
get_rc_and_modify_outer
|
||||
}
|
||||
}
|
||||
|
@ -431,3 +431,46 @@ fn union_linked_list_long_dec() {
|
||||
&[Deallocated; 1_000]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-wasm"))]
|
||||
fn boxed_str_inc() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
b = Box.box s
|
||||
|
||||
Tuple b b
|
||||
"#
|
||||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(2), // s
|
||||
Live(2), // b
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-wasm"))]
|
||||
fn boxed_str_dec() {
|
||||
assert_refcounts!(
|
||||
indoc!(
|
||||
r#"
|
||||
s = Str.concat "A long enough string " "to be heap-allocated"
|
||||
b = Box.box s
|
||||
|
||||
if False then
|
||||
ReturnTheBox b
|
||||
else
|
||||
DeallocateEverything
|
||||
"#
|
||||
),
|
||||
(i32, i32),
|
||||
&[
|
||||
Deallocated, // s
|
||||
Deallocated, // b
|
||||
]
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user