Skip to content

Commit 6b0a16a

Browse files
committed
Pre-allocate an empty Lrc<NamedMatchVec>.
This avoids some allocations.
1 parent 524d21b commit 6b0a16a

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

compiler/rustc_expand/src/mbe/macro_parser.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,11 @@ struct MatcherPos<'tt> {
155155
rustc_data_structures::static_assert_size!(MatcherPos<'_>, 104);
156156

157157
impl<'tt> MatcherPos<'tt> {
158-
fn top_level(matcher: &'tt [TokenTree]) -> Self {
158+
fn top_level(matcher: &'tt [TokenTree], empty_matches: Lrc<NamedMatchVec>) -> Self {
159159
MatcherPos {
160160
tts: matcher,
161161
idx: 0,
162-
matches: Lrc::new(smallvec![]),
162+
matches: empty_matches,
163163
seq_depth: 0,
164164
match_lo: 0,
165165
match_cur: 0,
@@ -168,7 +168,11 @@ impl<'tt> MatcherPos<'tt> {
168168
}
169169
}
170170

171-
fn sequence(parent: Box<MatcherPos<'tt>>, seq: &'tt SequenceRepetition) -> Self {
171+
fn sequence(
172+
parent: Box<MatcherPos<'tt>>,
173+
seq: &'tt SequenceRepetition,
174+
empty_matches: Lrc<NamedMatchVec>,
175+
) -> Self {
172176
let mut mp = MatcherPos {
173177
tts: &seq.tts,
174178
idx: 0,
@@ -182,7 +186,7 @@ impl<'tt> MatcherPos<'tt> {
182186
// Start with an empty vec for each metavar within the sequence. Note that `mp.seq_depth`
183187
// must have the parent's depth at this point for these `push_match` calls to work.
184188
for idx in mp.match_lo..mp.match_lo + seq.num_captures {
185-
mp.push_match(idx, MatchedSeq(Lrc::new(smallvec![])));
189+
mp.push_match(idx, MatchedSeq(empty_matches.clone()));
186190
}
187191
mp.seq_depth += 1;
188192
mp
@@ -415,11 +419,21 @@ pub struct TtParser<'tt> {
415419

416420
/// The set of mps that are waiting for the black-box parser.
417421
bb_mps: Vec<Box<MatcherPos<'tt>>>,
422+
423+
/// Pre-allocate an empty match array, so it can be cloned cheaply for macros with many rules
424+
/// that have no metavars.
425+
empty_matches: Lrc<NamedMatchVec>,
418426
}
419427

420428
impl<'tt> TtParser<'tt> {
421429
pub(super) fn new(macro_name: Ident) -> TtParser<'tt> {
422-
TtParser { macro_name, cur_mps: vec![], next_mps: vec![], bb_mps: vec![] }
430+
TtParser {
431+
macro_name,
432+
cur_mps: vec![],
433+
next_mps: vec![],
434+
bb_mps: vec![],
435+
empty_matches: Lrc::new(smallvec![]),
436+
}
423437
}
424438

425439
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -469,13 +483,17 @@ impl<'tt> TtParser<'tt> {
469483
new_mp.match_cur += seq.num_captures;
470484
new_mp.idx += 1;
471485
for idx in mp.match_cur..mp.match_cur + seq.num_captures {
472-
new_mp.push_match(idx, MatchedSeq(Lrc::new(smallvec![])));
486+
new_mp.push_match(idx, MatchedSeq(self.empty_matches.clone()));
473487
}
474488
self.cur_mps.push(new_mp);
475489
}
476490

477491
// Allow for the possibility of one or more matches of this sequence.
478-
self.cur_mps.push(box MatcherPos::sequence(mp, &seq));
492+
self.cur_mps.push(box MatcherPos::sequence(
493+
mp,
494+
&seq,
495+
self.empty_matches.clone(),
496+
));
479497
}
480498

481499
&TokenTree::MetaVarDecl(span, _, None) => {
@@ -621,7 +639,7 @@ impl<'tt> TtParser<'tt> {
621639
// possible next positions into `next_mps`. After some post-processing, the contents of
622640
// `next_mps` replenish `cur_mps` and we start over again.
623641
self.cur_mps.clear();
624-
self.cur_mps.push(box MatcherPos::top_level(matcher));
642+
self.cur_mps.push(box MatcherPos::top_level(matcher, self.empty_matches.clone()));
625643

626644
loop {
627645
self.next_mps.clear();

0 commit comments

Comments
 (0)