diff --git a/crates/fayalite/src/intern.rs b/crates/fayalite/src/intern.rs index b68140b..4969bcb 100644 --- a/crates/fayalite/src/intern.rs +++ b/crates/fayalite/src/intern.rs @@ -605,7 +605,14 @@ pub struct Interner { impl Interner { fn get() -> &'static Interner { static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); - TYPE_ID_MAP.get_or_insert_default() + thread_local! { + static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() }; + } + TYPE_ID_MAP_CACHE.with(|cache| { + cache.get_or_insert_with(|| { + TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default())) + }) + }) } } @@ -1035,10 +1042,17 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy { fn inner(self, input: Self::InputRef<'_>) -> Self::Output; fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output { static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); + thread_local! { + static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() }; + } let map: &RwLock<( DefaultBuildHasher, HashTable<(Self, Self::InputOwned, Self::Output)>, - )> = TYPE_ID_MAP.get_or_insert_default(); + )> = TYPE_ID_MAP_CACHE.with(|cache| { + cache.get_or_insert_with(|| { + TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default())) + }) + }); fn hash_eq_key<'a, 'b, T: MemoizeGeneric>( this: &'a T, input: T::InputRef<'b>, diff --git a/crates/fayalite/src/intern/type_map.rs b/crates/fayalite/src/intern/type_map.rs index 945116b..03b68e3 100644 --- a/crates/fayalite/src/intern/type_map.rs +++ b/crates/fayalite/src/intern/type_map.rs @@ -87,20 +87,23 @@ impl TypeIdMap { fn insert_slow( &self, type_id: TypeId, - make: fn() -> Box, + make: impl FnOnce() -> &'static (dyn Any + Sync + Send), ) -> &'static (dyn Any + Sync + Send) { - let value = Box::leak(make()); + let value = make(); let mut write_guard = self.0.write().unwrap(); *write_guard.entry(type_id).or_insert(value) } - pub(crate) fn get_or_insert_default(&self) -> &T { + pub(crate) fn get_or_insert_with( + &self, + make: impl FnOnce() -> &'static T, + ) -> &'static T { let type_id = TypeId::of::(); let read_guard = self.0.read().unwrap(); let retval = read_guard.get(&type_id).map(|v| *v); drop(read_guard); let retval = match retval { Some(retval) => retval, - None => self.insert_slow(type_id, move || Box::new(T::default())), + None => self.insert_slow(type_id, move || make()), }; retval.downcast_ref().expect("known to have correct TypeId") }