start resetref

This commit is contained in:
J.Teeuwissen 2023-03-29 11:57:13 +02:00
parent 61efec6fe2
commit d4ed6f7778
No known key found for this signature in database
GPG key ID: DB5F7A1ED8D478AD
13 changed files with 214 additions and 18 deletions

View file

@ -707,7 +707,7 @@ impl<'a> BorrowInfState<'a> {
self.if_is_owned_then_own(z, *x);
}
Reset { symbol: x, .. } => {
Reset { symbol: x, .. } | ResetRef { symbol: x, .. } => {
self.own_var(z);
self.own_var(*x);
}

View file

@ -31,6 +31,8 @@ pub enum HelperOp {
Dec,
DecRef(JoinPointId),
Reset,
// TODO update all usages
ResetRef,
Eq,
}
@ -272,7 +274,7 @@ impl<'a> CodeGenHelp<'a> {
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
match ctx.op {
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
Reset => (layout, self.arena.alloc([layout])),
Reset | ResetRef => (layout, self.arena.alloc([layout])),
Inc => (LAYOUT_UNIT, self.arena.alloc([arg, self.layout_isize])),
Eq => (LAYOUT_BOOL, self.arena.alloc([arg, arg])),
}
@ -346,7 +348,7 @@ impl<'a> CodeGenHelp<'a> {
Symbol::ARG_1,
),
),
Reset => (
Reset | ResetRef => (
layout,
refcount::refcount_reset_proc_body(
self,
@ -370,7 +372,7 @@ impl<'a> CodeGenHelp<'a> {
let inc_amount = (self.layout_isize, ARG_2);
self.arena.alloc([roc_value, inc_amount])
}
Dec | DecRef(_) | Reset => self.arena.alloc([roc_value]),
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
}
};
@ -421,6 +423,7 @@ impl<'a> CodeGenHelp<'a> {
niche: Niche::NONE,
},
HelperOp::DecRef(_) => unreachable!("No generated Proc for DecRef"),
HelperOp::ResetRef => unreachable!("No generated Proc for ResetRef"),
HelperOp::Eq => ProcLayout {
arguments: self.arena.alloc([layout, layout]),
result: LAYOUT_BOOL,

View file

@ -464,6 +464,10 @@ impl<'a, 'r> Ctx<'a, 'r> {
&Expr::Reset {
symbol,
update_mode: _,
}
| &Expr::ResetRef {
symbol,
update_mode: _,
} => {
self.check_sym_exists(symbol);
None

View file

@ -310,7 +310,14 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
update_mode_id: update_mode_ids.next_id(),
};
environment.push_reuse_token(&layout_clone, reuse_token);
Some((layout_clone, *symbol, reuse_token))
let dec_ref = match rc {
ModifyRc::Dec(_) => false,
ModifyRc::DecRef(_) => true,
_ => unreachable!(),
};
Some((layout_clone, *symbol, reuse_token, dec_ref))
}
_ => None,
}
@ -328,7 +335,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
);
// If we inserted a reuse token, we need to insert a reset reuse operation if the reuse token is consumed.
if let Some((layout, symbol, reuse_token)) = reuse_pair {
if let Some((layout, symbol, reuse_token, dec_ref)) = reuse_pair {
let stack_reuse_token = environment.peek_reuse_token(&layout);
match stack_reuse_token {
@ -340,9 +347,17 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
_ => {
// The token we inserted is no longer on the stack, it must have been consumed.
// So we need to insert a reset operation.
let reset_expr = Expr::Reset {
symbol,
update_mode: reuse_token.update_mode_id,
let reset_expr = match dec_ref {
// A decref will be replaced by a resetref.
true => Expr::ResetRef {
symbol,
update_mode: reuse_token.update_mode_id,
},
// And a dec will be replaced by a reset.
false => Expr::Reset {
symbol,
update_mode: reuse_token.update_mode_id,
},
};
// If we generate a reuse token, we no longer want to use the drop statement anymore. So we just return the reset expression.

View file

@ -205,7 +205,7 @@ pub fn occurring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
result.extend(arguments.iter().copied());
result.insert(*symbol);
}
Reset { symbol: x, .. } => {
Reset { symbol: x, .. } | ResetRef { symbol: x, .. } => {
result.insert(*x);
}
@ -945,7 +945,7 @@ impl<'a, 'i> Context<'a, 'i> {
self.arena.alloc(Stmt::Let(z, v, l, b))
}
EmptyArray | Literal(_) | Reset { .. } | RuntimeErrorFunction(_) => {
EmptyArray | Literal(_) | Reset { .. } | ResetRef { .. } | RuntimeErrorFunction(_) => {
// EmptyArray is always stack-allocated function pointers are persistent
self.arena.alloc(Stmt::Let(z, v, l, b))
}

View file

@ -1935,6 +1935,13 @@ pub enum Expr<'a> {
update_mode: UpdateModeId,
},
// Just like Reset, but does not recursively decrement the children.
// Used in reuse analysis to replace a decref with a resetRef to avoid decrementing when the dec ref didn't.
ResetRef {
symbol: Symbol,
update_mode: UpdateModeId,
},
RuntimeErrorFunction(&'a str),
}
@ -2057,7 +2064,13 @@ impl<'a> Expr<'a> {
"Reset {{ symbol: {:?}, id: {} }}",
symbol, update_mode.id
)),
ResetRef {
symbol,
update_mode,
} => alloc.text(format!(
"ResetRef {{ symbol: {:?}, id: {} }}",
symbol, update_mode.id
)),
Struct(args) => {
let it = args.iter().map(|s| symbol_to_doc(alloc, *s, pretty));
@ -7187,7 +7200,9 @@ fn substitute_in_expr<'a>(
}
}
Reuse { .. } | Reset { .. } => unreachable!("reset/reuse have not been introduced yet"),
Reuse { .. } | Reset { .. } | ResetRef { .. } => {
unreachable!("reset/resetref/reuse have not been introduced yet")
}
Struct(args) => {
let mut did_change = false;

View file

@ -427,8 +427,8 @@ impl VariableUsage {
borrowed: MutSet::default(),
}
}
Expr::Reuse { .. } | Expr::Reset { .. } => {
unreachable!("Reset and reuse should not exist at this point")
Expr::Reuse { .. } | Expr::Reset { .. } | Expr::ResetRef { .. } => {
unreachable!("Reset(ref) and reuse should not exist at this point")
}
}
}

View file

@ -326,6 +326,7 @@ fn insert_reset<'a>(
| EmptyArray
| Reuse { .. }
| Reset { .. }
| ResetRef { .. }
| RuntimeErrorFunction(_) => break,
}
}
@ -862,7 +863,7 @@ fn has_live_var_expr<'a>(expr: &'a Expr<'a>, needle: Symbol) -> bool {
Expr::Reuse {
symbol, arguments, ..
} => needle == *symbol || arguments.iter().any(|s| *s == needle),
Expr::Reset { symbol, .. } => needle == *symbol,
Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => needle == *symbol,
Expr::ExprBox { symbol, .. } => needle == *symbol,
Expr::ExprUnbox { symbol, .. } => needle == *symbol,
Expr::RuntimeErrorFunction(_) => false,