refactor/optimize loop in ir codegen

This commit is contained in:
Folkert 2021-05-02 01:08:53 +02:00
parent 839095942d
commit 2032ef9b52

View file

@ -1635,73 +1635,14 @@ pub fn specialize_all<'a>(
mut procs: Procs<'a>, mut procs: Procs<'a>,
layout_cache: &mut LayoutCache<'a>, layout_cache: &mut LayoutCache<'a>,
) -> Procs<'a> { ) -> Procs<'a> {
let it = procs.externals_others_need.specs.clone(); specialize_all_help(env, &mut procs, layout_cache);
let it = it
.into_iter()
.map(|(symbol, solved_types)| {
// for some unclear reason, the MutSet does not deduplicate according to the hash
// instance. So we do it manually here
let mut as_vec: std::vec::Vec<_> = solved_types.into_iter().collect();
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let hash_the_thing = |x: &SolvedType| {
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
as_vec.sort_by_key(|x| hash_the_thing(x));
as_vec.dedup_by_key(|x| hash_the_thing(x));
as_vec.into_iter().map(move |s| (symbol, s))
})
.flatten();
for (name, solved_type) in it.into_iter() {
let partial_proc = match procs.partial_procs.get(&name) {
Some(v) => v.clone(),
None => {
panic!("Cannot find a partial proc for {:?}", name);
}
};
match specialize_solved_type(
env,
&mut procs,
name,
layout_cache,
solved_type,
BumpMap::new_in(env.arena),
partial_proc,
) {
Ok((proc, layout)) => {
procs.specialized.insert((name, layout), Done(proc));
}
Err(SpecializeFailure {
problem: _,
attempted_layout,
}) => {
let proc = generate_runtime_error_function(env, name, attempted_layout);
procs
.specialized
.insert((name, attempted_layout), Done(proc));
}
}
}
let mut pending_specializations = procs
.pending_specializations
.unwrap_or_else(|| BumpMap::new_in(env.arena));
// When calling from_can, pending_specializations should be unavailable. // When calling from_can, pending_specializations should be unavailable.
// This must be a single pass, and we must not add any more entries to it! // This must be a single pass, and we must not add any more entries to it!
procs.pending_specializations = None; let opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
for (name, mut by_layout) in pending_specializations.drain() { for (name, by_layout) in opt_pending_specializations.into_iter().flatten() {
for (layout, pending) in by_layout.drain() { for (layout, pending) in by_layout.into_iter() {
// If we've already seen this (Symbol, Layout) combination before, // If we've already seen this (Symbol, Layout) combination before,
// don't try to specialize it again. If we do, we'll loop forever! // don't try to specialize it again. If we do, we'll loop forever!
// //
@ -1762,6 +1703,69 @@ pub fn specialize_all<'a>(
procs procs
} }
fn specialize_all_help<'a>(
env: &mut Env<'a, '_>,
procs: &mut Procs<'a>,
layout_cache: &mut LayoutCache<'a>,
) {
let mut symbol_solved_type = Vec::new_in(env.arena);
for (symbol, solved_types) in procs.externals_others_need.specs.iter() {
// for some unclear reason, the MutSet does not deduplicate according to the hash
// instance. So we do it manually here
let mut as_vec: std::vec::Vec<_> = solved_types.iter().collect();
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let hash_the_thing = |x: &SolvedType| {
let mut hasher = DefaultHasher::new();
x.hash(&mut hasher);
hasher.finish()
};
as_vec.sort_by_key(|x| hash_the_thing(x));
as_vec.dedup_by_key(|x| hash_the_thing(x));
for s in as_vec {
symbol_solved_type.push((*symbol, s.clone()));
}
}
for (name, solved_type) in symbol_solved_type.into_iter() {
let partial_proc = match procs.partial_procs.get(&name) {
Some(v) => v.clone(),
None => {
panic!("Cannot find a partial proc for {:?}", name);
}
};
match specialize_solved_type(
env,
procs,
name,
layout_cache,
solved_type,
BumpMap::new_in(env.arena),
partial_proc,
) {
Ok((proc, layout)) => {
procs.specialized.insert((name, layout), Done(proc));
}
Err(SpecializeFailure {
problem: _,
attempted_layout,
}) => {
let proc = generate_runtime_error_function(env, name, attempted_layout);
procs
.specialized
.insert((name, attempted_layout), Done(proc));
}
}
}
}
fn generate_runtime_error_function<'a>( fn generate_runtime_error_function<'a>(
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
name: Symbol, name: Symbol,