Subs efficiency

This commit is contained in:
Folkert 2021-03-22 02:04:59 +01:00
parent 7bb367713c
commit 41e61ba38a
3 changed files with 50 additions and 44 deletions

View file

@ -880,7 +880,7 @@ fn check_for_infinite_type(
let var = loc_var.value; let var = loc_var.value;
let is_uniq_infer = matches!( let is_uniq_infer = matches!(
subs.get(var).content, subs.get_ref(var).content,
Content::Alias(Symbol::ATTR_ATTR, _, _) Content::Alias(Symbol::ATTR_ATTR, _, _)
); );
@ -1088,7 +1088,7 @@ fn generalize(
for vars in all_but_last_pool { for vars in all_but_last_pool {
for &var in vars { for &var in vars {
if !subs.redundant(var) { if !subs.redundant(var) {
let rank = subs.get(var).rank; let rank = subs.get_rank(var);
pools.get_mut(rank).push(var); pools.get_mut(rank).push(var);
} }
@ -1099,13 +1099,12 @@ fn generalize(
// otherwise generalize // otherwise generalize
for &var in last_pool { for &var in last_pool {
if !subs.redundant(var) { if !subs.redundant(var) {
let mut desc = subs.get(var); let desc_rank = subs.get_rank(var);
if desc.rank < young_rank { if desc_rank < young_rank {
pools.get_mut(desc.rank).push(var); pools.get_mut(desc_rank).push(var);
} else { } else {
desc.rank = Rank::NONE; subs.set_rank(var, Rank::NONE);
subs.set(var, desc);
} }
} }
} }
@ -1121,18 +1120,8 @@ fn pool_to_rank_table(
// Sort the variables into buckets by rank. // Sort the variables into buckets by rank.
for &var in young_vars.iter() { for &var in young_vars.iter() {
let desc = subs.get(var); let rank = subs.get_rank(var);
let rank = desc.rank; subs.set_mark(var, young_mark);
subs.set(
var,
Descriptor {
rank,
mark: young_mark,
content: desc.content,
copy: desc.copy,
},
);
debug_assert!(rank.into_usize() < young_rank.into_usize() + 1); debug_assert!(rank.into_usize() < young_rank.into_usize() + 1);
pools.get_mut(rank).push(var); pools.get_mut(rank).push(var);
@ -1155,24 +1144,15 @@ fn adjust_rank(
if desc.mark == young_mark { if desc.mark == young_mark {
let Descriptor { let Descriptor {
content, content,
rank, rank: _,
mark: _, mark: _,
copy, copy,
} = desc; } = desc;
// Mark the variable as visited before adjusting content, as it may be cyclic. // Mark the variable as visited before adjusting content, as it may be cyclic.
subs.set( subs.set_mark(var, visit_mark);
var,
Descriptor {
content: content.clone(),
rank,
mark: visit_mark,
copy,
},
);
let max_rank = let max_rank = adjust_rank_content(subs, young_mark, visit_mark, group_rank, &content);
adjust_rank_content(subs, young_mark, visit_mark, group_rank, content.clone());
subs.set( subs.set(
var, var,
@ -1208,7 +1188,7 @@ fn adjust_rank_content(
young_mark: Mark, young_mark: Mark,
visit_mark: Mark, visit_mark: Mark,
group_rank: Rank, group_rank: Rank,
content: Content, content: &Content,
) -> Rank { ) -> Rank {
use roc_types::subs::Content::*; use roc_types::subs::Content::*;
use roc_types::subs::FlatType::*; use roc_types::subs::FlatType::*;
@ -1224,14 +1204,15 @@ fn adjust_rank_content(
let mut rank = Rank::toplevel(); let mut rank = Rank::toplevel();
for var in args { for var in args {
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank =
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
} }
rank rank
} }
Func(arg_vars, closure_var, ret_var) => { Func(arg_vars, closure_var, ret_var) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ret_var); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ret_var);
// TODO investigate further. // TODO investigate further.
// //
@ -1244,12 +1225,13 @@ fn adjust_rank_content(
young_mark, young_mark,
visit_mark, visit_mark,
group_rank, group_rank,
closure_var, *closure_var,
)); ));
} }
for var in arg_vars { for var in arg_vars {
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank =
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
} }
rank rank
@ -1263,7 +1245,7 @@ fn adjust_rank_content(
EmptyTagUnion => Rank::toplevel(), EmptyTagUnion => Rank::toplevel(),
Record(fields, ext_var) => { Record(fields, ext_var) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ext_var); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
for (_, var) in fields { for (_, var) in fields {
rank = rank.max(adjust_rank( rank = rank.max(adjust_rank(
@ -1279,7 +1261,7 @@ fn adjust_rank_content(
} }
TagUnion(tags, ext_var) => { TagUnion(tags, ext_var) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ext_var); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
for var in tags.values().flatten() { for var in tags.values().flatten() {
rank = rank =
@ -1290,9 +1272,9 @@ fn adjust_rank_content(
} }
RecursiveTagUnion(rec_var, tags, ext_var) => { RecursiveTagUnion(rec_var, tags, ext_var) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, rec_var); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *rec_var);
rank = rank.max(adjust_rank( rank = rank.max(adjust_rank(
subs, young_mark, visit_mark, group_rank, ext_var, subs, young_mark, visit_mark, group_rank, *ext_var,
)); ));
for var in tags.values().flatten() { for var in tags.values().flatten() {
@ -1305,10 +1287,11 @@ fn adjust_rank_content(
Boolean(Bool::Shared) => Rank::toplevel(), Boolean(Bool::Shared) => Rank::toplevel(),
Boolean(Bool::Container(cvar, mvars)) => { Boolean(Bool::Container(cvar, mvars)) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, cvar); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *cvar);
for var in mvars { for var in mvars {
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank =
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
} }
rank rank
@ -1322,13 +1305,13 @@ fn adjust_rank_content(
let mut rank = Rank::toplevel(); let mut rank = Rank::toplevel();
for (_, var) in args { for (_, var) in args {
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
} }
// from elm-compiler: THEORY: anything in the real_var would be Rank::toplevel() // from elm-compiler: THEORY: anything in the real_var would be Rank::toplevel()
// this theory is not true in Roc! aliases of function types capture the closure var // this theory is not true in Roc! aliases of function types capture the closure var
rank = rank.max(adjust_rank( rank = rank.max(adjust_rank(
subs, young_mark, visit_mark, group_rank, real_var, subs, young_mark, visit_mark, group_rank, *real_var,
)); ));
rank rank

View file

@ -306,6 +306,18 @@ impl Subs {
self.utable.probe_value(key) self.utable.probe_value(key)
} }
pub fn get_ref(&self, key: Variable) -> &Descriptor {
&self.utable.probe_value_ref(key).value
}
pub fn get_rank(&mut self, key: Variable) -> Rank {
self.utable.probe_value_ref(key).value.rank
}
pub fn get_mark(&mut self, key: Variable) -> Mark {
self.utable.probe_value_ref(key).value.mark
}
pub fn get_without_compacting(&self, key: Variable) -> Descriptor { pub fn get_without_compacting(&self, key: Variable) -> Descriptor {
self.utable.probe_value_without_compacting(key) self.utable.probe_value_without_compacting(key)
} }

View file

@ -433,6 +433,17 @@ where
self.value(id).value.clone() self.value(id).value.clone()
} }
/// Returns the current value for the given key. If the key has
/// been union'd, this will give the value from the current root.
pub fn probe_value_ref<K1>(&self, id: K1) -> &VarValue<K>
where
K1: Into<K>,
{
let id = id.into();
let id = self.get_root_key_without_compacting(id);
self.value(id)
}
/// This is for a debug_assert! in solve() only. Do not use it elsewhere! /// This is for a debug_assert! in solve() only. Do not use it elsewhere!
pub fn probe_value_without_compacting<K1>(&self, id: K1) -> V pub fn probe_value_without_compacting<K1>(&self, id: K1) -> V
where where