Skip to content

macro_rules: Add an expansion-local cache to span marker #119693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,28 @@ use rustc_errors::DiagnosticBuilder;
use rustc_errors::{pluralize, PResult};
use rustc_span::hygiene::{LocalExpnId, Transparency};
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::Span;
use rustc_span::{Span, SyntaxContext};

use smallvec::{smallvec, SmallVec};
use std::mem;

// 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 {
const VISIT_TOKENS: bool = true;

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);
}
}

Expand Down Expand Up @@ -123,7 +132,7 @@ pub(super) fn transcribe<'a>(
// again, and we are done transcribing.
let mut result: Vec<TokenTree> = 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 {
// Look at the last frame on the stack.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ impl SyntaxContext {
}

/// 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))
}

Expand Down