simplify monomorphization first steps

This commit is contained in:
Folkert 2021-10-22 18:12:46 +02:00
parent 0529d6dbc6
commit eaaf3eb940
2 changed files with 73 additions and 58 deletions

View File

@ -3981,6 +3981,30 @@ fn make_specializations<'a>(
} }
} }
#[derive(Clone, Debug)]
struct ProcsBase<'a> {
partial_procs: BumpMap<Symbol, PartialProc<'a>>,
module_thunks: bumpalo::collections::Vec<'a, Symbol>,
pending_specializations: BumpMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
runtime_errors: BumpMap<Symbol, &'a str>,
}
impl<'a> ProcsBase<'a> {
fn add_pending(
&mut self,
symbol: Symbol,
layout: ProcLayout<'a>,
pending: PendingSpecialization<'a>,
) {
let all_pending = self
.pending_specializations
.entry(symbol)
.or_insert_with(|| HashMap::with_capacity_and_hasher(1, default_hasher()));
all_pending.insert(layout, pending);
}
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn build_pending_specializations<'a>( fn build_pending_specializations<'a>(
arena: &'a Bump, arena: &'a Bump,
@ -3996,10 +4020,12 @@ fn build_pending_specializations<'a>(
exposed_to_host: MutMap<Symbol, Variable>, exposed_to_host: MutMap<Symbol, Variable>,
) -> Msg<'a> { ) -> Msg<'a> {
let find_specializations_start = SystemTime::now(); let find_specializations_start = SystemTime::now();
let mut procs = Procs::new_in(arena); let mut procs_base = ProcsBase {
partial_procs: BumpMap::default(),
debug_assert!(procs.imported_module_thunks.is_empty()); module_thunks: bumpalo::collections::Vec::new_in(arena),
procs.imported_module_thunks = imported_module_thunks; pending_specializations: BumpMap::default(),
runtime_errors: BumpMap::default(),
};
let mut mono_problems = std::vec::Vec::new(); let mut mono_problems = std::vec::Vec::new();
let mut subs = solved_subs.into_inner(); let mut subs = solved_subs.into_inner();
@ -4022,7 +4048,7 @@ fn build_pending_specializations<'a>(
match decl { match decl {
Declare(def) | Builtin(def) => add_def_to_module( Declare(def) | Builtin(def) => add_def_to_module(
&mut layout_cache, &mut layout_cache,
&mut procs, &mut procs_base,
&mut mono_env, &mut mono_env,
def, def,
&exposed_to_host, &exposed_to_host,
@ -4032,7 +4058,7 @@ fn build_pending_specializations<'a>(
for def in defs { for def in defs {
add_def_to_module( add_def_to_module(
&mut layout_cache, &mut layout_cache,
&mut procs, &mut procs_base,
&mut mono_env, &mut mono_env,
def, def,
&exposed_to_host, &exposed_to_host,
@ -4054,6 +4080,16 @@ fn build_pending_specializations<'a>(
.duration_since(find_specializations_start) .duration_since(find_specializations_start)
.unwrap(); .unwrap();
let mut procs = Procs::new_in(arena);
debug_assert!(procs.imported_module_thunks.is_empty());
procs.imported_module_thunks = imported_module_thunks;
procs.partial_procs = procs_base.partial_procs;
procs.module_thunks.extend(procs_base.module_thunks);
procs.pending_specializations = Some(procs_base.pending_specializations);
procs.runtime_errors = procs_base.runtime_errors;
Msg::FoundSpecializations { Msg::FoundSpecializations {
module_id: home, module_id: home,
solved_subs: roc_types::solved_types::Solved(subs), solved_subs: roc_types::solved_types::Solved(subs),
@ -4067,7 +4103,7 @@ fn build_pending_specializations<'a>(
fn add_def_to_module<'a>( fn add_def_to_module<'a>(
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
procs: &mut Procs<'a>, procs: &mut ProcsBase<'a>,
mono_env: &mut roc_mono::ir::Env<'a, '_>, mono_env: &mut roc_mono::ir::Env<'a, '_>,
def: roc_can::def::Def, def: roc_can::def::Def,
exposed_to_host: &MutMap<Symbol, Variable>, exposed_to_host: &MutMap<Symbol, Variable>,
@ -4129,14 +4165,18 @@ fn add_def_to_module<'a>(
} }
}; };
procs.insert_exposed( let pending = PendingSpecialization::from_exposed_function(
symbol,
ProcLayout::from_raw(mono_env.arena, layout),
mono_env.arena, mono_env.arena,
mono_env.subs, mono_env.subs,
def.annotation, def.annotation,
annotation, annotation,
); );
procs.add_pending(
symbol,
ProcLayout::from_raw(mono_env.arena, layout),
pending,
);
} }
let partial_proc = PartialProc::from_named_function( let partial_proc = PartialProc::from_named_function(
@ -4154,7 +4194,7 @@ fn add_def_to_module<'a>(
} }
body => { body => {
// mark this symbols as a top-level thunk before any other work on the procs // mark this symbols as a top-level thunk before any other work on the procs
procs.module_thunks.insert(symbol); procs.module_thunks.push(symbol);
// If this is an exposed symbol, we need to // If this is an exposed symbol, we need to
// register it as such. Otherwise, since it // register it as such. Otherwise, since it
@ -4189,14 +4229,14 @@ fn add_def_to_module<'a>(
} }
}; };
procs.insert_exposed( let pending = PendingSpecialization::from_exposed_function(
symbol,
top_level,
mono_env.arena, mono_env.arena,
mono_env.subs, mono_env.subs,
def.annotation, def.annotation,
annotation, annotation,
); );
procs.add_pending(symbol, top_level, pending);
} }
let proc = PartialProc { let proc = PartialProc {

View File

@ -188,6 +188,24 @@ impl<'a> PendingSpecialization<'a> {
_lifetime: std::marker::PhantomData, _lifetime: std::marker::PhantomData,
} }
} }
/// Add a named function that will be publicly exposed to the host
pub fn from_exposed_function(
arena: &'a Bump,
subs: &Subs,
opt_annotation: Option<roc_can::def::Annotation>,
fn_var: Variable,
) -> Self {
match opt_annotation {
None => PendingSpecialization::from_var(arena, subs, fn_var),
Some(annotation) => PendingSpecialization::from_var_host_exposed(
arena,
subs,
fn_var,
&annotation.introduced_variables.host_exposed_aliases,
),
}
}
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -586,50 +604,7 @@ impl<'a> Procs<'a> {
} }
} }
/// Add a named function that will be publicly exposed to the host fn insert_passed_by_name(
pub fn insert_exposed(
&mut self,
name: Symbol,
layout: ProcLayout<'a>,
arena: &'a Bump,
subs: &Subs,
opt_annotation: Option<roc_can::def::Annotation>,
fn_var: Variable,
) {
let tuple = (name, layout);
// If we've already specialized this one, no further work is needed.
if self.specialized.contains_key(&tuple) {
return;
}
// We're done with that tuple, so move layout back out to avoid cloning it.
let (name, layout) = tuple;
let pending = match opt_annotation {
None => PendingSpecialization::from_var(arena, subs, fn_var),
Some(annotation) => PendingSpecialization::from_var_host_exposed(
arena,
subs,
fn_var,
&annotation.introduced_variables.host_exposed_aliases,
),
};
// This should only be called when pending_specializations is Some.
// Otherwise, it's being called in the wrong pass!
match &mut self.pending_specializations {
Some(pending_specializations) => {
// register the pending specialization, so this gets code genned later
add_pending(pending_specializations, name, layout, pending)
}
None => unreachable!(
r"insert_exposed was called after the pending specializations phase had already completed!"
),
}
}
/// TODO
pub fn insert_passed_by_name(
&mut self, &mut self,
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
fn_var: Variable, fn_var: Variable,