Skip to content

Commit

Permalink
Give function bodies their own dep graph node
Browse files Browse the repository at this point in the history
  • Loading branch information
flodiebold committed Nov 29, 2016
1 parent 16eedd2 commit 936dbbc
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 29 deletions.
5 changes: 5 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Expand Up @@ -42,6 +42,9 @@ pub enum DepNode<D: Clone + Debug> {
// Represents the HIR node with the given node-id
Hir(D),

// Represents the body of a function or method
HirBody(D),

// Represents the metadata for a given HIR node, typically found
// in an extern crate.
MetaData(D),
Expand Down Expand Up @@ -150,6 +153,7 @@ impl<D: Clone + Debug> DepNode<D> {
CollectItem,
BorrowCheck,
Hir,
HirBody,
TransCrateItem,
TypeckItemType,
TypeckItemBody,
Expand Down Expand Up @@ -199,6 +203,7 @@ impl<D: Clone + Debug> DepNode<D> {
WorkProduct(ref id) => Some(WorkProduct(id.clone())),

Hir(ref d) => op(d).map(Hir),
HirBody(ref d) => op(d).map(HirBody),
MetaData(ref d) => op(d).map(MetaData),
CollectItem(ref d) => op(d).map(CollectItem),
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
Expand Down
52 changes: 50 additions & 2 deletions src/librustc/hir/map/mod.rs
Expand Up @@ -256,26 +256,46 @@ impl<'ast> Map<'ast> {
let map = self.map.borrow();
let mut id = id0;
if !self.is_inlined_node_id(id) {
let mut last_expr = None;
loop {
match map[id.as_usize()] {
EntryItem(_, item) => {
assert_eq!(id, item.id);
let def_id = self.local_def_id(id);
assert!(!self.is_inlined_def_id(def_id));

if let Some(last_id) = last_expr {
// The body of the item may have a separate dep node
// (Note that impl/trait items don't currently have
// their own dep node, so there's also just one
// HirBody node for all the items)
if self.is_body(last_id, item) {
return DepNode::HirBody(def_id);
}
}
return DepNode::Hir(def_id);
}

EntryImplItem(..) => {
EntryImplItem(_, item) => {
let def_id = self.local_def_id(id);
assert!(!self.is_inlined_def_id(def_id));

if let Some(last_id) = last_expr {
// The body of the item may have a separate dep node
// (Note that impl/trait items don't currently have
// their own dep node, so there's also just one
// HirBody node for all the items)
if self.is_impl_item_body(last_id, item) {
return DepNode::HirBody(def_id);
}
}
return DepNode::Hir(def_id);
}

EntryForeignItem(p, _) |
EntryTraitItem(p, _) |
EntryVariant(p, _) |
EntryField(p, _) |
EntryExpr(p, _) |
EntryStmt(p, _) |
EntryTy(p, _) |
EntryTraitRef(p, _) |
Expand All @@ -288,6 +308,11 @@ impl<'ast> Map<'ast> {
EntryVisibility(p, _) =>
id = p,

EntryExpr(p, _) => {
last_expr = Some(id);
id = p;
}

RootCrate =>
return DepNode::Krate,

Expand Down Expand Up @@ -345,6 +370,29 @@ impl<'ast> Map<'ast> {
}
}

fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
match item.node {
ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
// Since trait/impl items currently don't get their own dep nodes,
// we check here whether node_id is the body of any of the items.
// Once they get their own dep nodes, this can go away
ItemTrait(_, _, _, ref trait_items) => {
trait_items.iter().any(|trait_item| { match trait_item.node {
MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
_ => false
}})
}
_ => false
}
}

fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
match item.node {
ImplItemKind::Method(_, body) => body.node_id() == node_id,
_ => false
}
}

pub fn num_local_def_ids(&self) -> usize {
self.definitions.borrow().len()
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_const_eval/eval.rs
Expand Up @@ -33,7 +33,6 @@ use graphviz::IntoCow;
use syntax::ast;
use rustc::hir::{Expr, PatKind};
use rustc::hir;
use rustc::hir::intravisit::FnKind;
use syntax::ptr::P;
use syntax::codemap;
use syntax::attr::IntType;
Expand Down
19 changes: 14 additions & 5 deletions src/librustc_incremental/calculate_svh/mod.rs
Expand Up @@ -149,19 +149,27 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
{
assert!(def_id.is_local());
debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
self.calculate_def_hash(DepNode::Hir(def_id), false, &mut walk_op);
self.calculate_def_hash(DepNode::HirBody(def_id), true, &mut walk_op);
}

fn calculate_def_hash<W>(&mut self, dep_node: DepNode<DefId>, hash_bodies: bool, walk_op: &mut W)
where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
{
let mut state = IchHasher::new();
walk_op(&mut StrictVersionHashVisitor::new(&mut state,
self.tcx,
&mut self.def_path_hashes,
&mut self.codemap,
self.hash_spans));
self.hash_spans,
hash_bodies));
let bytes_hashed = state.bytes_hashed();
let item_hash = state.finish();
self.hashes.insert(DepNode::Hir(def_id), item_hash);
debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash);
debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
self.hashes.insert(dep_node, item_hash);

let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
bytes_hashed;
bytes_hashed;
self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
}

Expand Down Expand Up @@ -200,7 +208,8 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> {
self.tcx,
&mut self.def_path_hashes,
&mut self.codemap,
self.hash_spans);
self.hash_spans,
false);
visitor.hash_attributes(&krate.attrs);
}

Expand Down
25 changes: 19 additions & 6 deletions src/librustc_incremental/calculate_svh/svh_visitor.rs
Expand Up @@ -52,14 +52,16 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
hash_spans: bool,
codemap: &'a mut CachingCodemapView<'tcx>,
overflow_checks_enabled: bool,
hash_bodies: bool,
}

impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
pub fn new(st: &'a mut IchHasher,
tcx: TyCtxt<'hash, 'tcx, 'tcx>,
def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
codemap: &'a mut CachingCodemapView<'tcx>,
hash_spans: bool)
hash_spans: bool,
hash_bodies: bool)
-> Self {
let check_overflow = tcx.sess.opts.debugging_opts.force_overflow_checks
.unwrap_or(tcx.sess.opts.debug_assertions);
Expand All @@ -71,6 +73,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
hash_spans: hash_spans,
codemap: codemap,
overflow_checks_enabled: check_overflow,
hash_bodies: hash_bodies,
}
}

