]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #50525 - nnethercote:lit_token, r=michaelwoerister
authorkennytm <kennytm@gmail.com>
Wed, 9 May 2018 09:23:31 +0000 (17:23 +0800)
committerkennytm <kennytm@gmail.com>
Wed, 9 May 2018 09:23:31 +0000 (17:23 +0800)
Optimize string handling in lit_token().

In the common case, the string value in a string literal Token is the
same as the string value in a string literal LitKind. (The exception is
when escapes or \r are involved.) This patch takes advantage of that to
avoid calling str_lit() and re-interning the string in that case. This
speeds up incremental builds for a few of the rustc-benchmarks, the best
by 3%.

Benchmarks that got a speedup of 1% or more:
```
coercions
        avg: -1.1%      min: -3.5%      max: 0.4%
regex-check
        avg: -1.2%      min: -1.5%      max: -0.6%
futures-check
        avg: -0.9%      min: -1.4%      max: -0.3%
futures
        avg: -0.8%      min: -1.3%      max: -0.3%
futures-opt
        avg: -0.7%      min: -1.2%      max: -0.1%
regex
        avg: -0.5%      min: -1.2%      max: -0.1%
regex-opt
        avg: -0.5%      min: -1.1%      max: -0.1%
hyper-check
        avg: -0.7%      min: -1.0%      max: -0.3%
```

src/libsyntax/parse/mod.rs

index f252020bc31698836dc454794a6a8588288a8327..f26a6a5307401cb8645517e69e6dda98862f0b22 100644 (file)
@@ -419,13 +419,24 @@ pub fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Hand
         token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)),
         token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)),
 
-        token::Str_(s) => {
-            let s = Symbol::intern(&str_lit(&s.as_str(), diag));
-            (true, Some(LitKind::Str(s, ast::StrStyle::Cooked)))
+        token::Str_(mut sym) => {
+            // If there are no characters requiring special treatment we can
+            // reuse the symbol from the Token. Otherwise, we must generate a
+            // new symbol because the string in the LitKind is different to the
+            // string in the Token.
+            let s = &sym.as_str();
+            if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') {
+                sym = Symbol::intern(&str_lit(s, diag));
+            }
+            (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked)))
         }
-        token::StrRaw(s, n) => {
-            let s = Symbol::intern(&raw_str_lit(&s.as_str()));
-            (true, Some(LitKind::Str(s, ast::StrStyle::Raw(n))))
+        token::StrRaw(mut sym, n) => {
+            // Ditto.
+            let s = &sym.as_str();
+            if s.contains('\r') {
+                sym = Symbol::intern(&raw_str_lit(s));
+            }
+            (true, Some(LitKind::Str(sym, ast::StrStyle::Raw(n))))
         }
         token::ByteStr(i) => {
             (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str()))))