Skip to content

Commit 012f45e

Browse files
authored
Auto merge of #35854 - nikomatsakis:incr-comp-cache-hash-35549, r=mw
compute and cache HIR hashes at beginning This avoids the compile-time overhead of computing them twice. It also fixes an issue where the hash computed after typeck is differen than the hash before, because typeck mutates the def-map in place. Fixes #35549. Fixes #35593. Some performance measurements suggest this `HashesMap` is very small in memory (unobservable via `-Z time-passes`) and very cheap to construct. I do see some (very minor) performance wins in the incremental case after the first run -- the first run costs more because loading the dep-graph didn't have any hashing to do in that case. Example timings from two runs of `libsyntex-syntax` -- the (1) indicates first run, (2) indicates second run, and (*) indicates both together: | Phase | Master | Branch | | ---- | ---- | ---- | | compute_hashes_map (1) | N/A | 0.343 | | load_dep_graph (1) | 0 | 0 | | serialize dep graph (1) | 4.190 | 3.920 | | total (1) | 4.190 | 4.260 | | compute_hashes_map (2) | N/A | 0.344 | | load_dep_graph (2) | 0.592 | 0.252 | | serialize dep graph (2) | 4.119 | 3.779 | | total (2) | 4.71 | 4.375 | | total (*) | 8.9 | 8.635 | r? @michaelwoerister
2 parents 0bd99f9 + 1cc7c90 commit 012f45e

File tree

19 files changed

+350
-176
lines changed

19 files changed

+350
-176
lines changed

src/librustc/dep_graph/dep_node.rs

+5
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ impl<D: Clone + Debug> DepNode<D> {
147147
}
148148
}
149149

