From 191e76c5b88fe019c949a3404bda53e5cd67c5e6 Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Sat, 7 Jul 2018 17:11:20 -0400 Subject: [PATCH 1/2] fix perf issue in macro parser For a fuller description of the performance issue fixed by this: https://github.com/rust-lang/rust/issues/51754#issuecomment-403242159 --- src/libsyntax/ext/tt/macro_parser.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index fe458fa9977a5..ba61b2307d9c8 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -696,10 +696,17 @@ pub fn parse( } else { return Failure(parser.span, token::Eof); } + } else { + // Performance hack: eof_items may share matchers via Rc with other things that we want + // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an + // unnecessary implicit clone later in Rc::make_mut. + drop(eof_items); } + // Another possibility is that we need to call out to parse some rust nonterminal // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong. - else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { + assert!(!token_name_eq(&parser.token, &token::Eof)); + if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { let nts = bb_items .iter() .map(|item| match item.top_elts.get_tt(item.idx) { From 0467ae0cf52c47f204cc88a0e851e853ee2bed8f Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Mon, 16 Jul 2018 14:03:35 -0400 Subject: [PATCH 2/2] cleanup unnecessary else --- src/libsyntax/ext/tt/macro_parser.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ba61b2307d9c8..3046525b7144c 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -696,16 +696,14 @@ pub fn parse( } else { return Failure(parser.span, token::Eof); } - } else { - // Performance hack: eof_items may share matchers via Rc with other things that we want - // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an - // unnecessary implicit clone later in Rc::make_mut. - drop(eof_items); } + // Performance hack: eof_items may share matchers via Rc with other things that we want + // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an + // unnecessary implicit clone later in Rc::make_mut. + drop(eof_items); // Another possibility is that we need to call out to parse some rust nonterminal // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong. - assert!(!token_name_eq(&parser.token, &token::Eof)); if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { let nts = bb_items .iter()