diff options
Diffstat (limited to 'tvix/eval')
-rw-r--r-- | tvix/eval/Cargo.toml | 1 | ||||
-rw-r--r-- | tvix/eval/src/value/string.rs | 27 |
2 files changed, 21 insertions, 7 deletions
diff --git a/tvix/eval/Cargo.toml b/tvix/eval/Cargo.toml index 9637165e8500..70a356376622 100644 --- a/tvix/eval/Cargo.toml +++ b/tvix/eval/Cargo.toml @@ -35,6 +35,7 @@ sha1 = "0.10.6" md-5 = "0.10.6" data-encoding = "2.6.0" rustc-hash = "2.0.0" +nohash-hasher = "0.2.0" [dev-dependencies] criterion = "0.5" diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string.rs index 0365f5a9be77..247d23a7c895 100644 --- a/tvix/eval/src/value/string.rs +++ b/tvix/eval/src/value/string.rs @@ -4,18 +4,20 @@ //! level, allowing us to shave off some memory overhead and only //! paying the cost when creating new strings. use bstr::{BStr, BString, ByteSlice, Chars}; +use nohash_hasher::BuildNoHashHasher; use rnix::ast; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashSet; +use rustc_hash::FxHasher; use std::alloc::dealloc; use std::alloc::{alloc, handle_alloc_error, Layout}; use std::borrow::{Borrow, Cow}; use std::cell::RefCell; use std::ffi::c_void; use std::fmt::{self, Debug, Display}; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr::{self, NonNull}; -use std::{mem, slice}; +use std::slice; use serde::de::{Deserializer, Visitor}; use serde::{Deserialize, Serialize}; @@ -399,22 +401,33 @@ impl NixStringInner { #[derive(Default)] struct InternerInner { - map: FxHashMap<&'static [u8], NonNull<c_void>>, + #[allow(clippy::disallowed_types)] // Not using the default hasher + map: std::collections::HashMap<u64, NonNull<c_void>, BuildNoHashHasher<u64>>, #[cfg(feature = "no_leak")] + #[allow(clippy::disallowed_types)] // Not using the default hasher interned_strings: FxHashSet<NonNull<c_void>>, } unsafe impl Send for InternerInner {} +fn hash<T>(s: T) -> u64 +where + T: Hash, +{ + let mut hasher = FxHasher::default(); + s.hash(&mut hasher); + hasher.finish() +} + impl InternerInner { pub fn intern(&mut self, s: &[u8]) -> NixString { - if let Some(s) = self.map.get(s) { + let hash = hash(s); + if let Some(s) = self.map.get(&hash) { return NixString(*s); } let string = NixString::new_inner(s, None); - self.map - .insert(unsafe { mem::transmute(string.as_bytes()) }, string.0); + self.map.insert(hash, string.0); #[cfg(feature = "no_leak")] self.interned_strings.insert(string.0); string |