Skip to content

Commit 3d9ebf2

Browse files
Speed up expansion.
This reduces duplication, thereby increasing expansion speed.
1 parent 76242ae commit 3d9ebf2

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

src/libsyntax/ext/tt/macro_parser.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,20 @@ struct MatcherPos {
139139
sep: Option<Token>,
140140
idx: usize,
141141
up: Option<Box<MatcherPos>>,
142-
matches: Vec<Vec<Rc<NamedMatch>>>,
142+
matches: Vec<Rc<Vec<NamedMatch>>>,
143143
match_lo: usize,
144144
match_cur: usize,
145145
match_hi: usize,
146146
sp_lo: BytePos,
147147
}
148148

149+
impl MatcherPos {
150+
fn push_match(&mut self, idx: usize, m: NamedMatch) {
151+
let matches = Rc::make_mut(&mut self.matches[idx]);
152+
matches.push(m);
153+
}
154+
}
155+
149156
pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
150157

151158
pub fn count_names(ms: &[TokenTree]) -> usize {
@@ -199,14 +206,15 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
199206
/// only on the nesting depth of `ast::TTSeq`s in the originating
200207
/// token tree it was derived from.
201208
209+
#[derive(Debug, Clone)]
202210
pub enum NamedMatch {
203-
MatchedSeq(Vec<Rc<NamedMatch>>, syntax_pos::Span),
211+
MatchedSeq(Rc<Vec<NamedMatch>>, syntax_pos::Span),
204212
MatchedNonterminal(Rc<Nonterminal>)
205213
}
206214

207-
fn nameize<I: Iterator<Item=Rc<NamedMatch>>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
215+
fn nameize<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
208216
-> NamedParseResult {
209-
fn n_rec<I: Iterator<Item=Rc<NamedMatch>>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I,
217+
fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I,
210218
ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
211219
-> Result<(), (syntax_pos::Span, String)> {
212220
match *m {
@@ -228,7 +236,8 @@ fn nameize<I: Iterator<Item=Rc<NamedMatch>>>(sess: &ParseSess, ms: &[TokenTree],
228236
TokenTree::MetaVarDecl(sp, bind_name, _) => {
229237
match ret_val.entry(bind_name) {
230238
Vacant(spot) => {
231-
spot.insert(res.next().unwrap());
239+
// FIXME(simulacrum): Don't construct Rc here
240+
spot.insert(Rc::new(res.next().unwrap()));
232241
}
233242
Occupied(..) => {
234243
return Err((sp, format!("duplicated bind name: {}", bind_name)))
@@ -280,8 +289,8 @@ fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
280289
}
281290
}
282291

283-
fn create_matches(len: usize) -> Vec<Vec<Rc<NamedMatch>>> {
284-
(0..len).into_iter().map(|_| Vec::new()).collect()
292+
fn create_matches(len: usize) -> Vec<Rc<Vec<NamedMatch>>> {
293+
(0..len).into_iter().map(|_| Rc::new(Vec::new())).collect()
285294
}
286295

287296
fn inner_parse_loop(sess: &ParseSess,
@@ -320,15 +329,10 @@ fn inner_parse_loop(sess: &ParseSess,
320329
// update matches (the MBE "parse tree") by appending
321330
// each tree as a subtree.
322331

323-
// I bet this is a perf problem: we're preemptively
324-
// doing a lot of array work that will get thrown away
325-
// most of the time.
326-
327332
// Only touch the binders we have actually bound
328333
for idx in ei.match_lo..ei.match_hi {
329334
let sub = ei.matches[idx].clone();
330-
new_pos.matches[idx]
331-
.push(Rc::new(MatchedSeq(sub, Span { lo: ei.sp_lo, ..span })));
335+
new_pos.push_match(idx, MatchedSeq(sub, Span { lo: ei.sp_lo, ..span }));
332336
}
333337

334338
new_pos.match_cur = ei.match_hi;
@@ -362,7 +366,7 @@ fn inner_parse_loop(sess: &ParseSess,
362366
new_ei.match_cur += seq.num_captures;
363367
new_ei.idx += 1;
364368
for idx in ei.match_cur..ei.match_cur + seq.num_captures {
365-
new_ei.matches[idx].push(Rc::new(MatchedSeq(vec![], sp)));
369+
new_ei.push_match(idx, MatchedSeq(Rc::new(vec![]), sp));
366370
}
367371
cur_eis.push(new_ei);
368372
}
@@ -446,7 +450,9 @@ pub fn parse(sess: &ParseSess,
446450
/* error messages here could be improved with links to orig. rules */
447451
if token_name_eq(&parser.token, &token::Eof) {
448452
if eof_eis.len() == 1 {
449-
let matches = eof_eis[0].matches.iter_mut().map(|mut dv| dv.pop().unwrap());
453+
let matches = eof_eis[0].matches.iter_mut().map(|mut dv| {
454+
Rc::make_mut(dv).pop().unwrap()
455+
});
450456
return nameize(sess, ms, matches);
451457
} else if eof_eis.len() > 1 {
452458
return Error(parser.span, "ambiguity: multiple successful parses".to_string());
@@ -479,8 +485,8 @@ pub fn parse(sess: &ParseSess,
479485
let mut ei = bb_eis.pop().unwrap();
480486
if let TokenTree::MetaVarDecl(span, _, ident) = ei.top_elts.get_tt(ei.idx) {
481487
let match_cur = ei.match_cur;
482-
ei.matches[match_cur].push(Rc::new(MatchedNonterminal(
483-
Rc::new(parse_nt(&mut parser, span, &ident.name.as_str())))));
488+
ei.push_match(match_cur,
489+
MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))));
484490
ei.idx += 1;
485491
ei.match_cur += 1;
486492
} else {

src/libsyntax/ext/tt/macro_rules.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
219219
let lhses = match *argument_map[&lhs_nm] {
220220
MatchedSeq(ref s, _) => {
221221
s.iter().map(|m| {
222-
if let MatchedNonterminal(ref nt) = **m {
222+
if let MatchedNonterminal(ref nt) = *m {
223223
if let NtTT(ref tt) = **nt {
224224
let tt = quoted::parse(tt.clone().into(), true, sess).pop().unwrap();
225225
valid &= check_lhs_nt_follows(sess, features, &tt);
@@ -235,7 +235,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
235235
let rhses = match *argument_map[&rhs_nm] {
236236
MatchedSeq(ref s, _) => {
237237
s.iter().map(|m| {
238-
if let MatchedNonterminal(ref nt) = **m {
238+
if let MatchedNonterminal(ref nt) = *m {
239239
if let NtTT(ref tt) = **nt {
240240
return quoted::parse(tt.clone().into(), false, sess).pop().unwrap();
241241
}

src/libsyntax/ext/tt/transcribe.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,16 @@ fn lookup_cur_matched(ident: Ident,
182182
repeats: &[(usize, usize)])
183183
-> Option<Rc<NamedMatch>> {
184184
interpolations.get(&ident).map(|matched| {
185-
repeats.iter().fold(matched.clone(), |ad, &(idx, _)| {
186-
match *ad {
187-
MatchedNonterminal(_) => {
188-
// end of the line; duplicate henceforth
189-
ad.clone()
190-
}
191-
MatchedSeq(ref ads, _) => ads[idx].clone()
185+
let mut matched = matched.clone();
186+
for &(idx, _) in repeats {
187+
let m = matched.clone();
188+
match *m {
189+
MatchedNonterminal(_) => break,
190+
MatchedSeq(ref ads, _) => matched = Rc::new(ads[idx].clone()),
192191
}
193-
})
192+
}
193+
194+
matched
194195
})
195196
}
196197

src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
5454
let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) {
5555
(&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => {
5656
let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt| {
57-
match **pat_nt {
57+
match *pat_nt {
5858
MatchedNonterminal(ref nt) => match **nt {
5959
NtPat(ref pat) => pat.clone(),
6060
_ => unreachable!(),

0 commit comments

Comments
 (0)