Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incr.comp.: Speed up span hashing by caching expansion context hashes. #46562

Merged
merged 2 commits into from
Dec 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions src/librustc/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()));
Expand Down Expand Up @@ -337,19 +338,46 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
}

let len = span.hi - span.lo;

std_hash::Hash::hash(&TAG_VALID_SPAN, hasher);
std_hash::Hash::hash(&file_lo.name, hasher);
std_hash::Hash::hash(&line_lo, hasher);
std_hash::Hash::hash(&col_lo, hasher);
std_hash::Hash::hash(&len, hasher);
// We truncate the stable_id hash and line and col numbers. The chances
// of causing a collision this way should be minimal.
std_hash::Hash::hash(&(file_lo.stable_id.0 as u64), hasher);

let col = (col_lo.0 as u64) & 0xFF;
let line = ((line_lo as u64) & 0xFF_FF_FF) << 8;
let len = ((span.hi - span.lo).0 as u64) << 32;
let line_col_len = col | line | len;
std_hash::Hash::hash(&line_col_len, hasher);

if span.ctxt == SyntaxContext::empty() {
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);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
// Do not hash the source as it is not encoded
src: _,
src_hash,
// The stable id is just a hash of other fields
stable_id: _,
external_src: _,
start_pos,
end_pos: _,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/maps/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl<'sess> OnDiskCache<'sess> {
let index = FileMapIndex(index as u32);
let file_ptr: *const FileMap = &**file as *const _;
file_to_file_index.insert(file_ptr, index);
file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
file_index_to_stable_id.insert(index, file.stable_id);
}

