abstract checking of is module thunk

This commit is contained in:
Folkert 2021-10-22 22:16:52 +02:00
parent 6400baf2c1
commit 6a6ea64323
2 changed files with 35 additions and 28 deletions

View file

@ -3953,7 +3953,6 @@ fn make_specializations<'a>(
procs.partial_procs = procs_base.partial_procs; procs.partial_procs = procs_base.partial_procs;
procs.module_thunks.extend(procs_base.module_thunks); procs.module_thunks.extend(procs_base.module_thunks);
procs.pending_specializations = Some(procs_base.pending_specializations);
procs.runtime_errors = procs_base.runtime_errors; procs.runtime_errors = procs_base.runtime_errors;
procs.imported_module_thunks = procs_base.imported_module_thunks; procs.imported_module_thunks = procs_base.imported_module_thunks;
@ -3964,6 +3963,7 @@ fn make_specializations<'a>(
&mut mono_env, &mut mono_env,
procs, procs,
specializations_we_must_make, specializations_we_must_make,
procs_base.pending_specializations,
&mut layout_cache, &mut layout_cache,
); );

View file

@ -453,6 +453,10 @@ impl<'a> Procs<'a> {
self.imported_module_thunks.iter().any(|x| *x == symbol) self.imported_module_thunks.iter().any(|x| *x == symbol)
} }
fn is_module_thunk(&self, symbol: Symbol) -> bool {
self.module_thunks.iter().any(|x| *x == symbol)
}
pub fn get_specialized_procs_without_rc( pub fn get_specialized_procs_without_rc(
self, self,
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
@ -555,12 +559,13 @@ impl<'a> Procs<'a> {
}; };
} }
if self.is_module_thunk(symbol) {
debug_assert!(layout.arguments.is_empty());
}
match &mut self.pending_specializations { match &mut self.pending_specializations {
Some(pending_specializations) => { Some(pending_specializations) => {
// register the pending specialization, so this gets code genned later // register the pending specialization, so this gets code genned later
if self.module_thunks.contains(&symbol) {
debug_assert!(layout.arguments.is_empty());
}
add_pending(pending_specializations, symbol, layout, pending); add_pending(pending_specializations, symbol, layout, pending);
self.partial_procs.insert(symbol, partial_proc); self.partial_procs.insert(symbol, partial_proc);
@ -584,7 +589,7 @@ impl<'a> Procs<'a> {
proc.name proc.name
); );
if self.module_thunks.contains(&proc.name) { if self.is_module_thunk(proc.name) {
debug_assert!(top_level.arguments.is_empty()); debug_assert!(top_level.arguments.is_empty());
} }
@ -623,16 +628,17 @@ impl<'a> Procs<'a> {
return; return;
} }
// register the pending specialization, so this gets code genned later
if self.module_thunks.contains(&name) {
debug_assert!(layout.arguments.is_empty());
}
// This should only be called when pending_specializations is Some. // This should only be called when pending_specializations is Some.
// Otherwise, it's being called in the wrong pass! // Otherwise, it's being called in the wrong pass!
match &mut self.pending_specializations { match &mut self.pending_specializations {
Some(pending_specializations) => { Some(pending_specializations) => {
let pending = PendingSpecialization::from_var(env.arena, env.subs, fn_var); let pending = PendingSpecialization::from_var(env.arena, env.subs, fn_var);
// register the pending specialization, so this gets code genned later
if self.module_thunks.contains(&name) {
debug_assert!(layout.arguments.is_empty());
}
add_pending(pending_specializations, name, layout, pending) add_pending(pending_specializations, name, layout, pending)
} }
None => { None => {
@ -1675,15 +1681,18 @@ 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>,
mut pending_specializations: 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_all_help(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!
let opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
for (name, by_layout) in opt_pending_specializations.into_iter().flatten() { let opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
pending_specializations.extend(opt_pending_specializations.into_iter().flatten());
for (name, by_layout) in pending_specializations {
for (outside_layout, pending) in by_layout.into_iter() { for (outside_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!
@ -1718,7 +1727,7 @@ pub fn specialize_all<'a>(
// TODO thiscode is duplicated elsewhere // TODO thiscode is duplicated elsewhere
let top_level = ProcLayout::from_raw(env.arena, layout); let top_level = ProcLayout::from_raw(env.arena, layout);
if procs.module_thunks.contains(&proc.name) { if procs.is_module_thunk(proc.name) {
debug_assert!( debug_assert!(
top_level.arguments.is_empty(), top_level.arguments.is_empty(),
"{:?} from {:?}", "{:?} from {:?}",
@ -1798,7 +1807,7 @@ fn specialize_all_help<'a>(
Ok((proc, layout)) => { Ok((proc, layout)) => {
let top_level = ProcLayout::from_raw(env.arena, layout); let top_level = ProcLayout::from_raw(env.arena, layout);
if procs.module_thunks.contains(&name) { if procs.is_module_thunk(name) {
debug_assert!(top_level.arguments.is_empty()); debug_assert!(top_level.arguments.is_empty());
} }
@ -2498,7 +2507,7 @@ where
.raw_from_var(env.arena, fn_var, env.subs) .raw_from_var(env.arena, fn_var, env.subs)
.unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err)); .unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err));
let raw = if procs.module_thunks.contains(&proc_name) { let raw = if procs.is_module_thunk(proc_name) {
match raw { match raw {
RawFunctionLayout::Function(_, lambda_set, _) => { RawFunctionLayout::Function(_, lambda_set, _) => {
RawFunctionLayout::ZeroArgumentThunk(Layout::LambdaSet(lambda_set)) RawFunctionLayout::ZeroArgumentThunk(Layout::LambdaSet(lambda_set))
@ -2601,7 +2610,7 @@ fn specialize_naked_symbol<'a>(
hole: &'a Stmt<'a>, hole: &'a Stmt<'a>,
symbol: Symbol, symbol: Symbol,
) -> Stmt<'a> { ) -> Stmt<'a> {
if procs.module_thunks.contains(&symbol) { if procs.is_module_thunk(symbol) {
let partial_proc = procs.partial_procs.get(&symbol).unwrap(); let partial_proc = procs.partial_procs.get(&symbol).unwrap();
let fn_var = partial_proc.annotation; let fn_var = partial_proc.annotation;
@ -6163,7 +6172,7 @@ fn reuse_function_symbol<'a>(
closure_data, closure_data,
env.arena.alloc(result), env.arena.alloc(result),
) )
} else if procs.module_thunks.contains(&original) { } else if procs.is_module_thunk(original) {
// this is a 0-argument thunk // this is a 0-argument thunk
// TODO suspicious // TODO suspicious
@ -6359,7 +6368,7 @@ fn call_by_name<'a>(
evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args) evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args)
} }
Ok(RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout)) => { Ok(RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout)) => {
if procs.module_thunks.contains(&proc_name) { if procs.is_module_thunk(proc_name) {
if loc_args.is_empty() { if loc_args.is_empty() {
call_by_name_module_thunk( call_by_name_module_thunk(
env, env,
@ -6436,7 +6445,7 @@ fn call_by_name<'a>(
} }
} }
Ok(RawFunctionLayout::ZeroArgumentThunk(ret_layout)) => { Ok(RawFunctionLayout::ZeroArgumentThunk(ret_layout)) => {
if procs.module_thunks.contains(&proc_name) { if procs.is_module_thunk(proc_name) {
// here we turn a call to a module thunk into forcing of that thunk // here we turn a call to a module thunk into forcing of that thunk
call_by_name_module_thunk( call_by_name_module_thunk(
env, env,
@ -6590,14 +6599,14 @@ fn call_by_name_help<'a>(
// the same specialization independently), we work through the // the same specialization independently), we work through the
// queue of pending specializations to complete each specialization // queue of pending specializations to complete each specialization
// exactly once. // exactly once.
if procs.is_module_thunk(proc_name) {
debug_assert!(top_level_layout.arguments.is_empty());
}
match &mut procs.pending_specializations { match &mut procs.pending_specializations {
Some(pending_specializations) => { Some(pending_specializations) => {
debug_assert!(!env.is_imported_symbol(proc_name)); debug_assert!(!env.is_imported_symbol(proc_name));
if procs.module_thunks.contains(&proc_name) {
debug_assert!(top_level_layout.arguments.is_empty());
}
// register the pending specialization, so this gets code genned later // register the pending specialization, so this gets code genned later
add_pending( add_pending(
pending_specializations, pending_specializations,
@ -6725,8 +6734,6 @@ fn call_by_name_module_thunk<'a>(
) -> Stmt<'a> { ) -> Stmt<'a> {
debug_assert!(!env.is_imported_symbol(proc_name)); debug_assert!(!env.is_imported_symbol(proc_name));
// debug_assert!(!procs.module_thunks.contains(&proc_name), "{:?}", proc_name);
let top_level_layout = ProcLayout::new(env.arena, &[], *ret_layout); let top_level_layout = ProcLayout::new(env.arena, &[], *ret_layout);
let inner_layout = *ret_layout; let inner_layout = *ret_layout;
@ -6751,14 +6758,14 @@ fn call_by_name_module_thunk<'a>(
// the same specialization independently), we work through the // the same specialization independently), we work through the
// queue of pending specializations to complete each specialization // queue of pending specializations to complete each specialization
// exactly once. // exactly once.
if procs.is_module_thunk(proc_name) {
debug_assert!(top_level_layout.arguments.is_empty());
}
match &mut procs.pending_specializations { match &mut procs.pending_specializations {
Some(pending_specializations) => { Some(pending_specializations) => {
debug_assert!(!env.is_imported_symbol(proc_name)); debug_assert!(!env.is_imported_symbol(proc_name));
if procs.module_thunks.contains(&proc_name) {
debug_assert!(top_level_layout.arguments.is_empty());
}
// register the pending specialization, so this gets code genned later // register the pending specialization, so this gets code genned later
add_pending( add_pending(
pending_specializations, pending_specializations,