mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
hash less
This commit is contained in:
parent
05b5cd3429
commit
d35686f3a8
1 changed files with 29 additions and 27 deletions
|
@ -9,7 +9,7 @@ use crate::layout::{
|
|||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use hashbrown::hash_map::Entry;
|
||||
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap, MutSet};
|
||||
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
|
||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
|
@ -378,7 +378,8 @@ impl<'a> Proc<'a> {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ExternalSpecializations<'a> {
|
||||
pub specs: BumpMap<Symbol, MutSet<SolvedType>>,
|
||||
/// Not a bumpalo vec because bumpalo is not thread safe
|
||||
pub specs: BumpMap<Symbol, std::vec::Vec<SolvedType>>,
|
||||
_lifetime: std::marker::PhantomData<&'a u8>,
|
||||
}
|
||||
|
||||
|
@ -394,11 +395,11 @@ impl<'a> ExternalSpecializations<'a> {
|
|||
use hashbrown::hash_map::Entry::{Occupied, Vacant};
|
||||
|
||||
let existing = match self.specs.entry(symbol) {
|
||||
Vacant(entry) => entry.insert(MutSet::default()),
|
||||
Vacant(entry) => entry.insert(std::vec::Vec::new()),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
|
||||
existing.insert(typ);
|
||||
existing.push(typ);
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, other: Self) {
|
||||
|
@ -406,7 +407,7 @@ impl<'a> ExternalSpecializations<'a> {
|
|||
|
||||
for (symbol, solved_types) in other.specs {
|
||||
let existing = match self.specs.entry(symbol) {
|
||||
Vacant(entry) => entry.insert(MutSet::default()),
|
||||
Vacant(entry) => entry.insert(std::vec::Vec::new()),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
|
||||
|
@ -514,9 +515,12 @@ impl<'a> Procs<'a> {
|
|||
// by the surrounding context, so we can add pending specializations
|
||||
// for them immediately.
|
||||
|
||||
let tuple = (symbol, top_level);
|
||||
let already_specialized = self.specialized.contains_key(&tuple);
|
||||
let (symbol, layout) = tuple;
|
||||
let already_specialized = self
|
||||
.specialized
|
||||
.keys()
|
||||
.any(|(s, t)| *s == symbol && *t == top_level);
|
||||
|
||||
let layout = top_level;
|
||||
|
||||
// if we've already specialized this one, no further work is needed.
|
||||
if !already_specialized {
|
||||
|
@ -778,8 +782,6 @@ impl<'a, 'i> Env<'a, 'i> {
|
|||
pub fn unique_symbol(&mut self) -> Symbol {
|
||||
let ident_id = self.ident_ids.gen_unique();
|
||||
|
||||
self.home.register_debug_idents(self.ident_ids);
|
||||
|
||||
Symbol::new(self.home, ident_id)
|
||||
}
|
||||
|
||||
|
@ -1695,19 +1697,16 @@ pub fn specialize_all<'a>(
|
|||
env: &mut Env<'a, '_>,
|
||||
mut procs: Procs<'a>,
|
||||
externals_others_need: ExternalSpecializations<'a>,
|
||||
pending_specializations: BumpMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
|
||||
specializations_for_host: BumpMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) -> Procs<'a> {
|
||||
specialize_all_help(env, &mut procs, externals_others_need, layout_cache);
|
||||
specialize_externals_others_need(env, &mut procs, externals_others_need, 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!
|
||||
|
||||
// observation: specialize_all_help does add to pending_specializations, but does not reference
|
||||
// any existing values in it.
|
||||
let opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
|
||||
|
||||
let it = pending_specializations
|
||||
let it = specializations_for_host
|
||||
.into_iter()
|
||||
.chain(opt_pending_specializations.into_iter().flatten());
|
||||
|
||||
|
@ -1774,33 +1773,35 @@ pub fn specialize_all<'a>(
|
|||
procs
|
||||
}
|
||||
|
||||
fn specialize_all_help<'a>(
|
||||
fn specialize_externals_others_need<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
externals_others_need: ExternalSpecializations<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) {
|
||||
for (symbol, solved_types) in 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
|
||||
// de-duplicate by the Hash instance (set only deduplicates by Eq instance)
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
let mut seen_hashes = Vec::with_capacity_in(solved_types.len(), env.arena);
|
||||
|
||||
let hash_the_thing = |x: &SolvedType| {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
x.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
|
||||
let mut as_vec = Vec::from_iter_in(
|
||||
solved_types.iter().map(|x| (hash_the_thing(x), x)),
|
||||
env.arena,
|
||||
);
|
||||
for solved_type in solved_types {
|
||||
let hash = hash_the_thing(solved_type);
|
||||
|
||||
as_vec.sort_by_key(|(k, _)| *k);
|
||||
as_vec.dedup_by_key(|(k, _)| *k);
|
||||
if seen_hashes.iter().any(|h| *h == hash) {
|
||||
// we've seen this one already
|
||||
continue;
|
||||
}
|
||||
|
||||
seen_hashes.push(hash);
|
||||
|
||||
for (_, solved_type) in as_vec {
|
||||
let name = *symbol;
|
||||
|
||||
let partial_proc = match procs.partial_procs.get(&name) {
|
||||
|
@ -6535,7 +6536,8 @@ fn call_by_name_help<'a>(
|
|||
// If we've already specialized this one, no further work is needed.
|
||||
if procs
|
||||
.specialized
|
||||
.contains_key(&(proc_name, top_level_layout))
|
||||
.keys()
|
||||
.any(|x| x == &(proc_name, top_level_layout))
|
||||
{
|
||||
debug_assert_eq!(
|
||||
argument_layouts.len(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue