mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
use Box instead of a tag to read the refcount
This commit is contained in:
parent
ca7ba45955
commit
a61e7a696d
2 changed files with 86 additions and 30 deletions
|
@ -41,6 +41,10 @@ impl HelperOp {
|
||||||
fn is_decref(&self) -> bool {
|
fn is_decref(&self) -> bool {
|
||||||
matches!(self, Self::DecRef(_))
|
matches!(self, Self::DecRef(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_dec(&self) -> bool {
|
||||||
|
matches!(self, Self::Dec)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -81,7 +85,6 @@ pub struct CodeGenHelp<'a> {
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
target_info: TargetInfo,
|
target_info: TargetInfo,
|
||||||
layout_isize: InLayout<'a>,
|
layout_isize: InLayout<'a>,
|
||||||
union_refcount: UnionLayout<'a>,
|
|
||||||
specializations: Vec<'a, Specialization<'a>>,
|
specializations: Vec<'a, Specialization<'a>>,
|
||||||
debug_recursion_depth: usize,
|
debug_recursion_depth: usize,
|
||||||
}
|
}
|
||||||
|
@ -90,15 +93,11 @@ impl<'a> CodeGenHelp<'a> {
|
||||||
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self {
|
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self {
|
||||||
let layout_isize = Layout::isize(target_info);
|
let layout_isize = Layout::isize(target_info);
|
||||||
|
|
||||||
// Refcount is a boxed isize. TODO: use the new Box layout when dev backends support it
|
|
||||||
let union_refcount = UnionLayout::NonNullableUnwrapped(arena.alloc([layout_isize]));
|
|
||||||
|
|
||||||
CodeGenHelp {
|
CodeGenHelp {
|
||||||
arena,
|
arena,
|
||||||
home,
|
home,
|
||||||
target_info,
|
target_info,
|
||||||
layout_isize,
|
layout_isize,
|
||||||
union_refcount,
|
|
||||||
specializations: Vec::with_capacity_in(16, arena),
|
specializations: Vec::with_capacity_in(16, arena),
|
||||||
debug_recursion_depth: 0,
|
debug_recursion_depth: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,56 @@ pub fn refcount_generic<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn if_unique<'a>(
|
||||||
|
root: &mut CodeGenHelp<'a>,
|
||||||
|
ident_ids: &mut IdentIds,
|
||||||
|
value: Symbol,
|
||||||
|
when_unique: impl FnOnce(JoinPointId) -> Stmt<'a>,
|
||||||
|
when_done: Stmt<'a>,
|
||||||
|
) -> Stmt<'a> {
|
||||||
|
// joinpoint f =
|
||||||
|
// <when_done>
|
||||||
|
// in
|
||||||
|
// if is_unique <value> then
|
||||||
|
// <when_unique>(f)
|
||||||
|
// else
|
||||||
|
// jump f
|
||||||
|
|
||||||
|
let joinpoint = root.create_symbol(ident_ids, "is_unique_joinpoint");
|
||||||
|
let joinpoint = JoinPointId(joinpoint);
|
||||||
|
|
||||||
|
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||||
|
|
||||||
|
let mut stmt = Stmt::Switch {
|
||||||
|
cond_symbol: is_unique,
|
||||||
|
cond_layout: Layout::BOOL,
|
||||||
|
branches: root
|
||||||
|
.arena
|
||||||
|
.alloc([(true as _, BranchInfo::None, when_unique(joinpoint))]),
|
||||||
|
default_branch: (
|
||||||
|
BranchInfo::None,
|
||||||
|
root.arena.alloc(Stmt::Jump(joinpoint, &[])),
|
||||||
|
),
|
||||||
|
ret_layout: Layout::UNIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
stmt = Stmt::Join {
|
||||||
|
id: joinpoint,
|
||||||
|
parameters: &[],
|
||||||
|
body: root.arena.alloc(when_done),
|
||||||
|
remainder: root.arena.alloc(stmt),
|
||||||
|
};
|
||||||
|
|
||||||
|
let_lowlevel(
|
||||||
|
root.arena,
|
||||||
|
root.layout_isize,
|
||||||
|
is_unique,
|
||||||
|
LowLevel::RefCountIsUnique,
|
||||||
|
&[value],
|
||||||
|
root.arena.alloc(stmt),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn refcount_reset_proc_body<'a>(
|
pub fn refcount_reset_proc_body<'a>(
|
||||||
root: &mut CodeGenHelp<'a>,
|
root: &mut CodeGenHelp<'a>,
|
||||||
ident_ids: &mut IdentIds,
|
ident_ids: &mut IdentIds,
|
||||||
|
@ -348,12 +398,8 @@ pub fn refcount_reset_proc_body<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Refcount value
|
// Refcount value
|
||||||
let rc_expr = Expr::UnionAtIndex {
|
let rc_expr = Expr::ExprUnbox { symbol: rc_ptr };
|
||||||
structure: rc_ptr,
|
|
||||||
tag_id: 0,
|
|
||||||
union_layout: root.union_refcount,
|
|
||||||
index: 0,
|
|
||||||
};
|
|
||||||
let rc_stmt = Stmt::Let(
|
let rc_stmt = Stmt::Let(
|
||||||
rc,
|
rc,
|
||||||
rc_expr,
|
rc_expr,
|
||||||
|
@ -361,6 +407,9 @@ pub fn refcount_reset_proc_body<'a>(
|
||||||
root.arena.alloc(refcount_1_stmt),
|
root.arena.alloc(refcount_1_stmt),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// a Box never masks bits
|
||||||
|
let mask_lower_bits = false;
|
||||||
|
|
||||||
// Refcount pointer
|
// Refcount pointer
|
||||||
let rc_ptr_stmt = {
|
let rc_ptr_stmt = {
|
||||||
rc_ptr_from_data_ptr_help(
|
rc_ptr_from_data_ptr_help(
|
||||||
|
@ -368,7 +417,7 @@ pub fn refcount_reset_proc_body<'a>(
|
||||||
ident_ids,
|
ident_ids,
|
||||||
structure,
|
structure,
|
||||||
rc_ptr,
|
rc_ptr,
|
||||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
mask_lower_bits,
|
||||||
root.arena.alloc(rc_stmt),
|
root.arena.alloc(rc_stmt),
|
||||||
addr,
|
addr,
|
||||||
recursion_ptr,
|
recursion_ptr,
|
||||||
|
@ -508,12 +557,8 @@ pub fn refcount_resetref_proc_body<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Refcount value
|
// Refcount value
|
||||||
let rc_expr = Expr::UnionAtIndex {
|
let rc_expr = Expr::ExprUnbox { symbol: rc_ptr };
|
||||||
structure: rc_ptr,
|
|
||||||
tag_id: 0,
|
|
||||||
union_layout: root.union_refcount,
|
|
||||||
index: 0,
|
|
||||||
};
|
|
||||||
let rc_stmt = Stmt::Let(
|
let rc_stmt = Stmt::Let(
|
||||||
rc,
|
rc,
|
||||||
rc_expr,
|
rc_expr,
|
||||||
|
@ -521,6 +566,9 @@ pub fn refcount_resetref_proc_body<'a>(
|
||||||
root.arena.alloc(refcount_1_stmt),
|
root.arena.alloc(refcount_1_stmt),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// a Box never masks bits
|
||||||
|
let mask_lower_bits = false;
|
||||||
|
|
||||||
// Refcount pointer
|
// Refcount pointer
|
||||||
let rc_ptr_stmt = {
|
let rc_ptr_stmt = {
|
||||||
rc_ptr_from_data_ptr_help(
|
rc_ptr_from_data_ptr_help(
|
||||||
|
@ -528,7 +576,7 @@ pub fn refcount_resetref_proc_body<'a>(
|
||||||
ident_ids,
|
ident_ids,
|
||||||
structure,
|
structure,
|
||||||
rc_ptr,
|
rc_ptr,
|
||||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
mask_lower_bits,
|
||||||
root.arena.alloc(rc_stmt),
|
root.arena.alloc(rc_stmt),
|
||||||
addr,
|
addr,
|
||||||
recursion_ptr,
|
recursion_ptr,
|
||||||
|
@ -1813,7 +1861,8 @@ fn refcount_boxed<'a>(
|
||||||
Layout::OPAQUE_PTR,
|
Layout::OPAQUE_PTR,
|
||||||
);
|
);
|
||||||
|
|
||||||
if layout_interner.is_refcounted(inner_layout) && !ctx.op.is_decref() {
|
// decrement the inner value if the operation is a decrement and the box itself is unique
|
||||||
|
if layout_interner.is_refcounted(inner_layout) && ctx.op.is_dec() {
|
||||||
let inner = root.create_symbol(ident_ids, "inner");
|
let inner = root.create_symbol(ident_ids, "inner");
|
||||||
let inner_expr = Expr::ExprUnbox { symbol: outer };
|
let inner_expr = Expr::ExprUnbox { symbol: outer };
|
||||||
|
|
||||||
|
@ -1829,16 +1878,24 @@ fn refcount_boxed<'a>(
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Stmt::Let(
|
if_unique(
|
||||||
inner,
|
root,
|
||||||
inner_expr,
|
ident_ids,
|
||||||
inner_layout,
|
outer,
|
||||||
arena.alloc(Stmt::Let(
|
|id| {
|
||||||
mod_inner_unit,
|
Stmt::Let(
|
||||||
mod_inner_expr,
|
inner,
|
||||||
LAYOUT_UNIT,
|
inner_expr,
|
||||||
arena.alloc(get_rc_and_modify_outer),
|
inner_layout,
|
||||||
)),
|
arena.alloc(Stmt::Let(
|
||||||
|
mod_inner_unit,
|
||||||
|
mod_inner_expr,
|
||||||
|
LAYOUT_UNIT,
|
||||||
|
arena.alloc(Stmt::Jump(id, &[])),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
get_rc_and_modify_outer,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
get_rc_and_modify_outer
|
get_rc_and_modify_outer
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue