Merge pull request #1249 from rtfeldman/bumpmap-procs

Bumpmap procs
This commit is contained in:
Richard Feldman 2021-04-30 20:34:53 -04:00 committed by GitHub
commit 7b885f2e7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 63 deletions

View File

@ -29,6 +29,7 @@ pub type SendMap<K, V> = im::hashmap::HashMap<K, V, BuildHasher>;
pub type SendSet<K> = im::hashset::HashSet<K, BuildHasher>;
pub type BumpMap<'a, K, V> = hashbrown::HashMap<K, V, BuildHasher, hashbrown::BumpWrapper<'a>>;
pub type BumpSet<'a, K> = hashbrown::HashSet<K, BuildHasher, hashbrown::BumpWrapper<'a>>;
pub trait BumpMapDefault<'a> {
fn new_in(arena: &'a bumpalo::Bump) -> Self;
@ -50,6 +51,20 @@ impl<'a, K, V> BumpMapDefault<'a> for BumpMap<'a, K, V> {
}
}
impl<'a, K> BumpMapDefault<'a> for BumpSet<'a, K> {
fn new_in(arena: &'a bumpalo::Bump) -> Self {
hashbrown::HashSet::with_hasher_in(default_hasher(), hashbrown::BumpWrapper(arena))
}
fn with_capacity_in(capacity: usize, arena: &'a bumpalo::Bump) -> Self {
hashbrown::HashSet::with_capacity_and_hasher_in(
capacity,
default_hasher(),
hashbrown::BumpWrapper(arena),
)
}
}
pub fn arena_join<'a, I>(arena: &'a Bump, strings: &mut I, join_str: &str) -> String<'a>
where
I: Iterator<Item = &'a str>,

View File

@ -8,7 +8,7 @@ use roc_builtins::std::StdLib;
use roc_can::constraint::Constraint;
use roc_can::def::{Declaration, Def};
use roc_can::module::{canonicalize_module_defs, Module};
use roc_collections::all::{default_hasher, MutMap, MutSet};
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, BumpSet, MutMap, MutSet};
use roc_constrain::module::{
constrain_imports, pre_constrain_imports, ConstrainableImports, Import,
};
@ -355,7 +355,7 @@ struct ModuleCache<'a> {
constrained: MutMap<ModuleId, ConstrainedModule>,
typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>,
found_specializations: MutMap<ModuleId, FoundSpecializationsModule<'a>>,
external_specializations_requested: MutMap<ModuleId, ExternalSpecializations>,
external_specializations_requested: MutMap<ModuleId, ExternalSpecializations<'a>>,
/// Various information
imports: MutMap<ModuleId, MutSet<ModuleId>>,
@ -369,7 +369,12 @@ struct ModuleCache<'a> {
header_sources: MutMap<ModuleId, (PathBuf, &'a str)>,
}
fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> Vec<BuildTask<'a>> {
fn start_phase<'a>(
module_id: ModuleId,
phase: Phase,
arena: &'a Bump,
state: &mut State<'a>,
) -> Vec<BuildTask<'a>> {
// we blindly assume all dependencies are met
match state
@ -391,7 +396,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
.dependencies
.notify(module_id, phase)
.into_iter()
.map(|(module_id, phase)| start_phase(module_id, phase, state))
.map(|(module_id, phase)| start_phase(module_id, phase, arena, state))
.flatten()
.collect();
}
@ -545,7 +550,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
ident_ids,
} = typechecked;
let mut imported_module_thunks = MutSet::default();
let mut imported_module_thunks = BumpSet::new_in(arena);
if let Some(imports) = state.module_cache.imports.get(&module_id) {
for imported in imports.iter() {
@ -579,7 +584,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
.module_cache
.external_specializations_requested
.remove(&module_id)
.unwrap_or_default();
.unwrap_or_else(|| ExternalSpecializations::new_in(arena));
let FoundSpecializationsModule {
module_id,
@ -769,7 +774,7 @@ enum Msg<'a> {
module_id: ModuleId,
ident_ids: IdentIds,
layout_cache: LayoutCache<'a>,
external_specializations_requested: MutMap<ModuleId, ExternalSpecializations>,
external_specializations_requested: BumpMap<'a, ModuleId, ExternalSpecializations<'a>>,
procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>,
problems: Vec<roc_mono::ir::MonoProblem>,
module_timing: ModuleTiming,
@ -971,7 +976,7 @@ enum BuildTask<'a> {
module_timing: ModuleTiming,
layout_cache: LayoutCache<'a>,
solved_subs: Solved<Subs>,
imported_module_thunks: MutSet<Symbol>,
imported_module_thunks: BumpSet<'a, Symbol>,
module_id: ModuleId,
ident_ids: IdentIds,
decls: Vec<Declaration>,
@ -983,7 +988,7 @@ enum BuildTask<'a> {
subs: Subs,
procs: Procs<'a>,
layout_cache: LayoutCache<'a>,
specializations_we_must_make: ExternalSpecializations,
specializations_we_must_make: ExternalSpecializations<'a>,
module_timing: ModuleTiming,
},
}
@ -1464,7 +1469,7 @@ where
all_pending_specializations: MutMap::default(),
specializations_in_flight: 0,
layout_caches: std::vec::Vec::with_capacity(num_cpus::get()),
procs: Procs::default(),
procs: Procs::new_in(arena),
};
// We've now distributed one worker queue to each thread.
@ -1603,13 +1608,14 @@ where
}
fn start_tasks<'a>(
work: MutSet<(ModuleId, Phase)>,
arena: &'a Bump,
state: &mut State<'a>,
work: MutSet<(ModuleId, Phase)>,
injector: &Injector<BuildTask<'a>>,
worker_listeners: &'a [Sender<WorkerMsg>],
) -> Result<(), LoadingProblem<'a>> {
for (module_id, phase) in work {
for task in start_phase(module_id, phase, state) {
for task in start_phase(module_id, phase, arena, state) {
enqueue_task(&injector, worker_listeners, task)?
}
}
@ -1731,11 +1737,11 @@ fn update<'a>(
state.module_cache.headers.insert(header.module_id, header);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
let work = state.dependencies.notify(home, Phase::LoadHeader);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
Ok(state)
}
@ -1768,7 +1774,7 @@ fn update<'a>(
let work = state.dependencies.notify(module_id, Phase::Parse);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
Ok(state)
}
@ -1803,7 +1809,7 @@ fn update<'a>(
.dependencies
.notify(module_id, Phase::CanonicalizeAndConstrain);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
Ok(state)
}
@ -1854,7 +1860,7 @@ fn update<'a>(
.notify(module_id, Phase::CanonicalizeAndConstrain),
);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
Ok(state)
}
@ -1956,7 +1962,7 @@ fn update<'a>(
state.constrained_ident_ids.insert(module_id, ident_ids);
}
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
}
Ok(state)
@ -2011,7 +2017,7 @@ fn update<'a>(
.dependencies
.notify(module_id, Phase::FindSpecializations);
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
Ok(state)
}
@ -2057,7 +2063,7 @@ fn update<'a>(
.external_specializations_requested
.entry(module_id)
{
Vacant(entry) => entry.insert(ExternalSpecializations::default()),
Vacant(entry) => entry.insert(ExternalSpecializations::new_in(arena)),
Occupied(entry) => entry.into_mut(),
};
@ -2097,14 +2103,14 @@ fn update<'a>(
.external_specializations_requested
.entry(module_id)
{
Vacant(entry) => entry.insert(ExternalSpecializations::default()),
Vacant(entry) => entry.insert(ExternalSpecializations::new_in(arena)),
Occupied(entry) => entry.into_mut(),
};
existing.extend(requested);
}
start_tasks(work, &mut state, &injector, worker_listeners)?;
start_tasks(arena, &mut state, work, &injector, worker_listeners)?;
}
Ok(state)
@ -3776,7 +3782,7 @@ fn make_specializations<'a>(
mut subs: Subs,
mut procs: Procs<'a>,
mut layout_cache: LayoutCache<'a>,
specializations_we_must_make: ExternalSpecializations,
specializations_we_must_make: ExternalSpecializations<'a>,
mut module_timing: ModuleTiming,
ptr_bytes: u32,
) -> Msg<'a> {
@ -3825,7 +3831,7 @@ fn make_specializations<'a>(
fn build_pending_specializations<'a>(
arena: &'a Bump,
solved_subs: Solved<Subs>,
imported_module_thunks: MutSet<Symbol>,
imported_module_thunks: BumpSet<'a, Symbol>,
home: ModuleId,
mut ident_ids: IdentIds,
decls: Vec<Declaration>,
@ -3836,7 +3842,7 @@ fn build_pending_specializations<'a>(
exposed_to_host: MutMap<Symbol, Variable>,
) -> Msg<'a> {
let find_specializations_start = SystemTime::now();
let mut procs = Procs::default();
let mut procs = Procs::new_in(arena);
debug_assert!(procs.imported_module_thunks.is_empty());
procs.imported_module_thunks = imported_module_thunks;

View File

@ -6,7 +6,7 @@ use crate::layout::{
};
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap, MutSet};
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, BumpSet, MutMap, MutSet};
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
@ -55,12 +55,6 @@ pub struct PartialProc<'a> {
pub is_self_recursive: bool,
}
#[derive(Clone, Debug, PartialEq, Default)]
pub struct HostExposedVariables {
rigids: MutMap<Lowercase, Variable>,
aliases: MutMap<Symbol, Variable>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum CapturedSymbols<'a> {
None,
@ -243,14 +237,20 @@ impl<'a> Proc<'a> {
}
}
#[derive(Clone, Debug, Default)]
pub struct ExternalSpecializations {
pub specs: MutMap<Symbol, MutSet<SolvedType>>,
#[derive(Clone, Debug)]
pub struct ExternalSpecializations<'a> {
pub specs: BumpMap<'a, Symbol, MutSet<SolvedType>>,
}
impl ExternalSpecializations {
impl<'a> ExternalSpecializations<'a> {
pub fn new_in(arena: &'a Bump) -> Self {
Self {
specs: BumpMap::new_in(arena),
}
}
pub fn insert(&mut self, symbol: Symbol, typ: SolvedType) {
use std::collections::hash_map::Entry::{Occupied, Vacant};
use hashbrown::hash_map::Entry::{Occupied, Vacant};
let existing = match self.specs.entry(symbol) {
Vacant(entry) => entry.insert(MutSet::default()),
@ -261,7 +261,7 @@ impl ExternalSpecializations {
}
pub fn extend(&mut self, other: Self) {
use std::collections::hash_map::Entry::{Occupied, Vacant};
use hashbrown::hash_map::Entry::{Occupied, Vacant};
for (symbol, solved_types) in other.specs {
let existing = match self.specs.entry(symbol) {
@ -276,30 +276,30 @@ impl ExternalSpecializations {
#[derive(Clone, Debug)]
pub struct Procs<'a> {
pub partial_procs: MutMap<Symbol, PartialProc<'a>>,
pub imported_module_thunks: MutSet<Symbol>,
pub module_thunks: MutSet<Symbol>,
pub partial_procs: BumpMap<'a, Symbol, PartialProc<'a>>,
pub imported_module_thunks: BumpSet<'a, Symbol>,
pub module_thunks: BumpSet<'a, Symbol>,
pub pending_specializations:
Option<MutMap<Symbol, MutMap<Layout<'a>, PendingSpecialization<'a>>>>,
pub specialized: MutMap<(Symbol, Layout<'a>), InProgressProc<'a>>,
pub call_by_pointer_wrappers: MutMap<Symbol, Symbol>,
pub runtime_errors: MutMap<Symbol, &'a str>,
pub externals_others_need: ExternalSpecializations,
pub externals_we_need: MutMap<ModuleId, ExternalSpecializations>,
Option<BumpMap<'a, Symbol, MutMap<Layout<'a>, PendingSpecialization<'a>>>>,
pub specialized: BumpMap<'a, (Symbol, Layout<'a>), InProgressProc<'a>>,
pub runtime_errors: BumpMap<'a, Symbol, &'a str>,
pub call_by_pointer_wrappers: BumpMap<'a, Symbol, Symbol>,
pub externals_others_need: ExternalSpecializations<'a>,
pub externals_we_need: BumpMap<'a, ModuleId, ExternalSpecializations<'a>>,
}
impl<'a> Default for Procs<'a> {
fn default() -> Self {
impl<'a> Procs<'a> {
pub fn new_in(arena: &'a Bump) -> Self {
Self {
partial_procs: MutMap::default(),
imported_module_thunks: MutSet::default(),
module_thunks: MutSet::default(),
pending_specializations: Some(MutMap::default()),
specialized: MutMap::default(),
runtime_errors: MutMap::default(),
call_by_pointer_wrappers: MutMap::default(),
externals_we_need: MutMap::default(),
externals_others_need: ExternalSpecializations::default(),
partial_procs: BumpMap::new_in(arena),
imported_module_thunks: BumpSet::new_in(arena),
module_thunks: BumpSet::new_in(arena),
pending_specializations: Some(BumpMap::new_in(arena)),
specialized: BumpMap::new_in(arena),
runtime_errors: BumpMap::new_in(arena),
call_by_pointer_wrappers: BumpMap::new_in(arena),
externals_we_need: BumpMap::new_in(arena),
externals_others_need: ExternalSpecializations::new_in(arena),
}
}
}
@ -681,7 +681,11 @@ impl<'a> Procs<'a> {
}
fn add_pending<'a>(
pending_specializations: &mut MutMap<Symbol, MutMap<Layout<'a>, PendingSpecialization<'a>>>,
pending_specializations: &mut BumpMap<
'a,
Symbol,
MutMap<Layout<'a>, PendingSpecialization<'a>>,
>,
symbol: Symbol,
layout: Layout<'a>,
pending: PendingSpecialization<'a>,
@ -1688,7 +1692,9 @@ pub fn specialize_all<'a>(
}
}
let mut pending_specializations = procs.pending_specializations.unwrap_or_default();
let mut pending_specializations = procs
.pending_specializations
.unwrap_or_else(|| BumpMap::new_in(env.arena));
// 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!
@ -5948,10 +5954,10 @@ fn add_needed_external<'a>(
name: Symbol,
) {
// call of a function that is not in this module
use std::collections::hash_map::Entry::{Occupied, Vacant};
use hashbrown::hash_map::Entry::{Occupied, Vacant};
let existing = match procs.externals_we_need.entry(name.module_id()) {
Vacant(entry) => entry.insert(ExternalSpecializations::default()),
Vacant(entry) => entry.insert(ExternalSpecializations::new_in(env.arena)),
Occupied(entry) => entry.into_mut(),
};

View File

@ -84,7 +84,7 @@ mod test_reporting {
let arena = Bump::new();
// Compile and add all the Procs before adding main
let mut procs = Procs::default();
let mut procs = Procs::new_in(&arena);
let mut ident_ids = interns.all_ident_ids.remove(&home).unwrap();
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr