mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
refactor/optimize loop in ir codegen
This commit is contained in:
parent
839095942d
commit
2032ef9b52
1 changed files with 67 additions and 63 deletions
|
@ -1635,73 +1635,14 @@ pub fn specialize_all<'a>(
|
|||
mut procs: Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) -> Procs<'a> {
|
||||
let it = procs.externals_others_need.specs.clone();
|
||||
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));
|
||||
specialize_all_help(env, &mut procs, layout_cache);
|
||||
|
||||
// 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!
|
||||
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 (layout, pending) in by_layout.drain() {
|
||||
for (name, by_layout) in opt_pending_specializations.into_iter().flatten() {
|
||||
for (layout, pending) in by_layout.into_iter() {
|
||||
// If we've already seen this (Symbol, Layout) combination before,
|
||||
// don't try to specialize it again. If we do, we'll loop forever!
|
||||
//
|
||||
|
@ -1762,6 +1703,69 @@ pub fn specialize_all<'a>(
|
|||
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>(
|
||||
env: &mut Env<'a, '_>,
|
||||
name: Symbol,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue