Skip to content

Commit 05d8f5f

Browse files
Use a thread-local for the symbol interner (1/2)
1 parent 3076959 commit 05d8f5f

File tree

4 files changed

+33
-17
lines changed

4 files changed

+33
-17
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/proc-macro-srv/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ tt = { path = "../tt", version = "0.0.0" }
2424
mbe = { path = "../mbe", version = "0.0.0" }
2525
paths = { path = "../paths", version = "0.0.0" }
2626
proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
27-
once_cell = "1.13.0"
2827

2928
[dev-dependencies]
3029
expect-test = "1.4.0"

crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl server::FreeFunctions for RustAnalyzer {
8383
s: &str,
8484
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
8585
// FIXME: keep track of LitKind and Suffix
86-
let symbol = SYMBOL_INTERNER.lock().unwrap().intern(s);
86+
let symbol = ThreadLocalSymbolInterner::intern(s);
8787
Ok(bridge::Literal {
8888
kind: bridge::LitKind::Err,
8989
symbol,
@@ -124,18 +124,19 @@ impl server::TokenStream for RustAnalyzer {
124124

125125
bridge::TokenTree::Ident(ident) => {
126126
// FIXME: handle raw idents
127-
let text = SYMBOL_INTERNER.lock().unwrap().get(&ident.sym).clone();
127+
let text = ThreadLocalSymbolInterner::get_cloned(&ident.sym);
128128
let ident: tt::Ident = tt::Ident { text, id: ident.span };
129129
let leaf = tt::Leaf::from(ident);
130130
let tree = TokenTree::from(leaf);
131131
Self::TokenStream::from_iter(vec![tree])
132132
}
133133

134134
bridge::TokenTree::Literal(literal) => {
135-
let symbol = SYMBOL_INTERNER.lock().unwrap().get(&literal.symbol).clone();
135+
// FIXME: remove unnecessary clones here
136+
let symbol = ThreadLocalSymbolInterner::get_cloned(&literal.symbol);
136137

137138
let text: tt::SmolStr = if let Some(suffix) = literal.suffix {
138-
let suffix = SYMBOL_INTERNER.lock().unwrap().get(&suffix).clone();
139+
let suffix = ThreadLocalSymbolInterner::get_cloned(&suffix);
139140
format!("{symbol}{suffix}").into()
140141
} else {
141142
symbol
@@ -203,7 +204,7 @@ impl server::TokenStream for RustAnalyzer {
203204
.map(|tree| match tree {
204205
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
205206
bridge::TokenTree::Ident(bridge::Ident {
206-
sym: SYMBOL_INTERNER.lock().unwrap().intern(&ident.text),
207+
sym: ThreadLocalSymbolInterner::intern(&ident.text),
207208
// FIXME: handle raw idents
208209
is_raw: false,
209210
span: ident.id,
@@ -213,7 +214,7 @@ impl server::TokenStream for RustAnalyzer {
213214
bridge::TokenTree::Literal(bridge::Literal {
214215
// FIXME: handle literal kinds
215216
kind: bridge::LitKind::Err,
216-
symbol: SYMBOL_INTERNER.lock().unwrap().intern(&lit.text),
217+
symbol: ThreadLocalSymbolInterner::intern(&lit.text),
217218
// FIXME: handle suffixes
218219
suffix: None,
219220
span: lit.id,
@@ -407,11 +408,11 @@ impl server::Server for RustAnalyzer {
407408
}
408409

409410
fn intern_symbol(ident: &str) -> Self::Symbol {
410-
SYMBOL_INTERNER.lock().unwrap().intern(&tt::SmolStr::from(ident))
411+
ThreadLocalSymbolInterner::intern(&tt::SmolStr::from(ident))
411412
}
412413

413414
fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
414-
f(SYMBOL_INTERNER.lock().unwrap().get(symbol).as_str())
415+
ThreadLocalSymbolInterner::with(symbol, |s| f(s.as_str()))
415416
}
416417
}
417418

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
//! Symbol interner for proc-macro-srv
22
3-
use once_cell::sync::Lazy;
4-
use std::{collections::HashMap, sync::Mutex};
3+
use std::{cell::RefCell, collections::HashMap};
54
use tt::SmolStr;
65

7-
pub(super) static SYMBOL_INTERNER: Lazy<Mutex<SymbolInterner>> = Lazy::new(|| Default::default());
6+
thread_local! {
7+
static SYMBOL_INTERNER: RefCell<SymbolInterner> = Default::default();
8+
}
89

910
// ID for an interned symbol.
1011
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
1112
pub struct Symbol(u32);
1213

1314
#[derive(Default)]
14-
pub(super) struct SymbolInterner {
15+
struct SymbolInterner {
1516
idents: HashMap<SmolStr, u32>,
1617
ident_data: Vec<SmolStr>,
1718
}
1819

1920
impl SymbolInterner {
20-
pub(super) fn intern(&mut self, data: &str) -> Symbol {
21+
fn intern(&mut self, data: &str) -> Symbol {
2122
if let Some(index) = self.idents.get(data) {
2223
return Symbol(*index);
2324
}
@@ -29,7 +30,23 @@ impl SymbolInterner {
2930
Symbol(index)
3031
}
3132

32-
pub(super) fn get(&self, index: &Symbol) -> &SmolStr {
33-
&self.ident_data[index.0 as usize]
33+
fn get(&self, sym: &Symbol) -> &SmolStr {
34+
&self.ident_data[sym.0 as usize]
35+
}
36+
}
37+
38+
pub(super) struct ThreadLocalSymbolInterner;
39+
40+
impl ThreadLocalSymbolInterner {
41+
pub(super) fn intern(data: &str) -> Symbol {
42+
SYMBOL_INTERNER.with(|i| i.borrow_mut().intern(data))
43+
}
44+
45+
pub(super) fn with<T>(sym: &Symbol, f: impl FnOnce(&SmolStr) -> T) -> T {
46+
SYMBOL_INTERNER.with(|i| f(i.borrow().get(sym)))
47+
}
48+
49+
pub(super) fn get_cloned(sym: &Symbol) -> SmolStr {
50+
Self::with(sym, |s| s.clone())
3451
}
3552
}

0 commit comments

Comments
 (0)