Expand Down Expand Up @@ -459,15 +462,16 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
#[derive(Hash)]
enum SawTraitOrImplItemComponent {
SawTraitOrImplItemConst,
SawTraitOrImplItemMethod(Unsafety, Constness, Abi),
// The boolean signifies whether a body is present
SawTraitOrImplItemMethod(Unsafety, Constness, Abi, bool),
SawTraitOrImplItemType
}

fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
match *ti {
ConstTraitItem(..) => SawTraitOrImplItemConst,
MethodTraitItem(ref sig, _) =>
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
MethodTraitItem(ref sig, ref body) =>
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()),
TypeTraitItem(..) => SawTraitOrImplItemType
}
}
Expand All @@ -476,7 +480,7 @@ fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent {
match *ii {
ImplItemKind::Const(..) => SawTraitOrImplItemConst,
ImplItemKind::Method(ref sig, _) =>
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
ImplItemKind::Type(..) => SawTraitOrImplItemType
}
}
Expand Down Expand Up @@ -509,6 +513,14 @@ macro_rules! hash_span {
}

impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, visit::NestedVisitMode)> {
if self.hash_bodies {
Some((&self.tcx.map, visit::NestedVisitMode::OnlyBodies))
} else {
None
}
}

fn visit_variant_data(&mut self,
s: &'tcx VariantData,
name: Name,
Expand Down Expand Up @@ -609,7 +621,8 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has

fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, n: NodeId) {
debug!("visit_mod: st={:?}", self.st);
SawMod.hash(self.st); visit::walk_mod(self, m, n)
SawMod.hash(self.st);
visit::walk_mod(self, m, n)
}

