about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-17 19:28:23 +0000
committerbors <bors@rust-lang.org>2018-07-17 19:28:23 +0000
commit4f3c7a472b77ba3f3afbc12d004b9d1bbcee7fe7 (patch)
tree5e2753e692856610a816a80af55947e967e77832 /src/libsyntax/ext
parent1c84d8187395b641616649a0f16f15a78ea8bbce (diff)
parent0467ae0cf52c47f204cc88a0e851e853ee2bed8f (diff)
downloadrust-4f3c7a472b77ba3f3afbc12d004b9d1bbcee7fe7.tar.gz
rust-4f3c7a472b77ba3f3afbc12d004b9d1bbcee7fe7.zip
Auto merge of #52145 - ExpHP:drop-it-like-its-eof, r=nikomatsakis
Fix macro parser quadratic complexity in small repeating groups

Observed in #51754, and more easily demonstrated with the following:

```rust
macro_rules! stress {
    ($($t:tt)+) => { };
}

fn main() {
    stress!{
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        //    ... 65536 copies of "a" total ...
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
    }
}
```
which takes 50 seconds to compile prior to the fix and <1s after.

I hope this has a visible impact on the compile times for real code.  (I think it is most likely to affect incremental TT munchers that deal with large inputs, though it depends on how they are written)

For a fuller description of the performance issue:  https://github.com/rust-lang/rust/issues/51754#issuecomment-403242159

---

There is no test (yet) because I'm not sure how easily to measure this for regressions.
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index fe458fa9977..3046525b714 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -697,9 +697,14 @@ pub fn parse(
                 return Failure(parser.span, token::Eof);
             }
         }
+        // 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 {
+        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) {