Auto merge of #119693 - petrochenkov:cachemark, r=cjgillot
macro_rules: Add an expansion-local cache to span marker Most tokens in a macro body typically have the same syntax context. So the cache should usually be hit. This change can either be combined with https://github.com/rust-lang/rust/pull/119689, or serve as its alternative, depending on perf results.
This commit is contained in:
commit
0ee9cfd54d
@ -13,19 +13,28 @@
|
|||||||
use rustc_errors::{pluralize, PResult};
|
use rustc_errors::{pluralize, PResult};
|
||||||
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||||
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
|
||||||
use rustc_span::Span;
|
use rustc_span::{Span, SyntaxContext};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
// A Marker adds the given mark to the syntax context.
|
// A Marker adds the given mark to the syntax context.
|
||||||
struct Marker(LocalExpnId, Transparency);
|
struct Marker(LocalExpnId, Transparency, FxHashMap<SyntaxContext, SyntaxContext>);
|
||||||
|
|
||||||
impl MutVisitor for Marker {
|
impl MutVisitor for Marker {
|
||||||
const VISIT_TOKENS: bool = true;
|
const VISIT_TOKENS: bool = true;
|
||||||
|
|
||||||
fn visit_span(&mut self, span: &mut Span) {
|
fn visit_span(&mut self, span: &mut Span) {
|
||||||
*span = span.apply_mark(self.0.to_expn_id(), self.1)
|
// `apply_mark` is a relatively expensive operation, both due to taking hygiene lock, and
|
||||||
|
// by itself. All tokens in a macro body typically have the same syntactic context, unless
|
||||||
|
// it's some advanced case with macro-generated macros. So if we cache the marked version
|
||||||
|
// of that context once, we'll typically have a 100% cache hit rate after that.
|
||||||
|
let Marker(expn_id, transparency, ref mut cache) = *self;
|
||||||
|
let data = span.data();
|
||||||
|
let marked_ctxt = *cache
|
||||||
|
.entry(data.ctxt)
|
||||||
|
.or_insert_with(|| data.ctxt.apply_mark(expn_id.to_expn_id(), transparency));
|
||||||
|
*span = data.with_ctxt(marked_ctxt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +132,7 @@ pub(super) fn transcribe<'a>(
|
|||||||
// again, and we are done transcribing.
|
// again, and we are done transcribing.
|
||||||
let mut result: Vec<TokenTree> = Vec::new();
|
let mut result: Vec<TokenTree> = Vec::new();
|
||||||
let mut result_stack = Vec::new();
|
let mut result_stack = Vec::new();
|
||||||
let mut marker = Marker(cx.current_expansion.id, transparency);
|
let mut marker = Marker(cx.current_expansion.id, transparency, Default::default());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Look at the last frame on the stack.
|
// Look at the last frame on the stack.
|
||||||
|
@ -658,7 +658,7 @@ pub(crate) const fn from_u32(raw: u32) -> SyntaxContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extend a syntax context with a given expansion and transparency.
|
/// Extend a syntax context with a given expansion and transparency.
|
||||||
pub(crate) fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
|
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
|
||||||
HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
|
HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user