From 9faa31612fb7a847a1c85836996846b9a6f20116 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 7 Dec 2017 16:46:31 +0100 Subject: [PATCH] incr.comp.: Speed up span hashing by caching expansion context hashes. --- src/librustc/ich/hcx.rs | 31 ++++++++++++++++++++++++++++--- src/libsyntax_pos/hygiene.rs | 9 +++++++++ 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> = RefCell::new(FxHashSet())); @@ -349,7 +350,31 @@ impl<'gcx> HashStable> 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> = + 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 { 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) }