From 67b3e7cc435931330cae5ae104ec7a7d37df89dd Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Tue, 10 Oct 2017 22:54:06 -0500 Subject: [PATCH 1/4] Implement query ensure `$query::ensure()` guarantees that one of two things is true after it returns: - The query has all green inputs. - The query has been executed. and counts as a read from the source query --- src/librustc/ty/maps/plumbing.rs | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 88b619558d90b..28397ac33d940 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -344,6 +344,48 @@ macro_rules! define_maps { } } + /// Ensure that either this query has all green inputs or been executed. + /// Executing query::ensure(D) is considered a read of the dep-node D. + /// + /// This function is particularly useful when executing passes for their + /// side-effects -- e.g., in order to report errors for erroneous programs. + /// + /// Note: The optimization is only available during incr. comp. + pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () { + let dep_node = Self::to_dep_node(tcx, &key); + + // Ensuring an "input" or anonymous query makes no sense + assert!(!dep_node.kind.is_anon()); + assert!(!dep_node.kind.is_input()); + use dep_graph::DepNodeColor; + match tcx.dep_graph.node_color(&dep_node) { + Some(DepNodeColor::Green(dep_node_index)) => { + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.dep_graph.read_index(dep_node_index); + } + Some(DepNodeColor::Red) => { + let _ = tcx.$name(key); + } + None => { + // Huh + if !tcx.dep_graph.is_fully_enabled() { + let _ = tcx.$name(key); + return; + } + match tcx.dep_graph.try_mark_green(tcx, &dep_node) { + Some(dep_node_index) => { + debug_assert!(tcx.dep_graph.is_green(dep_node_index)); + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.dep_graph.read_index(dep_node_index); + } + None => { + let _ = tcx.$name(key); + } + } + } + } + } + fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { let provider = tcx.maps.providers[key.map_crate()].$name; provider(tcx.global_tcx(), key) From bbdc61313df2c54c08cddcfde803cc2b40aa2ba3 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Tue, 10 Oct 2017 22:55:23 -0500 Subject: [PATCH 2/4] Ensure typeck_tables_of from typck_item_bodies This should make TypeckTables lazier. --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c6a4abfbd7c0..02a41aefd13f1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -728,7 +728,7 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum debug_assert!(crate_num == LOCAL_CRATE); Ok(tcx.sess.track_errors(|| { for body_owner_def_id in tcx.body_owners() { - tcx.typeck_tables_of(body_owner_def_id); + ty::maps::queries::typeck_tables_of::ensure(tcx, body_owner_def_id); } })?) } From f03af1b8f1be0fdb04cc9d641e2777ff3a6ec817 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Thu, 12 Oct 2017 08:48:49 -0500 Subject: [PATCH 3/4] Remove query profiling from ensure --- src/librustc/ty/maps/plumbing.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 28397ac33d940..57e3e0496e2d6 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -360,7 +360,6 @@ macro_rules! define_maps { use dep_graph::DepNodeColor; match tcx.dep_graph.node_color(&dep_node) { Some(DepNodeColor::Green(dep_node_index)) => { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); tcx.dep_graph.read_index(dep_node_index); } Some(DepNodeColor::Red) => { @@ -375,7 +374,6 @@ macro_rules! define_maps { match tcx.dep_graph.try_mark_green(tcx, &dep_node) { Some(dep_node_index) => { debug_assert!(tcx.dep_graph.is_green(dep_node_index)); - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); tcx.dep_graph.read_index(dep_node_index); } None => { From d0cb4d09cd4eb7626130cc9e59ef69dbfec04d0e Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Thu, 12 Oct 2017 08:54:42 -0500 Subject: [PATCH 4/4] Explain why `ensure` of a red node == the query --- src/librustc/ty/maps/plumbing.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 57e3e0496e2d6..715d5993fc57b 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -363,6 +363,12 @@ macro_rules! define_maps { tcx.dep_graph.read_index(dep_node_index); } Some(DepNodeColor::Red) => { + // A DepNodeColor::Red DepNode means that this query was executed + // before. We can not call `dep_graph.read()` here as we don't have + // the DepNodeIndex. Instead, We call the query again to issue the + // appropriate `dep_graph.read()` call. The performance cost this + // introduces should be negligible as we'll immediately hit the + // in-memory cache. let _ = tcx.$name(key); } None => {