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>,
|
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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue