Skip to content

Commit 05c09cb

Browse files
committed
Move the Lock into symbol::Interner
This makes it easier to make the symbol interner (near) lock free in case of concurrent accesses in the future.
1 parent 2c7bc5e commit 05c09cb

File tree

3 files changed

+21
-16
lines changed

3 files changed

+21
-16
lines changed

compiler/rustc_span/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mod tests;
7878
// threads within the compilation session, but is not accessible outside the
7979
// session.
8080
pub struct SessionGlobals {
81-
symbol_interner: Lock<symbol::Interner>,
81+
symbol_interner: symbol::Interner,
8282
span_interner: Lock<span_encoding::SpanInterner>,
8383
hygiene_data: Lock<hygiene::HygieneData>,
8484
source_map: Lock<Option<Lrc<SourceMap>>>,
@@ -87,7 +87,7 @@ pub struct SessionGlobals {
8787
impl SessionGlobals {
8888
pub fn new(edition: Edition) -> SessionGlobals {
8989
SessionGlobals {
90-
symbol_interner: Lock::new(symbol::Interner::fresh()),
90+
symbol_interner: symbol::Interner::fresh(),
9191
span_interner: Lock::new(span_encoding::SpanInterner::default()),
9292
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
9393
source_map: Lock::new(None),

compiler/rustc_span/src/symbol.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use rustc_arena::DroplessArena;
66
use rustc_data_structures::fx::FxHashMap;
77
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
8+
use rustc_data_structures::sync::Lock;
89
use rustc_macros::HashStable_Generic;
910
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
1011

@@ -1696,6 +1697,9 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
16961697
}
16971698
}
16981699

1700+
#[derive(Default)]
1701+
pub(crate) struct Interner(Lock<InternerInner>);
1702+
16991703
// The `&'static str`s in this type actually point into the arena.
17001704
//
17011705
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
@@ -1705,45 +1709,46 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
17051709
// This type is private to prevent accidentally constructing more than one `Interner` on the same
17061710
// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
17071711
#[derive(Default)]
1708-
pub(crate) struct Interner {
1712+
struct InternerInner {
17091713
arena: DroplessArena,
17101714
names: FxHashMap<&'static str, Symbol>,
17111715
strings: Vec<&'static str>,
17121716
}
17131717

17141718
impl Interner {
17151719
fn prefill(init: &[&'static str]) -> Self {
1716-
Interner {
1720+
Interner(Lock::new(InternerInner {
17171721
strings: init.into(),
17181722
names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
17191723
..Default::default()
1720-
}
1724+
}))
17211725
}
17221726

17231727
#[inline]
1724-
pub fn intern(&mut self, string: &str) -> Symbol {
1725-
if let Some(&name) = self.names.get(string) {
1728+
pub(crate) fn intern(&self, string: &str) -> Symbol {
1729+
let mut inner = self.0.lock();
1730+
if let Some(&name) = inner.names.get(string) {
17261731
return name;
17271732
}
17281733

1729-
let name = Symbol::new(self.strings.len() as u32);
1734+
let name = Symbol::new(inner.strings.len() as u32);
17301735

17311736
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
17321737
// UTF-8.
17331738
let string: &str =
1734-
unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
1739+
unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
17351740
// It is safe to extend the arena allocation to `'static` because we only access
17361741
// these while the arena is still alive.
17371742
let string: &'static str = unsafe { &*(string as *const str) };
1738-
self.strings.push(string);
1739-
self.names.insert(string, name);
1743+
inner.strings.push(string);
1744+
inner.names.insert(string, name);
17401745
name
17411746
}
17421747

17431748
// Get the symbol as a string. `Symbol::as_str()` should be used in
17441749
// preference to this function.
1745-
pub fn get(&self, symbol: Symbol) -> &str {
1746-
self.strings[symbol.0.as_usize()]
1750+
pub(crate) fn get(&self, symbol: Symbol) -> &str {
1751+
self.0.lock().strings[symbol.0.as_usize()]
17471752
}
17481753
}
17491754

@@ -1875,8 +1880,8 @@ impl Ident {
18751880
}
18761881

18771882
#[inline]
1878-
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
1879-
with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
1883+
fn with_interner<T, F: FnOnce(&Interner) -> T>(f: F) -> T {
1884+
with_session_globals(|session_globals| f(&session_globals.symbol_interner))
18801885
}
18811886

18821887
/// An alternative to [`Symbol`], useful when the chars within the symbol need to

compiler/rustc_span/src/symbol/tests.rs

Lines changed: 1 addition & 1 deletion
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 mut i: Interner = Interner::default();
7+
let i = Interner::default();
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)