Merge pull request #990 from rtfeldman/fuse-rc-struct

Fuse rc in structs/closures
This commit is contained in:
Richard Feldman 2021-02-12 22:59:54 -05:00 committed by GitHub
commit 065b6ac2e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 23 deletions

View file

@ -157,6 +157,16 @@ impl<'a, 'i> Env<'a, 'i> {
} }
} }
fn insert_struct_info(&mut self, symbol: Symbol, fields: &'a [Layout<'a>]) {
self.constructor_map.insert(symbol, 0);
self.layout_map.insert(symbol, Layout::Struct(fields));
}
fn remove_struct_info(&mut self, symbol: Symbol) {
self.constructor_map.remove(&symbol);
self.layout_map.remove(&symbol);
}
pub fn unique_symbol(&mut self) -> Symbol { pub fn unique_symbol(&mut self) -> Symbol {
let ident_id = self.ident_ids.gen_unique(); let ident_id = self.ident_ids.gen_unique();
@ -213,6 +223,10 @@ fn layout_for_constructor<'a>(
} }
} }
} }
Struct(fields) => {
debug_assert_eq!(constructor, 0);
HasFields(fields)
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -322,7 +336,39 @@ enum ConstructorLayout<T> {
Unknown, Unknown,
} }
pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> { pub fn expand_and_cancel_proc<'a>(
env: &mut Env<'a, '_>,
stmt: &'a Stmt<'a>,
arguments: &'a [(Layout<'a>, Symbol)],
) -> &'a Stmt<'a> {
let mut introduced = Vec::new_in(env.arena);
for (layout, symbol) in arguments {
match layout {
Layout::Struct(fields) => {
env.insert_struct_info(*symbol, fields);
introduced.push(*symbol);
}
Layout::Closure(_, closure_layout, _) => {
if let Layout::Struct(fields) = closure_layout.layout {
env.insert_struct_info(*symbol, fields);
}
}
_ => {}
}
}
let result = expand_and_cancel(env, stmt);
for symbol in introduced {
env.remove_struct_info(symbol);
}
result
}
fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<'a> {
use Stmt::*; use Stmt::*;
let mut deferred_default = Deferred { let mut deferred_default = Deferred {
@ -351,7 +397,7 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
// prevent long chains of `Let`s from blowing the stack // prevent long chains of `Let`s from blowing the stack
let mut literal_stack = Vec::new_in(env.arena); let mut literal_stack = Vec::new_in(env.arena);
while !matches!(&expr, Expr::AccessAtIndex { .. } ) { while !matches!(&expr, Expr::AccessAtIndex { .. } | Expr::Struct(_)) {
if let Stmt::Let(symbol1, expr1, layout1, cont1) = cont { if let Stmt::Let(symbol1, expr1, layout1, cont1) = cont {
literal_stack.push((symbol, expr.clone(), layout.clone())); literal_stack.push((symbol, expr.clone(), layout.clone()));
@ -366,10 +412,10 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
let new_cont; let new_cont;
if let Expr::AccessAtIndex { match &expr {
Expr::AccessAtIndex {
structure, index, .. structure, index, ..
} = &expr } => {
{
let entry = env let entry = env
.alias_map .alias_map
.entry(*structure) .entry(*structure)
@ -383,9 +429,22 @@ pub fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a S
env.alias_map env.alias_map
.get_mut(structure) .get_mut(structure)
.and_then(|map| map.remove(index)); .and_then(|map| map.remove(index));
}
Expr::Struct(_) => {
if let Layout::Struct(fields) = layout {
env.insert_struct_info(symbol, fields);
new_cont = expand_and_cancel(env, cont);
env.remove_struct_info(symbol);
} else { } else {
new_cont = expand_and_cancel(env, cont); new_cont = expand_and_cancel(env, cont);
} }
}
_ => {
new_cont = expand_and_cancel(env, cont);
}
}
let stmt = Let(symbol, expr.clone(), layout.clone(), new_cont); let stmt = Let(symbol, expr.clone(), layout.clone(), new_cont);
let mut stmt = &*env.arena.alloc(stmt); let mut stmt = &*env.arena.alloc(stmt);

View file

@ -183,7 +183,11 @@ impl<'a> Proc<'a> {
}; };
for (_, proc) in procs.iter_mut() { for (_, proc) in procs.iter_mut() {
let b = expand_rc::expand_and_cancel(&mut env, arena.alloc(proc.body.clone())); let b = expand_rc::expand_and_cancel_proc(
&mut env,
arena.alloc(proc.body.clone()),
proc.args,
);
proc.body = b.clone(); proc.body = b.clone();
} }
} }

View file

@ -70,7 +70,9 @@ pub struct ClosureLayout<'a> {
/// the vec is likely to be small, so linear search is fine /// the vec is likely to be small, so linear search is fine
captured: &'a [(TagName, &'a [Layout<'a>])], captured: &'a [(TagName, &'a [Layout<'a>])],
layout: &'a Layout<'a>, /// use with care; there is some stuff happening here re. unwrapping
/// one-element records that might cause issues
pub layout: &'a Layout<'a>,
} }
impl<'a> ClosureLayout<'a> { impl<'a> ClosureLayout<'a> {

View file

@ -949,8 +949,7 @@ mod test_mono {
let Test.5 = 3.14f64; let Test.5 = 3.14f64;
let Test.3 = Struct {Test.4, Test.5}; let Test.3 = Struct {Test.4, Test.5};
let Test.1 = Index 0 Test.3; let Test.1 = Index 0 Test.3;
inc Test.1; decref Test.3;
dec Test.3;
ret Test.1; ret Test.1;
"# "#
), ),

View file

@ -4697,7 +4697,7 @@ mod test_reporting {
I was expecting to see a private tag name. I was expecting to see a private tag name.
Hint: Private tag names start with a `@` symbol followed by an Hint: Private tag names start with an `@` symbol followed by an
uppercase letter, like @UID or @SecretKey. uppercase letter, like @UID or @SecretKey.
"# "#
), ),