diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index c9247539990a..907c4ec774af 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -82,9 +82,11 @@ pub enum DepNode { Privacy, IntrinsicCheck(D), MatchCheck(D), - MirMapConstruction(D), - MirPass(D), - MirTypeck(D), + + // Represents the MIR for a fn; also used as the task node for + // things read/modify that MIR. + Mir(D), + BorrowCheck(D), RvalueCheck(D), Reachability, @@ -214,9 +216,7 @@ impl DepNode { CheckConst(ref d) => op(d).map(CheckConst), IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck), MatchCheck(ref d) => op(d).map(MatchCheck), - MirMapConstruction(ref d) => op(d).map(MirMapConstruction), - MirPass(ref d) => op(d).map(MirPass), - MirTypeck(ref d) => op(d).map(MirTypeck), + Mir(ref d) => op(d).map(Mir), BorrowCheck(ref d) => op(d).map(BorrowCheck), RvalueCheck(ref d) => op(d).map(RvalueCheck), TransCrateItem(ref d) => op(d).map(TransCrateItem), diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 922d32a30679..88cd1efd3459 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -61,6 +61,12 @@ impl DepTrackingMap { self.map.get(k) } + pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> { + self.read(k); + self.write(k); + self.map.get_mut(k) + } + pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option { self.write(&k); self.map.insert(k, v) @@ -70,6 +76,10 @@ impl DepTrackingMap { self.read(k); self.map.contains_key(k) } + + pub fn keys(&self) -> Vec { + self.map.keys().cloned().collect() + } } impl MemoizationMap for RefCell> { diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs index 1a34699aff49..92de65798d3c 100644 --- a/src/librustc/mir/mir_map.rs +++ b/src/librustc/mir/mir_map.rs @@ -8,9 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use util::nodemap::NodeMap; +use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; +use hir::def_id::DefId; use mir::repr::Mir; +use std::marker::PhantomData; pub struct MirMap<'tcx> { - pub map: NodeMap>, + pub map: DepTrackingMap>, +} + +impl<'tcx> MirMap<'tcx> { + pub fn new(graph: DepGraph) -> Self { + MirMap { + map: DepTrackingMap::new(graph) + } + } +} + +pub struct MirMapConfig<'tcx> { + data: PhantomData<&'tcx ()> +} + +impl<'tcx> DepTrackingMapConfig for MirMapConfig<'tcx> { + type Key = DefId; + type Value = Mir<'tcx>; + fn to_dep_node(key: &DefId) -> DepNode { + DepNode::Mir(*key) + } } diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 4ca3907d4e60..57601e675043 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -11,7 +11,6 @@ use dep_graph::DepNode; use hir; use hir::map::DefPathData; -use hir::def_id::DefId; use mir::mir_map::MirMap; use mir::repr::{Mir, Promoted}; use ty::TyCtxt; @@ -73,9 +72,6 @@ impl<'a, 'tcx> MirSource { /// Various information about pass. pub trait Pass { // fn should_run(Session) to check if pass should run? - fn dep_node(&self, def_id: DefId) -> DepNode { - DepNode::MirPass(def_id) - } fn name(&self) -> &str { let name = unsafe { ::std::intrinsics::type_name::() }; if let Some(tail) = name.rfind(":") { @@ -119,10 +115,11 @@ impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { map: &mut MirMap<'tcx>, hooks: &mut [Box MirPassHook<'s>>]) { - for (&id, mir) in &mut map.map { - let def_id = tcx.map.local_def_id(id); - let _task = tcx.dep_graph.in_task(self.dep_node(def_id)); - + let def_ids = map.map.keys(); + for def_id in def_ids { + let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); + let mir = map.map.get_mut(&def_id).unwrap(); + let id = tcx.map.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); for hook in &mut *hooks { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 1fe47cd48538..4b9562ca299f 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -168,8 +168,10 @@ fn borrowck_fn(this: &mut BorrowckCtxt, attributes: &[ast::Attribute]) { debug!("borrowck_fn(id={})", id); + let def_id = this.tcx.map.local_def_id(id); + if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) { - let mir = this.mir_map.unwrap().map.get(&id).unwrap(); + let mir = this.mir_map.unwrap().map.get(&def_id).unwrap(); this.with_temp_region_map(id, |this| { mir::borrowck_mir(this, fk, decl, mir, body, sp, id, attributes) }); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 14476cc997ff..e3e06963ad43 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -956,20 +956,24 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, PpmMir | PpmMirCFG => { if let Some(mir_map) = mir_map { if let Some(nodeid) = nodeid { - let mir = mir_map.map.get(&nodeid).unwrap_or_else(|| { - sess.fatal(&format!("no MIR map entry for node {}", nodeid)) - }); + let def_id = tcx.map.local_def_id(nodeid); match ppm { - PpmMir => write_mir_pretty(tcx, iter::once((&nodeid, mir)), &mut out), + PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mir_map, &mut out), PpmMirCFG => { - write_mir_graphviz(tcx, iter::once((&nodeid, mir)), &mut out) + write_mir_graphviz(tcx, iter::once(def_id), &mir_map, &mut out) } _ => unreachable!(), }?; } else { match ppm { - PpmMir => write_mir_pretty(tcx, mir_map.map.iter(), &mut out), - PpmMirCFG => write_mir_graphviz(tcx, mir_map.map.iter(), &mut out), + PpmMir => write_mir_pretty(tcx, + mir_map.map.keys().into_iter(), + &mir_map, + &mut out), + PpmMirCFG => write_mir_graphviz(tcx, + mir_map.map.keys().into_iter(), + &mir_map, + &mut out), _ => unreachable!(), }?; } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ffd2a3535c33..4e754abe2aec 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -743,7 +743,8 @@ fn encode_repr_attrs(rbml_w: &mut Encoder, } fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, node_id: NodeId) { - if let Some(mir) = ecx.mir_map.map.get(&node_id) { + let def_id = ecx.tcx.map.local_def_id(node_id); + if let Some(mir) = ecx.mir_map.map.get(&def_id) { rbml_w.start_tag(tag_mir as usize); rbml_w.emit_opaque(|opaque_encoder| { tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| { @@ -1361,7 +1362,7 @@ fn my_visit_expr(expr: &hir::Expr, ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap(); rbml_w.end_tag(); - assert!(ecx.mir_map.map.contains_key(&expr.id)); + assert!(ecx.mir_map.map.contains_key(&def_id)); encode_mir(ecx, rbml_w, expr.id); rbml_w.end_tag(); diff --git a/src/librustc_mir/graphviz.rs b/src/librustc_mir/graphviz.rs index fdfa872b0b69..d986d88dafc9 100644 --- a/src/librustc_mir/graphviz.rs +++ b/src/librustc_mir/graphviz.rs @@ -9,7 +9,9 @@ // except according to those terms. use dot; +use rustc::hir::def_id::DefId; use rustc::mir::repr::*; +use rustc::mir::mir_map::MirMap; use rustc::ty::{self, TyCtxt}; use std::fmt::Debug; use std::io::{self, Write}; @@ -19,10 +21,16 @@ use rustc_data_structures::indexed_vec::Idx; /// Write a graphviz DOT graph of a list of MIRs. pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>, - iter: I, w: &mut W) + iter: I, + mir_map: &MirMap<'tcx>, + w: &mut W) -> io::Result<()> -where W: Write, I: Iterator)> { - for (&nodeid, mir) in iter { + where W: Write, I: Iterator +{ + for def_id in iter { + let nodeid = tcx.map.as_local_node_id(def_id).unwrap(); + let mir = &mir_map.map[&def_id]; + writeln!(w, "digraph Mir_{} {{", nodeid)?; // Global graph properties diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 2438f43d24e0..df1fec75939b 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -22,6 +22,7 @@ use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; use rustc_const_eval as const_eval; use rustc_data_structures::indexed_vec::Idx; +use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::FnKind; use rustc::hir::map::blocks::FnLikeNode; @@ -61,7 +62,17 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { MirSource::Promoted(..) => bug!() }; - let attrs = infcx.tcx.map.attrs(src.item_id()); + let src_node_id = src.item_id(); + + // We are going to be accessing various tables + // generated by TypeckItemBody; we also assume + // that the body passes type check. These tables + // are not individually tracked, so just register + // a read here. + let src_def_id = infcx.tcx.map.local_def_id(src_node_id); + infcx.tcx.dep_graph.read(DepNode::TypeckItemBody(src_def_id)); + + let attrs = infcx.tcx.map.attrs(src_node_id); // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 11d6b0779275..42a643b8af6f 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -18,6 +18,7 @@ use build; use rustc::dep_graph::DepNode; +use rustc::hir::def_id::DefId; use rustc::mir::repr::Mir; use rustc::mir::transform::MirSource; use rustc::mir::visit::MutVisitor; @@ -29,7 +30,6 @@ use rustc::infer::InferCtxtBuilder; use rustc::traits::ProjectionMode; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; -use rustc::util::nodemap::NodeMap; use rustc::hir; use rustc::hir::intravisit::{self, FnKind, Visitor}; use syntax::ast; @@ -38,15 +38,13 @@ use syntax_pos::Span; use std::mem; pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx> { - let mut map = MirMap { - map: NodeMap(), - }; + let mut map = MirMap::new(tcx.dep_graph.clone()); { let mut dump = BuildMir { tcx: tcx, map: &mut map, }; - tcx.visit_all_items_in_krate(DepNode::MirMapConstruction, &mut dump); + tcx.visit_all_items_in_krate(DepNode::Mir, &mut dump); } map } @@ -94,6 +92,7 @@ struct BuildMir<'a, 'tcx: 'a> { /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Cx<'b, 'gcx, 'tcx>). struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { src: MirSource, + def_id: DefId, infcx: InferCtxtBuilder<'a, 'gcx, 'tcx>, map: &'a mut MirMap<'gcx>, } @@ -101,9 +100,11 @@ struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> { let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id()); + let def_id = self.tcx.map.local_def_id(src.item_id()); CxBuilder { src: src, infcx: self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal), + def_id: def_id, map: self.map } } @@ -133,7 +134,7 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { mir }); - assert!(self.map.map.insert(src.item_id(), mir).is_none()) + assert!(self.map.map.insert(self.def_id, mir).is_none()) } } diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index d1b88ddda0c6..55e7408b0fd5 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -10,7 +10,9 @@ use build::{Location, ScopeAuxiliaryVec, ScopeId}; use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::mir::repr::*; +use rustc::mir::mir_map::MirMap; use rustc::mir::transform::MirSource; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fnv::FnvHashMap; @@ -18,7 +20,6 @@ use rustc_data_structures::indexed_vec::{Idx}; use std::fmt::Display; use std::fs; use std::io::{self, Write}; -use syntax::ast::NodeId; use std::path::{PathBuf, Path}; const INDENT: &'static str = " "; @@ -89,12 +90,15 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Write out a human-readable textual representation for the given MIR. pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>, iter: I, + mir_map: &MirMap<'tcx>, w: &mut Write) -> io::Result<()> - where I: Iterator)>, 'tcx: 'a + where I: Iterator, 'tcx: 'a { let mut first = true; - for (&id, mir) in iter { + for def_id in iter { + let mir = &mir_map.map[&def_id]; + if first { first = false; } else { @@ -102,6 +106,7 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>, writeln!(w, "")?; } + let id = tcx.map.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); write_mir_fn(tcx, src, mir, w, None)?; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1d00938fb25e..28204f4630c8 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -16,6 +16,7 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::FnKind; @@ -881,8 +882,8 @@ fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let extern_mir; let param_env_and_mir = if def_id.is_local() { - let node_id = tcx.map.as_local_node_id(def_id).unwrap(); - mir_map.and_then(|map| map.map.get(&node_id)).map(|mir| { + mir_map.and_then(|map| map.map.get(&def_id)).map(|mir| { + let node_id = tcx.map.as_local_node_id(def_id).unwrap(); (ty::ParameterEnvironment::for_item(tcx, node_id), mir) }) } else if let Some(mir) = tcx.sess.cstore.maybe_get_item_mir(tcx, def_id) { @@ -917,9 +918,10 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { // First, visit `const` items, potentially recursing, to get // accurate MUTABLE_INTERIOR and NEEDS_DROP qualifications. - for &id in map.map.keys() { - let def_id = tcx.map.local_def_id(id); - let _task = tcx.dep_graph.in_task(self.dep_node(def_id)); + let keys = map.map.keys(); + for &def_id in &keys { + let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); + let id = tcx.map.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); if let MirSource::Const(_) = src { qualify_const_item_cached(tcx, &mut qualif_map, Some(map), def_id); @@ -929,9 +931,9 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { // Then, handle everything else, without recursing, // as the MIR map is not shared, since promotion // in functions (including `const fn`) mutates it. - for (&id, mir) in &mut map.map { - let def_id = tcx.map.local_def_id(id); - let _task = tcx.dep_graph.in_task(self.dep_node(def_id)); + for &def_id in &keys { + let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); + let id = tcx.map.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); let mode = match src { MirSource::Fn(_) => { @@ -948,6 +950,7 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { }; let param_env = ty::ParameterEnvironment::for_item(tcx, id); + let mir = map.map.get_mut(&def_id).unwrap(); for hook in &mut *hooks { hook.on_mir_pass(tcx, src, mir, self, false); } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index db49e1e04079..26a907920e8d 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -11,8 +11,6 @@ //! This pass type-checks the MIR to ensure it is not broken. #![allow(unreachable_code)] -use rustc::dep_graph::DepNode; -use rustc::hir::def_id::DefId; use rustc::infer::{self, InferCtxt, InferOk}; use rustc::traits::{self, ProjectionMode}; use rustc::ty::fold::TypeFoldable; @@ -714,7 +712,4 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { } impl Pass for TypeckMir { - fn dep_node(&self, def_id: DefId) -> DepNode { - DepNode::MirTypeck(def_id) - } } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 5a3c1c8512ad..909b3d065075 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -81,7 +81,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { check_overflow: bool, check_drop_flag_for_sanity: bool, mir_map: &'a MirMap<'tcx>, - mir_cache: RefCell>>>, + mir_cache: RefCell>>, use_dll_storage_attrs: bool, @@ -186,6 +186,19 @@ impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { } } +// Cache for mir loaded from metadata +struct MirCache<'tcx> { + data: PhantomData<&'tcx ()> +} + +impl<'tcx> DepTrackingMapConfig for MirCache<'tcx> { + type Key = DefId; + type Value = Rc>; + fn to_dep_node(key: &DefId) -> DepNode { + DepNode::Mir(*key) + } +} + /// This list owns a number of LocalCrateContexts and binds them to their common /// SharedCrateContext. This type just exists as a convenience, something to /// pass around all LocalCrateContexts with and get an iterator over them. @@ -474,7 +487,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, mir_map: mir_map, - mir_cache: RefCell::new(DefIdMap()), + mir_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), stats: Stats { n_glues_created: Cell::new(0), n_null_glues: Cell::new(0), @@ -538,8 +551,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn get_mir(&self, def_id: DefId) -> Option> { if def_id.is_local() { - let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); - self.mir_map.map.get(&node_id).map(CachedMir::Ref) + self.mir_map.map.get(&def_id).map(CachedMir::Ref) } else { if let Some(mir) = self.mir_cache.borrow().get(&def_id).cloned() { return Some(CachedMir::Owned(mir));