fn visit_ty(&mut self, t: &'tcx Ty) {
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_incremental/persist/dirty_clean.rs
Expand Up @@ -114,7 +114,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {

match dep_node {
DepNode::Krate |
DepNode::Hir(_) => {
DepNode::Hir(_) |
DepNode::HirBody(_) => {
// HIR nodes are inputs, so if we are asserting that the HIR node is
// dirty, we check the dirty input set.
if !self.dirty_inputs.contains(&dep_node) {
Expand Down Expand Up @@ -143,7 +144,8 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {

match dep_node {
DepNode::Krate |
DepNode::Hir(_) => {
DepNode::Hir(_) |
DepNode::HirBody(_) => {
// For HIR nodes, check the inputs.
if self.dirty_inputs.contains(&dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_incremental/persist/hash.rs
Expand Up @@ -45,7 +45,9 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
match *dep_node {
DepNode::Krate |
DepNode::Hir(_) => true,
DepNode::Hir(_) |
DepNode::HirBody(_) =>
true,
DepNode::MetaData(def_id) => !def_id.is_local(),
_ => false,
}
Expand All @@ -58,7 +60,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
}

// HIR nodes (which always come from our crate) are an input:
DepNode::Hir(def_id) => {
DepNode::Hir(def_id) | DepNode::HirBody(def_id) => {
assert!(def_id.is_local(),
"cannot hash HIR for non-local def-id {:?} => {:?}",
def_id,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_incremental/persist/save.rs
Expand Up @@ -145,8 +145,8 @@ pub fn encode_dep_graph(preds: &Predecessors,
for (&target, sources) in &preds.inputs {
match *target {
DepNode::MetaData(ref def_id) => {
// Metadata *targets* are always local metadata nodes. We handle
// those in `encode_metadata_hashes`, which comes later.
// Metadata *targets* are always local metadata nodes. We have
// already handled those in `encode_metadata_hashes`.
assert!(def_id.is_local());
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/incremental/hello_world.rs
Expand Up @@ -31,7 +31,7 @@ mod x {
mod y {
use x;

#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn y() {
x::x();
}
Expand Down
4 changes: 3 additions & 1 deletion src/test/incremental/ich_method_call_trait_scope.rs
Expand Up @@ -46,12 +46,14 @@ mod mod3 {
mod mod3 {
use Trait2;

#[rustc_dirty(label="Hir", cfg="rpass2")]
#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_dirty(label="HirBody", cfg="rpass2")]
fn bar() {
().method();
}

#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn baz() {
22; // no method call, traits in scope don't matter
}
Expand Down
3 changes: 3 additions & 0 deletions src/test/incremental/ich_nested_items.rs
Expand Up @@ -23,11 +23,14 @@ fn foo() {

#[cfg(rpass2)]
#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn foo() {
#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn baz() { } // order is different...

#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn bar() { } // but that doesn't matter.

fn bap() { } // neither does adding a new item
Expand Down
8 changes: 6 additions & 2 deletions src/test/incremental/ich_resolve_results.rs
Expand Up @@ -45,11 +45,13 @@ mod mod3 {
use test;

#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn in_expr() {
Foo(0);
}

#[rustc_clean(label="Hir", cfg="rpass2")]
#[rustc_clean(label="HirBody", cfg="rpass2")]
fn in_type() {
test::<Foo>();
}
Expand All @@ -60,12 +62,14 @@ mod mod3 {
use test;
use mod2::Foo; // <-- This changed!

#[rustc_dirty(label="Hir", cfg="rpass3")]
#[rustc_clean(label="Hir", cfg="rpass3")]
#[rustc_dirty(label="HirBody", cfg="rpass3")]
fn in_expr() {
Foo(0);
}

#[rustc_dirty(label="Hir", cfg="rpass3")]
#[rustc_clean(label="Hir", cfg="rpass3")]
#[rustc_dirty(label="HirBody", cfg="rpass3")]
fn in_type() {
test::<Foo>();
}
Expand Down

0 comments on commit 936dbbc

Please sign in to comment.