Skip to content

incr.comp.: Cache Hir-DepNodeIndices in the HIR map. #44012

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

Merged
merged 1 commit into from
Aug 25, 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
4 changes: 2 additions & 2 deletions src/librustc/dep_graph/edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ impl DepGraphEdges {
self.edges.insert((source, target));
}

pub fn add_node(&mut self, node: DepNode) {
self.get_or_create_node(node);
pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex {
self.get_or_create_node(node)
}

#[inline]
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ impl DepGraph {
self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
}

pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
if let Some(ref data) = self.data {
data.edges.borrow_mut().add_node(node)
} else {
DepNodeIndex::INVALID
}
}

/// Indicates that a previous work product exists for `v`. This is
/// invoked during initial start-up based on what nodes are clean
/// (and what files exist in the incr. directory).
Expand Down
11 changes: 10 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,16 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:

pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
// NB: Deliberately force a compilation error if/when new fields are added.
let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
let ImplItem {
id: _,
hir_id: _,
name,
ref vis,
ref defaultness,
ref attrs,
ref node,
span
} = *impl_item;

visitor.visit_name(span, name);
visitor.visit_vis(vis);
Expand Down
27 changes: 21 additions & 6 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,12 @@ impl<'a> LoweringContext<'a> {
path.span = span;

self.allocate_hir_id_counter(import.id, import);
self.with_hir_id_owner(import.id, |this| {
let LoweredNodeId {
node_id: import_node_id,
hir_id: import_hir_id,
} = self.lower_node_id(import.id);

self.with_hir_id_owner(import_node_id, |this| {
let vis = match *vis {
hir::Visibility::Public => hir::Visibility::Public,
hir::Visibility::Crate => hir::Visibility::Crate,
Expand All @@ -1282,8 +1287,9 @@ impl<'a> LoweringContext<'a> {
}
};

this.items.insert(import.id, hir::Item {
id: import.id,
this.items.insert(import_node_id, hir::Item {
id: import_node_id,
hir_id: import_hir_id,
name: import.rename.unwrap_or(ident).name,
attrs: attrs.clone(),
node: hir::ItemUse(P(path), hir::UseKind::Single),
Expand Down Expand Up @@ -1414,8 +1420,11 @@ impl<'a> LoweringContext<'a> {

fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
self.with_parent_def(i.id, |this| {
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);

hir::TraitItem {
id: this.lower_node_id(i.id).node_id,
id: node_id,
hir_id,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
Expand Down Expand Up @@ -1475,8 +1484,11 @@ impl<'a> LoweringContext<'a> {

fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
self.with_parent_def(i.id, |this| {
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);

hir::ImplItem {
id: this.lower_node_id(i.id).node_id,
id: node_id,
hir_id,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
vis: this.lower_visibility(&i.vis, None),
Expand Down Expand Up @@ -1567,8 +1579,11 @@ impl<'a> LoweringContext<'a> {
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
});

let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);

Some(hir::Item {
id: self.lower_node_id(i.id).node_id,
id: node_id,
hir_id,
name,
attrs,
node,
Expand Down
194 changes: 165 additions & 29 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,55 @@

use super::*;

use dep_graph::{DepGraph, DepKind, DepNodeIndex};
use hir::intravisit::{Visitor, NestedVisitorMap};
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID};
use syntax_pos::Span;

/// A Visitor that walks over the HIR and collects Nodes into a HIR map
pub struct NodeCollector<'hir> {
pub(super) struct NodeCollector<'a, 'hir> {
/// The crate
pub krate: &'hir Crate,
krate: &'hir Crate,
/// The node map
pub(super) map: Vec<MapEntry<'hir>>,
map: Vec<MapEntry<'hir>>,
/// The parent of this node
pub parent_node: NodeId,
parent_node: NodeId,

current_dep_node_owner: DefIndex,
current_dep_node_index: DepNodeIndex,

dep_graph: &'a DepGraph,
definitions: &'a definitions::Definitions,
}

impl<'hir> NodeCollector<'hir> {
pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> {
impl<'a, 'hir> NodeCollector<'a, 'hir> {
pub(super) fn root(krate: &'hir Crate,
dep_graph: &'a DepGraph,
definitions: &'a definitions::Definitions)
-> NodeCollector<'a, 'hir> {
let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir);
let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node);

let mut collector = NodeCollector {
krate,
map: vec![],
parent_node: CRATE_NODE_ID,
current_dep_node_index: root_mod_dep_node_index,
current_dep_node_owner: CRATE_DEF_INDEX,
dep_graph,
definitions,
};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index));

collector
}

pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> {
self.map
}

fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
debug!("hir_map: {:?} => {:?}", id, entry);
let len = self.map.len();
Expand All @@ -47,8 +69,55 @@ impl<'hir> NodeCollector<'hir> {
}

fn insert(&mut self, id: NodeId, node: Node<'hir>) {
let entry = MapEntry::from_node(self.parent_node, node);
let parent = self.parent_node;
let dep_node_index = self.current_dep_node_index;

let entry = match node {
NodeItem(n) => EntryItem(parent, dep_node_index, n),
NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n),
NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n),
NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
NodeField(n) => EntryField(parent, dep_node_index, n),
NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
NodeTy(n) => EntryTy(parent, dep_node_index, n),
NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n),
NodeBinding(n) => EntryBinding(parent, dep_node_index, n),
NodePat(n) => EntryPat(parent, dep_node_index, n),
NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
};

// Make sure that the DepNode of some node coincides with the HirId
// owner of that node.
if cfg!(debug_assertions) {
let hir_id_owner = self.definitions.node_to_hir_id(id).owner;

if hir_id_owner != self.current_dep_node_owner {
let node_str = match self.definitions.opt_def_index(id) {
Some(def_index) => {
self.definitions.def_path(def_index).to_string_no_crate()
}
None => format!("{:?}", node)
};

bug!("inconsistent DepNode for `{}`: \
current_dep_node_owner={}, hir_id.owner={}",
node_str,
self.definitions
.def_path(self.current_dep_node_owner)
.to_string_no_crate(),
self.definitions.def_path(hir_id_owner).to_string_no_crate())
}
}

self.insert_entry(id, entry);

}

fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
Expand All @@ -57,9 +126,27 @@ impl<'hir> NodeCollector<'hir> {
f(self);
self.parent_node = parent_node;
}

fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self,
dep_node_owner: DefIndex,
f: F) {
let prev_owner = self.current_dep_node_owner;
let prev_index = self.current_dep_node_index;

// When we enter a new owner (item, impl item, or trait item), we always
// start out again with DepKind::Hir.
let new_dep_node = self.definitions
.def_path_hash(dep_node_owner)
.to_dep_node(DepKind::Hir);
self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
self.current_dep_node_owner = dep_node_owner;
f(self);
self.current_dep_node_index = prev_index;
self.current_dep_node_owner = prev_owner;
}
}

impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
Expand All @@ -82,25 +169,37 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
}

fn visit_nested_body(&mut self, id: BodyId) {
// When we enter a body, we switch to DepKind::HirBody.
// Note that current_dep_node_index might already be DepKind::HirBody,
// e.g. when entering the body of a closure that is already part of a
// surrounding body. That's expected and not a problem.
let prev_index = self.current_dep_node_index;
let new_dep_node = self.definitions
.def_path_hash(self.current_dep_node_owner)
.to_dep_node(DepKind::HirBody);
self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
self.visit_body(self.krate.body(id));
self.current_dep_node_index = prev_index;
}

fn visit_item(&mut self, i: &'hir Item) {
debug!("visit_item: {:?}", i);

self.insert(i.id, NodeItem(i));

self.with_parent(i.id, |this| {
match i.node {
ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.insert(struct_def.id(), NodeStructCtor(struct_def));
debug_assert_eq!(i.hir_id.owner,
self.definitions.opt_def_index(i.id).unwrap());
self.with_dep_node_owner(i.hir_id.owner, |this| {
this.insert(i.id, NodeItem(i));
this.with_parent(i.id, |this| {
match i.node {
ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.insert(struct_def.id(), NodeStructCtor(struct_def));
}
}
_ => {}
}
_ => {}
}
intravisit::walk_item(this, i);
intravisit::walk_item(this, i);
});
});
}

Expand All @@ -121,18 +220,26 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
}

fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
self.insert(ti.id, NodeTraitItem(ti));

self.with_parent(ti.id, |this| {
intravisit::walk_trait_item(this, ti);
debug_assert_eq!(ti.hir_id.owner,
self.definitions.opt_def_index(ti.id).unwrap());
self.with_dep_node_owner(ti.hir_id.owner, |this| {
this.insert(ti.id, NodeTraitItem(ti));

this.with_parent(ti.id, |this| {
intravisit::walk_trait_item(this, ti);
});
});
}

fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
self.insert(ii.id, NodeImplItem(ii));

self.with_parent(ii.id, |this| {
intravisit::walk_impl_item(this, ii);
debug_assert_eq!(ii.hir_id.owner,
self.definitions.opt_def_index(ii.id).unwrap());
self.with_dep_node_owner(ii.hir_id.owner, |this| {
this.insert(ii.id, NodeImplItem(ii));

this.with_parent(ii.id, |this| {
intravisit::walk_impl_item(this, ii);
});
});
}

Expand Down Expand Up @@ -238,4 +345,33 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
intravisit::walk_struct_field(this, field);
});
}

fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
// Do not visit the duplicate information in TraitItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
let TraitItemRef {
id,
name: _,
kind: _,
span: _,
defaultness: _,
} = *ii;

self.visit_nested_trait_item(id);
}

fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
// Do not visit the duplicate information in ImplItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
let ImplItemRef {
id,
name: _,
kind: _,
span: _,
vis: _,
defaultness: _,
} = *ii;

self.visit_nested_impl_item(id);
}
}
Loading