From a47fb35c0ea7e5715e303b236e8b30d10e3965d5 Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 4 Sep 2023 14:04:39 +0800 Subject: [PATCH] fix(resolver): fix collision on hash entries (#850) --- crates/oxc_resolver/src/cache.rs | 60 ++++++++++++++------------------ 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/crates/oxc_resolver/src/cache.rs b/crates/oxc_resolver/src/cache.rs index 04cd35676..93706bffb 100644 --- a/crates/oxc_resolver/src/cache.rs +++ b/crates/oxc_resolver/src/cache.rs @@ -1,5 +1,6 @@ use once_cell::sync::OnceCell as OnceLock; use std::{ + borrow::Borrow, convert::AsRef, hash::{BuildHasherDefault, Hash, Hasher}, ops::Deref, @@ -7,7 +8,7 @@ use std::{ sync::Arc, }; -use dashmap::DashMap; +use dashmap::{DashMap, DashSet}; use rustc_hash::FxHasher; use crate::{ @@ -17,24 +18,8 @@ use crate::{ #[derive(Default)] pub struct Cache { pub(crate) fs: Fs, - // Using IdentityHasher to avoid double hashing in the `get` + `insert` case. - cache: DashMap>, - tsconfigs: DashMap, BuildHasherDefault>, -} - -#[derive(Default)] -struct IdentityHasher(u64); - -impl Hasher for IdentityHasher { - fn write(&mut self, _: &[u8]) { - unreachable!("Invalid use of IdentityHasher") - } - fn write_u64(&mut self, n: u64) { - self.0 = n; - } - fn finish(&self) -> u64 { - self.0 - } + cache: DashSet>, + tsconfigs: DashMap, BuildHasherDefault>, } impl Cache { @@ -48,18 +33,13 @@ impl Cache { } pub fn value(&self, path: &Path) -> CachedPath { - let hash = { - let mut hasher = FxHasher::default(); - path.hash(&mut hasher); - hasher.finish() - }; - if let Some(cache_entry) = self.cache.get(&hash) { - return cache_entry.value().clone(); + if let Some(cache_entry) = self.cache.get(path) { + return cache_entry.clone(); } let parent = path.parent().map(|p| self.value(p)); let data = CachedPath(Arc::new(CachedPathImpl::new(path.to_path_buf().into_boxed_path(), parent))); - self.cache.insert(hash, data.clone()); + self.cache.insert(data.clone()); data } @@ -68,13 +48,8 @@ impl Cache { tsconfig_path: &Path, callback: impl FnOnce(&mut TsConfig) -> Result<(), ResolveError>, // callback for modifying tsconfig with `extends` ) -> Result, ResolveError> { - let hash = { - let mut hasher = FxHasher::default(); - tsconfig_path.hash(&mut hasher); - hasher.finish() - }; self.tsconfigs - .entry(hash) + .entry(tsconfig_path.to_path_buf()) .or_try_insert_with(|| { let mut tsconfig_string = self .fs @@ -94,6 +69,19 @@ impl Cache { #[derive(Clone)] pub struct CachedPath(Arc); +impl Hash for CachedPath { + fn hash(&self, state: &mut H) { + self.0.path.hash(state); + } +} + +impl PartialEq for CachedPath { + fn eq(&self, other: &Self) -> bool { + self.0.path == other.0.path + } +} +impl Eq for CachedPath {} + impl Deref for CachedPath { type Target = CachedPathImpl; @@ -102,6 +90,12 @@ impl Deref for CachedPath { } } +impl Borrow for CachedPath { + fn borrow(&self) -> &Path { + &self.0.path + } +} + impl AsRef for CachedPath { fn as_ref(&self) -> &CachedPathImpl { self.0.as_ref()