From 49843b2a13f2cf4c497cd583af1134d0ec47154f Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Tue, 17 Dec 2024 22:59:54 +0100 Subject: [PATCH] proc_macro bridge: remove fxhash --- library/proc_macro/src/bridge/fxhash.rs | 113 ------------------------ library/proc_macro/src/bridge/handle.rs | 6 +- library/proc_macro/src/bridge/mod.rs | 7 +- library/proc_macro/src/bridge/symbol.rs | 4 +- 4 files changed, 9 insertions(+), 121 deletions(-) delete mode 100644 library/proc_macro/src/bridge/fxhash.rs diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs deleted file mode 100644 index 74a41451825ff..0000000000000 --- a/library/proc_macro/src/bridge/fxhash.rs +++ /dev/null @@ -1,113 +0,0 @@ -//! This is a copy of the `rustc_hash` crate, adapted to work as a module. -//! -//! If in the future it becomes more reasonable to add dependencies to -//! `proc_macro`, this module should be removed and replaced with a dependency -//! on the `rustc_hash` crate. - -use std::collections::HashMap; -use std::hash::{BuildHasherDefault, Hasher}; -use std::ops::BitXor; - -/// Type alias for a hashmap using the `fx` hash algorithm. -pub type FxHashMap = HashMap>; - -/// A speedy hash algorithm for use within rustc. The hashmap in alloc by -/// default uses SipHash which isn't quite as speedy as we want. In the compiler -/// we're not really worried about DOS attempts, so we use a fast -/// non-cryptographic hash. -/// -/// This is the same as the algorithm used by Firefox -- which is a homespun -/// one not based on any widely-known algorithm -- though modified to produce -/// 64-bit hash values instead of 32-bit hash values. It consistently -/// out-performs an FNV-based hash within rustc itself -- the collision rate is -/// similar or slightly worse than FNV, but the speed of the hash function -/// itself is much higher because it works on up to 8 bytes at a time. -pub struct FxHasher { - hash: usize, -} - -#[cfg(target_pointer_width = "32")] -const K: usize = 0x9e3779b9; -#[cfg(target_pointer_width = "64")] -const K: usize = 0x517cc1b727220a95; - -impl Default for FxHasher { - #[inline] - fn default() -> FxHasher { - FxHasher { hash: 0 } - } -} - -impl FxHasher { - #[inline] - fn add_to_hash(&mut self, i: usize) { - self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K); - } -} - -impl Hasher for FxHasher { - #[inline] - fn write(&mut self, mut bytes: &[u8]) { - #[cfg(target_pointer_width = "32")] - let read_usize = |bytes: &[u8]| u32::from_ne_bytes(bytes[..4].try_into().unwrap()); - #[cfg(target_pointer_width = "64")] - let read_usize = |bytes: &[u8]| u64::from_ne_bytes(bytes[..8].try_into().unwrap()); - - let mut hash = FxHasher { hash: self.hash }; - assert!(size_of::() <= 8); - while bytes.len() >= size_of::() { - hash.add_to_hash(read_usize(bytes) as usize); - bytes = &bytes[size_of::()..]; - } - if (size_of::() > 4) && (bytes.len() >= 4) { - hash.add_to_hash(u32::from_ne_bytes(bytes[..4].try_into().unwrap()) as usize); - bytes = &bytes[4..]; - } - if (size_of::() > 2) && bytes.len() >= 2 { - hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize); - bytes = &bytes[2..]; - } - if (size_of::() > 1) && !bytes.is_empty() { - hash.add_to_hash(bytes[0] as usize); - } - self.hash = hash.hash; - } - - #[inline] - fn write_u8(&mut self, i: u8) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_u16(&mut self, i: u16) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_u32(&mut self, i: u32) { - self.add_to_hash(i as usize); - } - - #[cfg(target_pointer_width = "32")] - #[inline] - fn write_u64(&mut self, i: u64) { - self.add_to_hash(i as usize); - self.add_to_hash((i >> 32) as usize); - } - - #[cfg(target_pointer_width = "64")] - #[inline] - fn write_u64(&mut self, i: u64) { - self.add_to_hash(i as usize); - } - - #[inline] - fn write_usize(&mut self, i: usize) { - self.add_to_hash(i); - } - - #[inline] - fn finish(&self) -> u64 { - self.hash as u64 - } -} diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs index 8c53bb609f60c..cbec666c82fbb 100644 --- a/library/proc_macro/src/bridge/handle.rs +++ b/library/proc_macro/src/bridge/handle.rs @@ -6,7 +6,7 @@ use std::num::NonZero; use std::ops::{Index, IndexMut}; use std::sync::atomic::{AtomicU32, Ordering}; -use super::fxhash::FxHashMap; +use super::DeterministicHashMap; pub(super) type Handle = NonZero; @@ -56,12 +56,12 @@ impl IndexMut for OwnedStore { /// Like `OwnedStore`, but avoids storing any value more than once. pub(super) struct InternedStore { owned: OwnedStore, - interner: FxHashMap, + interner: DeterministicHashMap, } impl InternedStore { pub(super) fn new(counter: &'static AtomicU32) -> Self { - InternedStore { owned: OwnedStore::new(counter), interner: FxHashMap::default() } + InternedStore { owned: OwnedStore::new(counter), interner: DeterministicHashMap::default() } } pub(super) fn alloc(&mut self, x: T) -> Handle { diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 03c3e697cfe2b..db6143d973730 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -8,13 +8,16 @@ #![deny(unsafe_code)] -use std::hash::Hash; +use std::collections::HashMap; +use std::hash::{BuildHasherDefault, DefaultHasher, Hash}; use std::ops::{Bound, Range}; use std::sync::Once; use std::{fmt, marker, mem, panic, thread}; use crate::{Delimiter, Level, Spacing}; +type DeterministicHashMap = HashMap>; + /// Higher-order macro describing the server RPC API, allowing automatic /// generation of type-safe Rust APIs, both client-side and server-side. /// @@ -155,8 +158,6 @@ pub mod client; #[allow(unsafe_code)] mod closure; #[forbid(unsafe_code)] -mod fxhash; -#[forbid(unsafe_code)] mod handle; #[macro_use] #[forbid(unsafe_code)] diff --git a/library/proc_macro/src/bridge/symbol.rs b/library/proc_macro/src/bridge/symbol.rs index 6a1cecd69fb5f..9b5e152c0be62 100644 --- a/library/proc_macro/src/bridge/symbol.rs +++ b/library/proc_macro/src/bridge/symbol.rs @@ -128,7 +128,7 @@ impl DecodeMut<'_, '_, S> for Symbol { thread_local! { static INTERNER: RefCell = RefCell::new(Interner { arena: arena::Arena::new(), - names: fxhash::FxHashMap::default(), + names: DeterministicHashMap::default(), strings: Vec::new(), // Start with a base of 1 to make sure that `NonZero` works. sym_base: NonZero::new(1).unwrap(), @@ -141,7 +141,7 @@ struct Interner { // SAFETY: These `'static` lifetimes are actually references to data owned // by the Arena. This is safe, as we never return them as static references // from `Interner`. - names: fxhash::FxHashMap<&'static str, Symbol>, + names: DeterministicHashMap<&'static str, Symbol>, strings: Vec<&'static str>, // The offset to apply to symbol names stored in the interner. This is used // to ensure that symbol names are not re-used after the interner is