perf: cache subtype relation judgement

This commit is contained in:
Shunsuke Shibayama 2024-09-26 23:49:32 +09:00
parent 544fee8d59
commit c965ea2c5b
5 changed files with 75 additions and 3 deletions

View file

@ -260,6 +260,26 @@ impl<K: Eq, V> Dict<K, V> {
.find(|(k, _)| (*k).borrow() == key)
.map(|(_, v)| v)
}
/// K: interior-mutable
/// This method is O(1) but may fail to get the value.
pub fn force_o1_get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q> + Hash,
Q: Hash + Eq + ?Sized,
{
self.dict.get(key)
}
/// K: interior-mutable
/// This method is O(1) but may fail to get the value.
pub fn force_o1_get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
K: Borrow<Q> + Hash,
Q: Hash + Eq + ?Sized,
{
self.dict.get_mut(key)
}
}
impl<K: Eq, V: Eq> Dict<K, V> {

View file

@ -234,12 +234,24 @@ impl Context {
/// make judgments that include supertypes in the same namespace & take into account glue patches
/// 同一名前空間にある上位型を含めた判定&接着パッチを考慮した判定を行う
fn nominal_supertype_of(&self, lhs: &Type, rhs: &Type) -> bool {
if let Some(res) = self.shared().type_cache.get(lhs, rhs) {
return res.is_subtype;
}
if let (Absolutely, judge) = self.classes_supertype_of(lhs, rhs) {
self.shared()
.type_cache
.insert(lhs.clone(), rhs.clone(), judge);
return judge;
}
if let (Absolutely, judge) = self.traits_supertype_of(lhs, rhs) {
self.shared()
.type_cache
.insert(lhs.clone(), rhs.clone(), judge);
return judge;
}
self.shared()
.type_cache
.insert(lhs.clone(), rhs.clone(), false);
false
}

View file

@ -2042,8 +2042,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
return None;
}
}
(FreeVar(fv), _) if fv.is_linked() => return self.unify(&fv.crack(), rhs),
(_, FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, &fv.crack()),
(FreeVar(fv), _) if fv.is_linked() => return self.unify(&fv.unwrap_linked(), rhs),
(_, FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, &fv.unwrap_linked()),
// TODO: unify(?T, ?U) ?
(FreeVar(_), FreeVar(_)) => {}
(FreeVar(fv), _) if fv.constraint_is_sandwiched() => {

View file

@ -431,3 +431,39 @@ impl SharedGeneralizationCache {
self.0.borrow().linear_get(key).cloned()
}
}
use crate::ty::Type;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TypeRelationResult {
pub is_subtype: bool,
}
#[derive(Debug, Clone, Default)]
pub struct SupAndResult(Dict<Type, TypeRelationResult>);
#[derive(Debug, Clone, Default)]
pub struct SharedTypeRelationCache(Shared<Dict<Type, SupAndResult>>);
impl SharedTypeRelationCache {
pub fn new() -> Self {
Self(Shared::new(Dict::new()))
}
pub fn insert(&self, sub: Type, sup: Type, is_subtype: bool) {
self.0
.borrow_mut()
.entry(sub)
.or_default()
.0
.insert(sup, TypeRelationResult { is_subtype });
}
pub fn get(&self, sub: &Type, sup: &Type) -> Option<TypeRelationResult> {
self.0
.borrow()
.force_o1_get(sub)
.and_then(|dict| dict.0.force_o1_get(sup))
.copied()
}
}

View file

@ -5,7 +5,9 @@ use erg_common::spawn::safe_yield;
use crate::context::{Context, ModuleContext};
use super::cache::{ModuleEntry, SharedGeneralizationCache, SharedModuleCache};
use super::cache::{
ModuleEntry, SharedGeneralizationCache, SharedModuleCache, SharedTypeRelationCache,
};
use super::errors::{SharedCompileErrors, SharedCompileWarnings};
use super::graph::SharedModuleGraph;
use super::impls::SharedTraitImpls;
@ -35,6 +37,7 @@ pub struct SharedCompilerResource {
pub errors: SharedCompileErrors,
pub warns: SharedCompileWarnings,
pub gen_cache: SharedGeneralizationCache,
pub type_cache: SharedTypeRelationCache,
}
impl SharedCompilerResource {
@ -52,6 +55,7 @@ impl SharedCompilerResource {
errors: SharedCompileErrors::new(),
warns: SharedCompileWarnings::new(),
gen_cache: SharedGeneralizationCache::new(),
type_cache: SharedTypeRelationCache::new(),
};
Context::init_builtins(cfg, self_.clone());
self_