Reduce code size for Union refcount procedures

This commit is contained in:
Brian Carroll 2022-01-06 09:27:37 +00:00
parent d9cc3c5692
commit 040b8ce430

View file

@ -867,6 +867,7 @@ fn refcount_union_contents<'a>(
tag_id_layout: Layout<'a>, tag_id_layout: Layout<'a>,
modify_union_stmt: Stmt<'a>, modify_union_stmt: Stmt<'a>,
) -> Stmt<'a> { ) -> Stmt<'a> {
let jp_modify_union = JoinPointId(root.create_symbol(ident_ids, "jp_modify_union"));
let mut tag_branches = Vec::with_capacity_in(tag_layouts.len() + 1, root.arena); let mut tag_branches = Vec::with_capacity_in(tag_layouts.len() + 1, root.arena);
if let Some(id) = null_id { if let Some(id) = null_id {
@ -883,6 +884,10 @@ fn refcount_union_contents<'a>(
_ => {} _ => {}
} }
// After refcounting the fields, jump to modify the union itself
// (Order is important, to avoid use-after-free for Dec)
let following = Stmt::Jump(jp_modify_union, &[]);
let fields_stmt = refcount_tag_fields( let fields_stmt = refcount_tag_fields(
root, root,
ident_ids, ident_ids,
@ -891,7 +896,7 @@ fn refcount_union_contents<'a>(
field_layouts, field_layouts,
structure, structure,
tag_id, tag_id,
modify_union_stmt.clone(), // TODO: Use a jump, this is a bit bloated following,
); );
tag_branches.push((tag_id as u64, BranchInfo::None, fields_stmt)); tag_branches.push((tag_id as u64, BranchInfo::None, fields_stmt));
@ -901,12 +906,19 @@ fn refcount_union_contents<'a>(
let default_stmt: Stmt<'a> = tag_branches.pop().unwrap().2; let default_stmt: Stmt<'a> = tag_branches.pop().unwrap().2;
Stmt::Switch { let tag_id_switch = Stmt::Switch {
cond_symbol: tag_id_sym, cond_symbol: tag_id_sym,
cond_layout: tag_id_layout, cond_layout: tag_id_layout,
branches: tag_branches.into_bump_slice(), branches: tag_branches.into_bump_slice(),
default_branch: (BranchInfo::None, root.arena.alloc(default_stmt)), default_branch: (BranchInfo::None, root.arena.alloc(default_stmt)),
ret_layout: LAYOUT_UNIT, ret_layout: LAYOUT_UNIT,
};
Stmt::Join {
id: jp_modify_union,
parameters: &[],
body: root.arena.alloc(modify_union_stmt),
remainder: root.arena.alloc(tag_id_switch),
} }
} }