150+
if label == "Krate" {
151+
// special case
152+
return Ok(DepNode::Krate);
153+
}
154+
150155
check! {
151156
CollectItem,
152157
BorrowCheck,

src/librustc/hir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,7 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
16211621

16221622
pub type CaptureModeMap = NodeMap<CaptureClause>;
16231623

1624-
#[derive(Clone)]
1624+
#[derive(Clone, Debug)]
16251625
pub struct TraitCandidate {
16261626
pub def_id: DefId,
16271627
pub import_id: Option<NodeId>,

src/librustc_driver/driver.rs

+28-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc::util::common::time;
2626
use rustc::util::nodemap::NodeSet;
2727
use rustc_back::sha2::{Sha256, Digest};
2828
use rustc_borrowck as borrowck;
29-
use rustc_incremental;
29+
use rustc_incremental::{self, IncrementalHashesMap};
3030
use rustc_resolve::{MakeGlobMap, Resolver};
3131
use rustc_metadata::macro_import;
3232
use rustc_metadata::creader::read_local_crates;
@@ -172,7 +172,7 @@ pub fn compile_input(sess: &Session,
172172
resolutions,
173173
&arenas,
174174
&crate_name,
175-
|tcx, mir_map, analysis, result| {
175+
|tcx, mir_map, analysis, incremental_hashes_map, result| {
176176
{
177177
// Eventually, we will want to track plugins.
178178
let _ignore = tcx.dep_graph.in_ignore();
@@ -202,7 +202,8 @@ pub fn compile_input(sess: &Session,
202202
}
203203
let trans = phase_4_translate_to_llvm(tcx,
204204
mir_map.unwrap(),
205-
analysis);
205+
analysis,
206+
&incremental_hashes_map);
206207

207208
if log_enabled!(::log::INFO) {
208209
println!("Post-trans");
@@ -797,14 +798,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
797798
where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
798799
Option<MirMap<'tcx>>,
799800
ty::CrateAnalysis,
801+
IncrementalHashesMap,
800802
CompileResult) -> R
801803
{
802804
macro_rules! try_with_f {
803-
($e: expr, ($t: expr, $m: expr, $a: expr)) => {
805+
($e: expr, ($t: expr, $m: expr, $a: expr, $h: expr)) => {
804806
match $e {
805807
Ok(x) => x,
806808
Err(x) => {
807-
f($t, $m, $a, Err(x));
809+
f($t, $m, $a, $h, Err(x));
808810
return Err(x);
809811
}
810812
}
@@ -860,12 +862,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
860862
index,
861863
name,
862864
|tcx| {
865+
let incremental_hashes_map =
866+
time(time_passes,
867+
"compute_incremental_hashes_map",
868+
|| rustc_incremental::compute_incremental_hashes_map(tcx));
863869
time(time_passes,
864870
"load_dep_graph",
865-
|| rustc_incremental::load_dep_graph(tcx));
871+
|| rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
866872

867873
// passes are timed inside typeck
868-
try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis));
874+
try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis, incremental_hashes_map));
869875

870876
time(time_passes,
871877
"const checking",
@@ -935,7 +941,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
935941
// lint warnings and so on -- kindck used to do this abort, but
936942
// kindck is gone now). -nmatsakis
937943
if sess.err_count() > 0 {
938-
return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
944+
return Ok(f(tcx,
945+
Some(mir_map),
946+
analysis,
947+
incremental_hashes_map,
948+
Err(sess.err_count())));
939949
}
940950

941951
analysis.reachable =
@@ -963,17 +973,22 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
963973

964974
// The above three passes generate errors w/o aborting
965975
if sess.err_count() > 0 {
966-
return Ok(f(tcx, Some(mir_map), analysis, Err(sess.err_count())));
976+
return Ok(f(tcx,
977+
Some(mir_map),
978+
analysis,
979+
incremental_hashes_map,
980+
Err(sess.err_count())));
967981
}
968982

969-
Ok(f(tcx, Some(mir_map), analysis, Ok(())))
983+
Ok(f(tcx, Some(mir_map), analysis, incremental_hashes_map, Ok(())))
970984
})
971985
}
972986

973987
/// Run the translation phase to LLVM, after which the AST and analysis can
974988
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
975989
mut mir_map: MirMap<'tcx>,
976-
analysis: ty::CrateAnalysis)
990+
analysis: ty::CrateAnalysis,
991+
incremental_hashes_map: &IncrementalHashesMap)
977992
-> trans::CrateTranslation {
978993
let time_passes = tcx.sess.time_passes();
979994

@@ -1007,15 +1022,15 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10071022
let translation =
10081023
time(time_passes,
10091024
"translation",
1010-
move || trans::trans_crate(tcx, &mir_map, analysis));
1025+
move || trans::trans_crate(tcx, &mir_map, analysis, &incremental_hashes_map));
10111026

10121027
time(time_passes,
10131028
"assert dep graph",
10141029
move || rustc_incremental::assert_dep_graph(tcx));
10151030

10161031
time(time_passes,
10171032
"serialize dep graph",
1018-
move || rustc_incremental::save_dep_graph(tcx));
1033+
move || rustc_incremental::save_dep_graph(tcx, &incremental_hashes_map));
10191034

10201035
translation
10211036
}

src/librustc_driver/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl PpSourceMode {
234234
resolutions.clone(),
235235
arenas,
236236
id,
237-
|tcx, _, _, _| {
237+
|tcx, _, _, _, _| {
238238
let annotation = TypedAnnotation {
239239
tcx: tcx,
240240
};
@@ -951,7 +951,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
951951
resolutions.clone(),
952952
arenas,
953953
crate_name,
954-
|tcx, mir_map, _, _| {
954+
|tcx, mir_map, _, _, _| {
955955
match ppm {
956956
PpmMir | PpmMirCFG => {
957957
if let Some(mir_map) = mir_map {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::hir::def_id::DefId;
12+
use rustc::ty::TyCtxt;
13+
use rustc::util::nodemap::DefIdMap;
14+
15+
pub struct DefPathHashes<'a, 'tcx: 'a> {
16+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
17+
data: DefIdMap<u64>,
18+
}
19+
20+
impl<'a, 'tcx> DefPathHashes<'a, 'tcx> {
21+
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
22+
DefPathHashes {
23+
tcx: tcx,
24+
data: DefIdMap()
25+
}
26+
}
27+
28+
pub fn hash(&mut self, def_id: DefId) -> u64 {
29+
let tcx = self.tcx;
30+
*self.data.entry(def_id)
31+
.or_insert_with(|| {
32+
let def_path = tcx.def_path(def_id);
33+
def_path.deterministic_hash(tcx)
34+
})
35+
}
36+
}

0 commit comments

Comments
 (0)