mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Use LayoutCache to avoid recomputing layouts
This commit is contained in:
parent
efa486251e
commit
510ab36f51
6 changed files with 238 additions and 168 deletions
|
@ -36,21 +36,7 @@ pub enum Builtin<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Layout<'a> {
|
||||
/// Returns Err(()) if given an error, or Ok(Layout) if given a non-erroneous Structure.
|
||||
/// Panics if given a FlexVar or RigidVar, since those should have been
|
||||
/// monomorphized away already!
|
||||
pub fn from_var(
|
||||
arena: &'a Bump,
|
||||
var: Variable,
|
||||
subs: &Subs,
|
||||
pointer_size: u32,
|
||||
) -> Result<Self, ()> {
|
||||
let content = subs.get_without_compacting(var).content;
|
||||
|
||||
Self::from_content(arena, content, subs, pointer_size)
|
||||
}
|
||||
|
||||
pub fn from_content(
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
content: Content,
|
||||
subs: &Subs,
|
||||
|
@ -61,7 +47,7 @@ impl<'a> Layout<'a> {
|
|||
match content {
|
||||
var @ FlexVar(_) | var @ RigidVar(_) => {
|
||||
panic!(
|
||||
"Layout::from_content encountered an unresolved {:?} - subs was {:?}",
|
||||
"Layout::new encountered an unresolved {:?} - subs was {:?}",
|
||||
var, subs
|
||||
);
|
||||
}
|
||||
|
@ -75,7 +61,7 @@ impl<'a> Layout<'a> {
|
|||
debug_assert!(args.is_empty());
|
||||
Ok(Layout::Builtin(Builtin::Float64))
|
||||
}
|
||||
Alias(_, _, var) => Self::from_content(
|
||||
Alias(_, _, var) => Self::new(
|
||||
arena,
|
||||
subs.get_without_compacting(var).content,
|
||||
subs,
|
||||
|
@ -85,6 +71,20 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns Err(()) if given an error, or Ok(Layout) if given a non-erroneous Structure.
|
||||
/// Panics if given a FlexVar or RigidVar, since those should have been
|
||||
/// monomorphized away already!
|
||||
fn from_var(
|
||||
arena: &'a Bump,
|
||||
var: Variable,
|
||||
subs: &Subs,
|
||||
pointer_size: u32,
|
||||
) -> Result<Self, ()> {
|
||||
let content = subs.get_without_compacting(var).content;
|
||||
|
||||
Self::new(arena, content, subs, pointer_size)
|
||||
}
|
||||
|
||||
pub fn safe_to_memcpy(&self) -> bool {
|
||||
use Layout::*;
|
||||
|
||||
|
@ -139,7 +139,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
/// Avoid recomputing Layout from Variable multiple times.
|
||||
#[derive(Default)]
|
||||
struct LayoutCache<'a> {
|
||||
pub struct LayoutCache<'a> {
|
||||
layouts: MutMap<Variable, Result<Layout<'a>, ()>>,
|
||||
}
|
||||
|
||||
|
@ -153,10 +153,18 @@ impl<'a> LayoutCache<'a> {
|
|||
var: Variable,
|
||||
subs: &Subs,
|
||||
pointer_size: u32,
|
||||
) -> &Result<Layout<'a>, ()> {
|
||||
) -> Result<Layout<'a>, ()> {
|
||||
// Store things according to the root Variable, to avoid duplicate work.
|
||||
let var = subs.get_root_key_without_compacting(var);
|
||||
|
||||
self.layouts
|
||||
.entry(var)
|
||||
.or_insert_with(|| Layout::from_var(arena, var, subs, pointer_size))
|
||||
.or_insert_with(|| {
|
||||
let content = subs.get_without_compacting(var).content;
|
||||
|
||||
Layout::new(arena, content, subs, pointer_size)
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +247,7 @@ fn layout_from_flat_type<'a>(
|
|||
match subs.get_without_compacting(args[0]).content {
|
||||
FlexVar(_) | RigidVar(_) => Ok(Layout::Builtin(Builtin::EmptyList)),
|
||||
content => {
|
||||
let elem_layout =
|
||||
Layout::from_content(arena, content, subs, pointer_size)?;
|
||||
let elem_layout = Layout::new(arena, content, subs, pointer_size)?;
|
||||
|
||||
Ok(Layout::Builtin(Builtin::List(arena.alloc(elem_layout))))
|
||||
}
|
||||
|
@ -269,16 +276,11 @@ fn layout_from_flat_type<'a>(
|
|||
for arg_var in args {
|
||||
let arg_content = subs.get_without_compacting(arg_var).content;
|
||||
|
||||
fn_args.push(Layout::from_content(
|
||||
arena,
|
||||
arg_content,
|
||||
subs,
|
||||
pointer_size,
|
||||
)?);
|
||||
fn_args.push(Layout::new(arena, arg_content, subs, pointer_size)?);
|
||||
}
|
||||
|
||||
let ret_content = subs.get_without_compacting(ret_var).content;
|
||||
let ret = Layout::from_content(arena, ret_content, subs, pointer_size)?;
|
||||
let ret = Layout::new(arena, ret_content, subs, pointer_size)?;
|
||||
|
||||
Ok(Layout::FunctionPointer(
|
||||
fn_args.into_bump_slice(),
|
||||
|
@ -296,14 +298,13 @@ fn layout_from_flat_type<'a>(
|
|||
|
||||
for (_, field_var) in btree {
|
||||
let field_content = subs.get_without_compacting(field_var).content;
|
||||
let field_layout =
|
||||
match Layout::from_content(arena, field_content, subs, pointer_size) {
|
||||
Ok(layout) => layout,
|
||||
Err(()) => {
|
||||
// Invalid field!
|
||||
panic!("TODO gracefully handle record with invalid field.var");
|
||||
}
|
||||
};
|
||||
let field_layout = match Layout::new(arena, field_content, subs, pointer_size) {
|
||||
Ok(layout) => layout,
|
||||
Err(()) => {
|
||||
// Invalid field!
|
||||
panic!("TODO gracefully handle record with invalid field.var");
|
||||
}
|
||||
};
|
||||
|
||||
layouts.push(field_layout);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue