Skip to content

Commit 94a36d2

Browse files
committed
Use FxIndexSet in the symbol interner.
It makes the code a little nicer. As part of this, the interner's `Default` impl is removed and `prefill` is used in a test instead.
1 parent b0a0759 commit 94a36d2

File tree

2 files changed

+12
-21
lines changed

2 files changed

+12
-21
lines changed

compiler/rustc_span/src/symbol.rs

+11-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! type, and vice versa.
44
55
use rustc_arena::DroplessArena;
6-
use rustc_data_structures::fx::FxHashMap;
6+
use rustc_data_structures::fx::FxIndexSet;
77
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
88
use rustc_data_structures::sync::Lock;
99
use rustc_macros::HashStable_Generic;
@@ -2076,43 +2076,33 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
20762076
}
20772077
}
20782078

2079-
#[derive(Default)]
20802079
pub(crate) struct Interner(Lock<InternerInner>);
20812080

20822081
// The `&'static str`s in this type actually point into the arena.
20832082
//
2084-
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
2085-
// found that to regress performance up to 2% in some cases. This might be
2086-
// revisited after further improvements to `indexmap`.
2087-
//
20882083
// This type is private to prevent accidentally constructing more than one
20892084
// `Interner` on the same thread, which makes it easy to mix up `Symbol`s
20902085
// between `Interner`s.
2091-
#[derive(Default)]
20922086
struct InternerInner {
20932087
arena: DroplessArena,
2094-
names: FxHashMap<&'static str, Symbol>,
2095-
strings: Vec<&'static str>,
2088+
strings: FxIndexSet<&'static str>,
20962089
}
20972090

20982091
impl Interner {
20992092
fn prefill(init: &[&'static str]) -> Self {
21002093
Interner(Lock::new(InternerInner {
2101-
strings: init.into(),
2102-
names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
2103-
..Default::default()
2094+
arena: Default::default(),
2095+
strings: init.iter().copied().collect(),
21042096
}))
21052097
}
21062098

21072099
#[inline]
21082100
fn intern(&self, string: &str) -> Symbol {
21092101
let mut inner = self.0.lock();
2110-
if let Some(&name) = inner.names.get(string) {
2111-
return name;
2102+
if let Some(idx) = inner.strings.get_index_of(string) {
2103+
return Symbol::new(idx as u32);
21122104
}
21132105

2114-
let name = Symbol::new(inner.strings.len() as u32);
2115-
21162106
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
21172107
// and immediately convert the clone back to `&[u8]`, all because there
21182108
// is no `inner.arena.alloc_str()` method. This is clearly safe.
@@ -2122,20 +2112,21 @@ impl Interner {
21222112
// SAFETY: we can extend the arena allocation to `'static` because we
21232113
// only access these while the arena is still alive.
21242114
let string: &'static str = unsafe { &*(string as *const str) };
2125-
inner.strings.push(string);
21262115

21272116
// This second hash table lookup can be avoided by using `RawEntryMut`,
21282117
// but this code path isn't hot enough for it to be worth it. See
21292118
// #91445 for details.
2130-
inner.names.insert(string, name);
2131-
name
2119+
let (idx, is_new) = inner.strings.insert_full(string);
2120+
debug_assert!(is_new); // due to the get_index_of check above
2121+
2122+
Symbol::new(idx as u32)
21322123
}
21332124

21342125
/// Get the symbol as a string.
21352126
///
21362127
/// [`Symbol::as_str()`] should be used in preference to this function.
21372128
fn get(&self, symbol: Symbol) -> &str {
2138-
self.0.lock().strings[symbol.0.as_usize()]
2129+
self.0.lock().strings.get_index(symbol.0.as_usize()).unwrap()
21392130
}
21402131
}
21412132

compiler/rustc_span/src/symbol/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::create_default_session_globals_then;
44

55
#[test]
66
fn interner_tests() {
7-
let i = Interner::default();
7+
let i = Interner::prefill(&[]);
88
// first one is zero:
99
assert_eq!(i.intern("dog"), Symbol::new(0));
1010
// re-use gets the same entry:

0 commit comments

Comments
 (0)