diff --git a/src/eval/expr.rs b/src/eval/expr.rs index f3c3cca1..af762e20 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -268,9 +268,8 @@ impl Engine { }; if let Some(f) = func { - if cache.filter.is_absent(hash) { + if cache.filter.is_absent_and_set(hash) { // Do not cache "one-hit wonders" - cache.filter.mark(hash); local_entry = CallableFunction::from_fn_builtin(f); &local_entry } else { diff --git a/src/func/call.rs b/src/func/call.rs index 41aa19a6..7adcded8 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -237,9 +237,8 @@ impl Engine { func: f.clone(), source: s.map(|s| Box::new(s.into())), }); - return if cache.filter.is_absent(hash) { + return if cache.filter.is_absent_and_set(hash) { // Do not cache "one-hit wonders" - cache.filter.mark(hash); *local_entry = new_entry; local_entry.as_ref() } else { @@ -299,9 +298,8 @@ impl Engine { } }); - return if cache.filter.is_absent(hash) { + return if cache.filter.is_absent_and_set(hash) { // Do not cache "one-hit wonders" - cache.filter.mark(hash); *local_entry = builtin; local_entry.as_ref() } else { diff --git a/src/types/bloom_filter.rs b/src/types/bloom_filter.rs index d7bc9f25..61a1d360 100644 --- a/src/types/bloom_filter.rs +++ b/src/types/bloom_filter.rs @@ -23,6 +23,7 @@ pub struct BloomFilterU64([usize; SIZE]); impl BloomFilterU64 { /// Get the bit position of a `u64` hash value. #[inline(always)] + #[must_use] const fn calc_hash(value: u64) -> (usize, usize) { let hash = (value & 0x00ff) as usize; (hash / 64, 0x01 << (hash % 64)) @@ -37,7 +38,7 @@ impl BloomFilterU64 { #[inline(always)] #[must_use] pub fn is_empty(&self) -> bool { - self.0.iter().all(|&v| v == 0) + self.0 == [0; SIZE] } /// Clear this [`BloomFilterU64`]. #[inline(always)] @@ -46,7 +47,7 @@ impl BloomFilterU64 { self } /// Mark a `u64` hash into this [`BloomFilterU64`]. - #[inline(always)] + #[inline] pub fn mark(&mut self, hash: u64) -> &mut Self { let (offset, mask) = Self::calc_hash(hash); self.0[offset] |= mask; @@ -54,10 +55,21 @@ impl BloomFilterU64 { } /// Is a `u64` hash definitely absent from this [`BloomFilterU64`]? #[inline] + #[must_use] pub const fn is_absent(&self, hash: u64) -> bool { let (offset, mask) = Self::calc_hash(hash); (self.0[offset] & mask) == 0 } + /// If a `u64` hash is absent from this [`BloomFilterU64`], return `true` and then mark it. + /// Otherwise return `false`. + #[inline] + #[must_use] + pub fn is_absent_and_set(&mut self, hash: u64) -> bool { + let (offset, mask) = Self::calc_hash(hash); + let result = (self.0[offset] & mask) == 0; + self.0[offset] |= mask; + result + } } impl Add for &BloomFilterU64 {