(file_to_file_index, file_index_to_stable_id)
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,7 @@ impl<'a, 'tcx> CrateMetadata {
let syntax_pos::FileMap { name,
name_was_remapped,
src_hash,
stable_id,
start_pos,
end_pos,
lines,
Expand Down Expand Up @@ -1155,6 +1156,7 @@ impl<'a, 'tcx> CrateMetadata {
name_was_remapped,
self.cnum.as_u32(),
src_hash,
stable_id,
source_length,
lines,
multibyte_chars,
Expand Down
26 changes: 4 additions & 22 deletions src/libsyntax/codemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan};
pub use self::ExpnFormat::*;

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use std::cell::{RefCell, Ref};
use std::hash::Hash;
use std::path::{Path, PathBuf};
use std::rc::Rc;

Expand Down Expand Up @@ -102,24 +100,6 @@ impl FileLoader for RealFileLoader {
}
}

// This is a FileMap identifier that is used to correlate FileMaps between
// subsequent compilation sessions (which is something we need to do during
// incremental compilation).
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct StableFilemapId(u128);

impl StableFilemapId {
pub fn new(filemap: &FileMap) -> StableFilemapId {
let mut hasher = StableHasher::new();

filemap.name.hash(&mut hasher);
filemap.name_was_remapped.hash(&mut hasher);
filemap.unmapped_path.hash(&mut hasher);

StableFilemapId(hasher.finish())
}
}

// _____________________________________________________________________________
// CodeMap
//
Expand Down Expand Up @@ -217,7 +197,7 @@ impl CodeMap {

self.stable_id_to_filemap
.borrow_mut()
.insert(StableFilemapId::new(&filemap), filemap.clone());
.insert(filemap.stable_id, filemap.clone());

filemap
}
Expand Down Expand Up @@ -246,6 +226,7 @@ impl CodeMap {
name_was_remapped: bool,
crate_of_origin: u32,
src_hash: u128,
stable_id: StableFilemapId,
source_len: usize,
mut file_local_lines: Vec<BytePos>,
mut file_local_multibyte_chars: Vec<MultiByteChar>,
Expand Down Expand Up @@ -276,6 +257,7 @@ impl CodeMap {
crate_of_origin,
src: None,
src_hash,
stable_id,
external_src: RefCell::new(ExternalSource::AbsentOk),
start_pos,
end_pos,
Expand All @@ -288,7 +270,7 @@ impl CodeMap {

self.stable_id_to_filemap
.borrow_mut()
.insert(StableFilemapId::new(&filemap), filemap.clone());
.insert(stable_id, filemap.clone());

filemap
}
Expand Down
9 changes: 9 additions & 0 deletions src/libsyntax_pos/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
56 changes: 44 additions & 12 deletions src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ pub struct FileMap {
pub src: Option<Rc<String>>,
/// The source code's hash
pub src_hash: u128,
/// The stable id used during incr. comp.
pub stable_id: StableFilemapId,
/// The external source code (used for external crates, which will have a `None`
/// value as `self.src`.
pub external_src: RefCell<ExternalSource>,
Expand All @@ -693,15 +695,37 @@ pub struct FileMap {
pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
}

// This is a FileMap identifier that is used to correlate FileMaps between
// subsequent compilation sessions (which is something we need to do during
// incremental compilation).
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct StableFilemapId(pub u128);

impl StableFilemapId {
pub fn new(name: &FileName,
name_was_remapped: bool,
unmapped_path: &FileName)
-> StableFilemapId {
use std::hash::Hash;

let mut hasher = StableHasher::new();
name.hash(&mut hasher);
name_was_remapped.hash(&mut hasher);
unmapped_path.hash(&mut hasher);
StableFilemapId(hasher.finish())
}
}

impl Encodable for FileMap {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("FileMap", 8, |s| {
s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?;
s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?;
s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?;
s.emit_struct_field("lines", 4, |s| {
s.emit_struct_field("src_hash", 2, |s| self.src_hash.encode(s))?;
s.emit_struct_field("stable_id", 3, |s| self.stable_id.encode(s))?;
s.emit_struct_field("start_pos", 4, |s| self.start_pos.encode(s))?;
s.emit_struct_field("end_pos", 5, |s| self.end_pos.encode(s))?;
s.emit_struct_field("lines", 6, |s| {
let lines = self.lines.borrow();
// store the length
s.emit_u32(lines.len() as u32)?;
Expand Down Expand Up @@ -747,10 +771,10 @@ impl Encodable for FileMap {

Ok(())
})?;
s.emit_struct_field("multibyte_chars", 5, |s| {
s.emit_struct_field("multibyte_chars", 7, |s| {
(*self.multibyte_chars.borrow()).encode(s)
})?;
s.emit_struct_field("non_narrow_chars", 7, |s| {
s.emit_struct_field("non_narrow_chars", 8, |s| {
(*self.non_narrow_chars.borrow()).encode(s)
})
})
Expand All @@ -765,11 +789,13 @@ impl Decodable for FileMap {
let name_was_remapped: bool =
d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?;
let src_hash: u128 =
d.read_struct_field("src_hash", 6, |d| Decodable::decode(d))?;
d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?;
let stable_id: StableFilemapId =
d.read_struct_field("stable_id", 3, |d| Decodable::decode(d))?;
let start_pos: BytePos =
d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?;
let lines: Vec<BytePos> = d.read_struct_field("lines", 4, |d| {
d.read_struct_field("start_pos", 4, |d| Decodable::decode(d))?;
let end_pos: BytePos = d.read_struct_field("end_pos", 5, |d| Decodable::decode(d))?;
let lines: Vec<BytePos> = d.read_struct_field("lines", 6, |d| {
let num_lines: u32 = Decodable::decode(d)?;
let mut lines = Vec::with_capacity(num_lines as usize);

Expand Down Expand Up @@ -798,9 +824,9 @@ impl Decodable for FileMap {
Ok(lines)
})?;
let multibyte_chars: Vec<MultiByteChar> =
d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
d.read_struct_field("multibyte_chars", 7, |d| Decodable::decode(d))?;
let non_narrow_chars: Vec<NonNarrowChar> =
d.read_struct_field("non_narrow_chars", 7, |d| Decodable::decode(d))?;
d.read_struct_field("non_narrow_chars", 8, |d| Decodable::decode(d))?;
Ok(FileMap {
name,
name_was_remapped,
Expand All @@ -813,6 +839,7 @@ impl Decodable for FileMap {
end_pos,
src: None,
src_hash,
stable_id,
external_src: RefCell::new(ExternalSource::AbsentOk),
lines: RefCell::new(lines),
multibyte_chars: RefCell::new(multibyte_chars),
Expand Down Expand Up @@ -840,6 +867,10 @@ impl FileMap {
hasher.write(src.as_bytes());
let src_hash = hasher.finish();

let stable_id = StableFilemapId::new(&name,
name_was_remapped,
&unmapped_path);

let end_pos = start_pos.to_usize() + src.len();

FileMap {
Expand All @@ -849,6 +880,7 @@ impl FileMap {
crate_of_origin: 0,
src: Some(Rc::new(src)),
src_hash,
stable_id,
external_src: RefCell::new(ExternalSource::Unneeded),
start_pos,
end_pos: Pos::from_usize(end_pos),
Expand Down