about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-12-07 16:46:31 +0100
committerMichael Woerister <michaelwoerister@posteo>2017-12-14 10:15:10 -0600
commit9faa31612fb7a847a1c85836996846b9a6f20116 (patch)
tree64ebfef720abdccff8f316c8841929ab7f6617e6
parent8624ea51172c8a86d5c7c47d740be65a3a9efbc6 (diff)
downloadrust-9faa31612fb7a847a1c85836996846b9a6f20116.tar.gz
rust-9faa31612fb7a847a1c85836996846b9a6f20116.zip
incr.comp.: Speed up span hashing by caching expansion context hashes.
-rw-r--r--src/librustc/ich/hcx.rs31
-rw-r--r--src/libsyntax_pos/hygiene.rs9
2 files changed, 37 insertions, 3 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 0ef42177c14..2d20836814c 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -12,7 +12,7 @@ use hir;
 use hir::def_id::{DefId, DefIndex};
 use hir::map::DefPathHash;
 use hir::map::definitions::Definitions;
-use ich::{self, CachingCodemapView};
+use ich::{self, CachingCodemapView, Fingerprint};
 use middle::cstore::CrateStore;
 use ty::{TyCtxt, fast_reject};
 use session::Session;
@@ -28,12 +28,13 @@ use syntax::codemap::CodeMap;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::hygiene;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
                                            StableHasher, StableHasherResult,
                                            ToStableHashKey};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
 thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
     RefCell::new(FxHashSet()));
@@ -349,7 +350,31 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
             TAG_NO_EXPANSION.hash_stable(hcx, hasher);
         } else {
             TAG_EXPANSION.hash_stable(hcx, hasher);
-            span.ctxt.outer().expn_info().hash_stable(hcx, hasher);
+
+            // Since the same expansion context is usually referenced many
+            // times, we cache a stable hash of it and hash that instead of
+            // recursing every time.
+            thread_local! {
+                static CACHE: RefCell<FxHashMap<hygiene::Mark, u64>> =
+                    RefCell::new(FxHashMap());
+            }
+
+            let sub_hash: u64 = CACHE.with(|cache| {
+                let mark = span.ctxt.outer();
+
+                if let Some(&sub_hash) = cache.borrow().get(&mark) {
+                    return sub_hash;
+                }
+
+                let mut hasher = StableHasher::new();
+                mark.expn_info().hash_stable(hcx, &mut hasher);
+                let sub_hash: Fingerprint = hasher.finish();
+                let sub_hash = sub_hash.to_smaller_hash();
+                cache.borrow_mut().insert(mark, sub_hash);
+                sub_hash
+            });
+
+            sub_hash.hash_stable(hcx, hasher);
         }
     }
 }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index ab6c3f7d62d..55342c2768a 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -60,22 +60,27 @@ impl Mark {
     }
 
     /// The mark of the theoretical expansion that generates freshly parsed, unexpanded AST.
+    #[inline]
     pub fn root() -> Self {
         Mark(0)
     }
 
+    #[inline]
     pub fn as_u32(self) -> u32 {
         self.0
     }
 
+    #[inline]
     pub fn from_u32(raw: u32) -> Mark {
         Mark(raw)
     }
 
+    #[inline]
     pub fn expn_info(self) -> Option<ExpnInfo> {
         HygieneData::with(|data| data.marks[self.0 as usize].expn_info.clone())
     }
 
+    #[inline]
     pub fn set_expn_info(self, info: ExpnInfo) {
         HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
     }
@@ -91,10 +96,12 @@ impl Mark {
         })
     }
 
+    #[inline]
     pub fn kind(self) -> MarkKind {
         HygieneData::with(|data| data.marks[self.0 as usize].kind)
     }
 
+    #[inline]
     pub fn set_kind(self, kind: MarkKind) {
         HygieneData::with(|data| data.marks[self.0 as usize].kind = kind)
     }
@@ -309,10 +316,12 @@ impl SyntaxContext {
         Some(scope)
     }
 
+    #[inline]
     pub fn modern(self) -> SyntaxContext {
         HygieneData::with(|data| data.syntax_contexts[self.0 as usize].modern)
     }
 
+    #[inline]
     pub fn outer(self) -> Mark {
         HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark)
     }