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::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use hashbrown::hash_map::Entry;
|
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::ident::{ForeignSymbol, Lowercase, TagName};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||||
|
@ -378,7 +378,8 @@ impl<'a> Proc<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ExternalSpecializations<'a> {
|
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>,
|
_lifetime: std::marker::PhantomData<&'a u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,11 +395,11 @@ impl<'a> ExternalSpecializations<'a> {
|
||||||
use hashbrown::hash_map::Entry::{Occupied, Vacant};
|
use hashbrown::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
|
||||||
let existing = match self.specs.entry(symbol) {
|
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(),
|
Occupied(entry) => entry.into_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
existing.insert(typ);
|
existing.push(typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend(&mut self, other: Self) {
|
pub fn extend(&mut self, other: Self) {
|
||||||
|
@ -406,7 +407,7 @@ impl<'a> ExternalSpecializations<'a> {
|
||||||
|
|
||||||
for (symbol, solved_types) in other.specs {
|
for (symbol, solved_types) in other.specs {
|
||||||
let existing = match self.specs.entry(symbol) {
|
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(),
|
Occupied(entry) => entry.into_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -514,9 +515,12 @@ impl<'a> Procs<'a> {
|
||||||
// by the surrounding context, so we can add pending specializations
|
// by the surrounding context, so we can add pending specializations
|
||||||
// for them immediately.
|
// for them immediately.
|
||||||
|
|
||||||
let tuple = (symbol, top_level);
|
let already_specialized = self
|
||||||
let already_specialized = self.specialized.contains_key(&tuple);
|
.specialized
|
||||||
let (symbol, layout) = tuple;
|
.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 we've already specialized this one, no further work is needed.
|
||||||
if !already_specialized {
|
if !already_specialized {
|
||||||
|
@ -778,8 +782,6 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
pub fn unique_symbol(&mut self) -> Symbol {
|
pub fn unique_symbol(&mut self) -> Symbol {
|
||||||
let ident_id = self.ident_ids.gen_unique();
|
let ident_id = self.ident_ids.gen_unique();
|
||||||
|
|
||||||
self.home.register_debug_idents(self.ident_ids);
|
|
||||||
|
|
||||||
Symbol::new(self.home, ident_id)
|
Symbol::new(self.home, ident_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1695,19 +1697,16 @@ pub fn specialize_all<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
mut procs: Procs<'a>,
|
mut procs: Procs<'a>,
|
||||||
externals_others_need: ExternalSpecializations<'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>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
) -> Procs<'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.
|
// 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!
|
||||||
|
|
||||||
// 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 opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
|
||||||
|
|
||||||
let it = pending_specializations
|
let it = specializations_for_host
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(opt_pending_specializations.into_iter().flatten());
|
.chain(opt_pending_specializations.into_iter().flatten());
|
||||||
|
|
||||||
|
@ -1774,33 +1773,35 @@ pub fn specialize_all<'a>(
|
||||||
procs
|
procs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn specialize_all_help<'a>(
|
fn specialize_externals_others_need<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
procs: &mut Procs<'a>,
|
procs: &mut Procs<'a>,
|
||||||
externals_others_need: ExternalSpecializations<'a>,
|
externals_others_need: ExternalSpecializations<'a>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
) {
|
) {
|
||||||
for (symbol, solved_types) in externals_others_need.specs.iter() {
|
for (symbol, solved_types) in externals_others_need.specs.iter() {
|
||||||
// for some unclear reason, the MutSet does not deduplicate according to the hash
|
// de-duplicate by the Hash instance (set only deduplicates by Eq instance)
|
||||||
// instance. So we do it manually here
|
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
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 hash_the_thing = |x: &SolvedType| {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
x.hash(&mut hasher);
|
x.hash(&mut hasher);
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut as_vec = Vec::from_iter_in(
|
for solved_type in solved_types {
|
||||||
solved_types.iter().map(|x| (hash_the_thing(x), x)),
|
let hash = hash_the_thing(solved_type);
|
||||||
env.arena,
|
|
||||||
);
|
|
||||||
|
|
||||||
as_vec.sort_by_key(|(k, _)| *k);
|
if seen_hashes.iter().any(|h| *h == hash) {
|
||||||
as_vec.dedup_by_key(|(k, _)| *k);
|
// we've seen this one already
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen_hashes.push(hash);
|
||||||
|
|
||||||
for (_, solved_type) in as_vec {
|
|
||||||
let name = *symbol;
|
let name = *symbol;
|
||||||
|
|
||||||
let partial_proc = match procs.partial_procs.get(&name) {
|
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 we've already specialized this one, no further work is needed.
|
||||||
if procs
|
if procs
|
||||||
.specialized
|
.specialized
|
||||||
.contains_key(&(proc_name, top_level_layout))
|
.keys()
|
||||||
|
.any(|x| x == &(proc_name, top_level_layout))
|
||||||
{
|
{
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
argument_layouts.len(),
|
argument_layouts.len(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue