Merge pull request #4851 from JTeeuwissen/main

replace borrowed boolean with ownership enum
This commit is contained in:
Folkert de Vries 2023-01-09 23:24:39 +01:00 committed by GitHub
commit 61a2091b27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 58 deletions

View file

@ -15,12 +15,22 @@ use roc_module::symbol::Symbol;
pub(crate) const OWNED: bool = false;
pub(crate) const BORROWED: bool = true;
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
/// means incrementing its reference count. Hence, we prefer borrowing for these types
fn should_borrow_layout(layout: &Layout) -> bool {
layout.is_refcounted()
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Ownership {
Owned,
Borrowed,
}
impl Ownership {
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
/// means incrementing its reference count. Hence, we prefer borrowing for these types
fn from_layout(layout: &Layout) -> Self {
match layout.is_refcounted() {
true => Ownership::Borrowed,
false => Ownership::Owned,
}
}
}
pub fn infer_borrow<'a>(
arena: &'a Bump,
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
@ -106,7 +116,7 @@ pub struct ParamOffset(usize);
impl From<ParamOffset> for usize {
fn from(id: ParamOffset) -> Self {
id.0 as usize
id.0
}
}
@ -220,7 +230,7 @@ impl<'a> ParamMap<'a> {
fn init_borrow_params(arena: &'a Bump, ps: &'a [Param<'a>]) -> &'a [Param<'a>] {
Vec::from_iter_in(
ps.iter().map(|p| Param {
borrow: p.layout.is_refcounted(),
ownership: Ownership::from_layout(&p.layout),
layout: p.layout,
symbol: p.symbol,
}),
@ -232,7 +242,7 @@ impl<'a> ParamMap<'a> {
fn init_borrow_args(arena: &'a Bump, ps: &'a [(Layout<'a>, Symbol)]) -> &'a [Param<'a>] {
Vec::from_iter_in(
ps.iter().map(|(layout, symbol)| Param {
borrow: should_borrow_layout(layout),
ownership: Ownership::from_layout(layout),
layout: *layout,
symbol: *symbol,
}),
@ -247,7 +257,7 @@ impl<'a> ParamMap<'a> {
) -> &'a [Param<'a>] {
Vec::from_iter_in(
ps.iter().map(|(layout, symbol)| Param {
borrow: false,
ownership: Ownership::Owned,
layout: *layout,
symbol: *symbol,
}),
@ -390,12 +400,12 @@ impl<'a> BorrowInfState<'a> {
fn update_param_map_help(&mut self, ps: &[Param<'a>]) -> &'a [Param<'a>] {
let mut new_ps = Vec::with_capacity_in(ps.len(), self.arena);
new_ps.extend(ps.iter().map(|p| {
if !p.borrow {
if p.ownership == Ownership::Owned {
*p
} else if self.is_owned(p.symbol) {
self.modified = true;
let mut p = *p;
p.borrow = false;
p.ownership = Ownership::Owned;
p
} else {
@ -412,15 +422,15 @@ impl<'a> BorrowInfState<'a> {
start: ParamOffset,
length: usize,
) {
let index: usize = start.into();
let ParamOffset(index) = start;
let ps = &mut param_map.declarations[index..][..length];
for p in ps.iter_mut() {
if !p.borrow {
if p.ownership == Ownership::Owned {
// do nothing
} else if self.is_owned(p.symbol) {
self.modified = true;
p.borrow = false;
p.ownership = Ownership::Owned;
} else {
// do nothing
}
@ -440,7 +450,7 @@ impl<'a> BorrowInfState<'a> {
debug_assert_eq!(xs.len(), ps.len());
for (x, p) in xs.iter().zip(ps.iter()) {
if !p.borrow {
if p.ownership == Ownership::Owned {
self.own_var(*x);
}
}
@ -568,44 +578,44 @@ impl<'a> BorrowInfState<'a> {
match op {
ListMap { xs } => {
// own the list if the function wants to own the element
if !function_ps[0].borrow {
if function_ps[0].ownership == Ownership::Owned {
self.own_var(*xs);
}
}
ListMap2 { xs, ys } => {
// own the lists if the function wants to own the element
if !function_ps[0].borrow {
if function_ps[0].ownership == Ownership::Owned {
self.own_var(*xs);
}
if !function_ps[1].borrow {
if function_ps[1].ownership == Ownership::Owned {
self.own_var(*ys);
}
}
ListMap3 { xs, ys, zs } => {
// own the lists if the function wants to own the element
if !function_ps[0].borrow {
if function_ps[0].ownership == Ownership::Owned {
self.own_var(*xs);
}
if !function_ps[1].borrow {
if function_ps[1].ownership == Ownership::Owned {
self.own_var(*ys);
}
if !function_ps[2].borrow {
if function_ps[2].ownership == Ownership::Owned {
self.own_var(*zs);
}
}
ListMap4 { xs, ys, zs, ws } => {
// own the lists if the function wants to own the element
if !function_ps[0].borrow {
if function_ps[0].ownership == Ownership::Owned {
self.own_var(*xs);
}
if !function_ps[1].borrow {
if function_ps[1].ownership == Ownership::Owned {
self.own_var(*ys);
}
if !function_ps[2].borrow {
if function_ps[2].ownership == Ownership::Owned {
self.own_var(*zs);
}
if !function_ps[3].borrow {
if function_ps[3].ownership == Ownership::Owned {
self.own_var(*ws);
}
}
@ -617,7 +627,9 @@ impl<'a> BorrowInfState<'a> {
// own the closure environment if the function needs to own it
let function_env_position = op.function_arity();
if let Some(false) = function_ps.get(function_env_position).map(|p| p.borrow) {
if let Some(Ownership::Owned) =
function_ps.get(function_env_position).map(|p| p.ownership)
{
self.own_var(passed_function.captured_environment);
}
}

View file

@ -2,6 +2,7 @@ use bumpalo::collections::vec::Vec;
use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, Symbol};
use crate::borrow::Ownership;
use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId,
};
@ -418,7 +419,7 @@ fn eq_tag_union_help<'a>(
} else {
let loop_params_iter = operands.iter().map(|arg| Param {
symbol: *arg,
borrow: true,
ownership: Ownership::Borrowed,
layout: Layout::Union(union_layout),
});
@ -718,13 +719,13 @@ fn eq_list<'a>(
let param_addr1 = Param {
symbol: addr1,
borrow: false,
ownership: Ownership::Owned,
layout: layout_isize,
};
let param_addr2 = Param {
symbol: addr2,
borrow: false,
ownership: Ownership::Owned,
layout: layout_isize,
};

View file

@ -6,6 +6,7 @@ use roc_module::low_level::{LowLevel, LowLevel::*};
use roc_module::symbol::{IdentIds, Symbol};
use roc_target::PtrWidth;
use crate::borrow::Ownership;
use crate::code_gen_help::let_lowlevel;
use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
@ -944,7 +945,7 @@ fn refcount_list_elems<'a>(
let param_addr = Param {
symbol: addr,
borrow: false,
ownership: Ownership::Owned,
layout: layout_isize,
};
@ -1602,7 +1603,7 @@ fn refcount_union_tailrec<'a>(
let jp_param = Param {
symbol: next_ptr,
borrow: true,
ownership: Ownership::Borrowed,
layout,
};
@ -1622,7 +1623,7 @@ fn refcount_union_tailrec<'a>(
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
let loop_param = Param {
symbol: current,
borrow: true,
ownership: Ownership::Borrowed,
layout: Layout::Union(union_layout),
};

View file

@ -347,7 +347,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
for Param {
symbol,
layout,
borrow: _,
ownership: _,
} in parameters
{
ctx.insert(*symbol, *layout);
@ -369,7 +369,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
for (arg, param) in symbols.iter().zip(parameters.iter()) {
let Param {
symbol: _,
borrow: _,
ownership: _,
layout,
} = param;
self.check_sym_layout(*arg, *layout, UseKind::JumpArg);

View file

@ -1,3 +1,4 @@
use crate::borrow::Ownership;
use crate::ir::{
build_list_index_probe, BranchInfo, Call, CallType, DestructType, Env, Expr, JoinPointId,
ListIndex, Literal, Param, Pattern, Procs, Stmt,
@ -1906,7 +1907,7 @@ fn decide_to_branching<'a>(
let param = Param {
symbol: test_symbol,
layout: Layout::Builtin(Builtin::Bool),
borrow: false,
ownership: Ownership::Owned,
};
let join = Stmt::Join {

View file

@ -1,4 +1,4 @@
use crate::borrow::{ParamMap, BORROWED, OWNED};
use crate::borrow::{Ownership, ParamMap, BORROWED, OWNED};
use crate::ir::{
CallType, Expr, HigherOrderLowLevel, JoinPointId, ModifyRc, Param, Proc, ProcLayout, Stmt,
UpdateModeIds,
@ -61,13 +61,13 @@ impl DataFunction {
use DataFunction::*;
let data_borrowed = !vars[&lowlevel_argument].consume;
let function_borrows = passed_function_argument.borrow;
let function_ownership = passed_function_argument.ownership;
match (data_borrowed, function_borrows) {
(BORROWED, BORROWED) => DataBorrowedFunctionBorrows,
(BORROWED, OWNED) => DataBorrowedFunctionOwns,
(OWNED, BORROWED) => DataOwnedFunctionBorrows,
(OWNED, OWNED) => DataOwnedFunctionOwns,
match (data_borrowed, function_ownership) {
(BORROWED, Ownership::Borrowed) => DataBorrowedFunctionBorrows,
(BORROWED, Ownership::Owned) => DataBorrowedFunctionOwns,
(OWNED, Ownership::Borrowed) => DataOwnedFunctionBorrows,
(OWNED, Ownership::Owned) => DataOwnedFunctionOwns,
}
}
}
@ -302,7 +302,10 @@ where
fn is_borrow_param(x: Symbol, ys: &[Symbol], ps: &[Param]) -> bool {
// default to owned arguments
let is_owned = |i: usize| match ps.get(i) {
Some(param) => !param.borrow,
Some(param) => match param.ownership {
Ownership::Owned => true,
Ownership::Borrowed => false,
},
None => unreachable!("or?"),
};
is_borrow_param_help(x, ys, is_owned)
@ -473,7 +476,10 @@ impl<'a, 'i> Context<'a, 'i> {
) -> &'a Stmt<'a> {
// default to owned arguments
let pred = |i: usize| match ps.get(i) {
Some(param) => !param.borrow,
Some(param) => match param.ownership {
Ownership::Owned => true,
Ownership::Borrowed => false,
},
None => unreachable!("or?"),
};
self.add_inc_before_help(xs, pred, b, live_vars_after)
@ -992,7 +998,10 @@ impl<'a, 'i> Context<'a, 'i> {
for p in ps.iter() {
let info = VarInfo {
reference: p.layout.contains_refcounted(self.layout_interner),
consume: !p.borrow,
consume: match p.ownership {
Ownership::Owned => true,
Ownership::Borrowed => false,
},
persistent: false,
reset: false,
};
@ -1014,7 +1023,7 @@ impl<'a, 'i> Context<'a, 'i> {
b_live_vars: &LiveVarSet,
) -> &'a Stmt<'a> {
for p in ps.iter() {
if !p.borrow
if p.ownership == Ownership::Owned
&& p.layout.contains_refcounted(self.layout_interner)
&& !b_live_vars.contains(&p.symbol)
{
@ -1334,7 +1343,7 @@ fn create_holl_call<'a>(
arguments: &'a [Symbol],
) -> Expr<'a> {
let call = crate::ir::Call {
call_type: if let Some(OWNED) = param.map(|p| p.borrow) {
call_type: if let Some(Ownership::Owned) = param.map(|p| p.ownership) {
let mut passed_function = holl.passed_function;
passed_function.owns_captured_environment = true;
@ -1519,7 +1528,7 @@ fn visit_proc<'a, 'i>(
None => Vec::from_iter_in(
proc.args.iter().cloned().map(|(layout, symbol)| Param {
symbol,
borrow: false,
ownership: Ownership::Owned,
layout,
}),
arena,

View file

@ -1,5 +1,6 @@
#![allow(clippy::manual_map)]
use crate::borrow::Ownership;
use crate::layout::{
self, Builtin, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName, LambdaSet,
Layout, LayoutCache, LayoutInterner, LayoutProblem, Niche, RawFunctionLayout, STLayoutInterner,
@ -1525,14 +1526,14 @@ pub struct JoinPointId(pub Symbol);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Param<'a> {
pub symbol: Symbol,
pub borrow: bool,
pub ownership: Ownership,
pub layout: Layout<'a>,
}
impl<'a> Param<'a> {
pub const EMPTY: Self = Param {
symbol: Symbol::EMPTY_PARAM,
borrow: false,
ownership: Ownership::Owned,
layout: Layout::UNIT,
};
}
@ -4545,7 +4546,7 @@ pub fn with_hole<'a>(
let param = Param {
symbol: assigned,
layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {
@ -4610,7 +4611,7 @@ pub fn with_hole<'a>(
let param = Param {
symbol: assigned,
layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {
@ -10402,7 +10403,7 @@ where
let param = Param {
symbol: assigned,
layout: return_layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {
@ -10626,7 +10627,7 @@ fn union_lambda_set_to_switch<'a>(
let param = Param {
symbol: assigned,
layout: *return_layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {
@ -10777,7 +10778,7 @@ fn enum_lambda_set_to_switch<'a>(
let param = Param {
symbol: assigned,
layout: *return_layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {
@ -10880,7 +10881,7 @@ where
let param = Param {
symbol: assigned,
layout: return_layout,
borrow: false,
ownership: Ownership::Owned,
};
Stmt::Join {

View file

@ -1,5 +1,6 @@
#![allow(clippy::manual_map)]
use crate::borrow::Ownership;
use crate::ir::{CallType, Expr, JoinPointId, Param, Stmt};
use crate::layout::{LambdaName, Layout};
use bumpalo::collections::Vec;
@ -46,7 +47,7 @@ pub fn make_tail_recursive<'a>(
args.iter().map(|(layout, symbol, _)| Param {
symbol: *symbol,
layout: *layout,
borrow: true,
ownership: Ownership::Borrowed,
}),
arena,
)