Skip to content

Commit d09fd1a

Browse files
committed
Instrument the AST map so that it registers reads when data is
acccessed.
1 parent 37fbfaf commit d09fd1a

File tree

8 files changed

+118
-18
lines changed

8 files changed

+118
-18
lines changed

src/librustc/dep_graph/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ impl DepGraph {
116116
}
117117
}
118118

119+
/// True if we are actually building a dep-graph. If this returns false,
120+
/// then the other methods on this `DepGraph` will have no net effect.
121+
#[inline]
122+
pub fn enabled(&self) -> bool {
123+
self.data.enabled()
124+
}
125+
119126
pub fn query(&self) -> DepGraphQuery {
120127
self.data.query()
121128
}

src/librustc/front/map/collector.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl<'ast> NodeCollector<'ast> {
7979

8080
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
8181
let parent_def = self.parent_def();
82+
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
8283
self.definitions.create_def_with_parent(parent_def, node_id, data)
8384
}
8485

@@ -115,10 +116,13 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
115116
/// deep walking so that we walk nested items in the context of
116117
/// their outer items.
117118
fn visit_nested_item(&mut self, item: ItemId) {
119+
debug!("visit_nested_item: {:?}", item);
118120
self.visit_item(self.krate.item(item.id))
119121
}
120122

121123
fn visit_item(&mut self, i: &'ast Item) {
124+
debug!("visit_item: {:?}", i);
125+
122126
// Pick the def data. This need not be unique, but the more
123127
// information we encapsulate into
124128
let def_data = match i.node {

src/librustc/front/map/mod.rs

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use self::MapEntry::*;
1414
use self::collector::NodeCollector;
1515
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
1616

17+
use dep_graph::{DepGraph, DepNode};
18+
1719
use middle::cstore::InlinedItem;
1820
use middle::cstore::InlinedItem as II;
1921
use middle::def_id::DefId;
@@ -228,19 +230,22 @@ impl<'ast> MapEntry<'ast> {
228230

229231
/// Stores a crate and any number of inlined items from other crates.
230232
pub struct Forest {
231-
pub krate: Crate,
233+
krate: Crate,
234+
pub dep_graph: DepGraph,
232235
inlined_items: TypedArena<InlinedParent>
233236
}
234237

235238
impl Forest {
236-
pub fn new(krate: Crate) -> Forest {
239+
pub fn new(krate: Crate, dep_graph: DepGraph) -> Forest {
237240
Forest {
238241
krate: krate,
242+
dep_graph: dep_graph,
239243
inlined_items: TypedArena::new()
240244
}
241245
}
242246

243247
pub fn krate<'ast>(&'ast self) -> &'ast Crate {
248+
self.dep_graph.read(DepNode::Krate);
244249
&self.krate
245250
}
246251
}
@@ -252,6 +257,10 @@ pub struct Map<'ast> {
252257
/// The backing storage for all the AST nodes.
253258
pub forest: &'ast Forest,
254259

260+
/// Same as the dep_graph in forest, just available with one fewer
261+
/// deref. This is a gratuitious micro-optimization.
262+
pub dep_graph: DepGraph,
263+
255264
/// NodeIds are sequential integers from 0, so we can be
256265
/// super-compact by storing them in a vector. Not everything with
257266
/// a NodeId is in the map, but empirically the occupancy is about
@@ -267,6 +276,60 @@ pub struct Map<'ast> {
267276
}
268277

269278
impl<'ast> Map<'ast> {
279+
/// Registers a read in the dependency graph of the AST node with
280+
/// the given `id`. This needs to be called each time a public
281+
/// function returns the HIR for a node -- in other words, when it
282+
/// "reveals" the content of a node to the caller (who might not
283+
/// otherwise have had access to those contents, and hence needs a
284+
/// read recorded). If the function just returns a DefId or
285+
/// NodeId, no actual content was returned, so no read is needed.
286+
fn read(&self, id: NodeId) {
287+
self.dep_graph.read(self.dep_node(id));
288+
}
289+
290+
fn dep_node(&self, id0: NodeId) -> DepNode {
291+
let map = self.map.borrow();
292+
let mut id = id0;
293+
loop {
294+
match map[id as usize] {
295+
EntryItem(_, item) => {
296+
let def_id = self.local_def_id(item.id);
297+
// NB ^~~~~~~
298+
//
299+
// You would expect that `item.id == id`, but this
300+
// is not always the case. In particular, for
301+
// ViewPath like `use self::{mem, foo}`, we record
302+
// map the ids for `mem` and `foo` to the
303+
// enclosing view path item. This seems mega super
304+
// ultra wrong, but then who am I to
305+
// judge. -nmatsakis
306+
return DepNode::Hir(def_id);
307+
}
308+
309+
EntryForeignItem(p, _) |
310+
EntryTraitItem(p, _) |
311+
EntryImplItem(p, _) |
312+
EntryVariant(p, _) |
313+
EntryExpr(p, _) |
314+
EntryStmt(p, _) |
315+
EntryLocal(p, _) |
316+
EntryPat(p, _) |
317+
EntryBlock(p, _) |
318+
EntryStructCtor(p, _) |
319+
EntryLifetime(p, _) |
320+
EntryTyParam(p, _) =>
321+
id = p,
322+
323+
RootCrate |
324+
RootInlinedParent(_) => // FIXME(#2369) clarify story about cross-crate dep tracking
325+
return DepNode::Krate,
326+
327+
NotPresent =>
328+
panic!("Walking parents from `{}` led to `NotPresent` at `{}`", id0, id),
329+
}
330+
}
331+
}
332+
270333
pub fn num_local_def_ids(&self) -> usize {
271334
self.definitions.borrow().len()
272335
}
@@ -309,26 +372,30 @@ impl<'ast> Map<'ast> {
309372
}
310373

311374
pub fn krate(&self) -> &'ast Crate {
312-
&self.forest.krate
375+
self.forest.krate()
313376
}
314377

315378
/// Retrieve the Node corresponding to `id`, panicking if it cannot
316379
/// be found.
317380
pub fn get(&self, id: NodeId) -> Node<'ast> {
318381
match self.find(id) {
319-
Some(node) => node,
382+
Some(node) => node, // read recorded by `find`
320383
None => panic!("couldn't find node id {} in the AST map", id)
321384
}
322385
}
323386

324387
pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
325-
self.as_local_node_id(id).map(|id| self.get(id))
388+
self.as_local_node_id(id).map(|id| self.get(id)) // read recorded by `get`
326389
}
327390

328391
/// Retrieve the Node corresponding to `id`, returning None if
329392
/// cannot be found.
330393
pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
331-
self.find_entry(id).and_then(|x| x.to_node())
394+
let result = self.find_entry(id).and_then(|x| x.to_node());
395+
if result.is_some() {
396+
self.read(id);
397+
}
398+
result
332399
}
333400

334401
/// Similar to get_parent, returns the parent node id or id if there is no
@@ -459,22 +526,25 @@ impl<'ast> Map<'ast> {
459526
_ => None
460527
};
461528
match abi {
462-
Some(abi) => abi,
529+
Some(abi) => {
530+
self.read(id); // reveals some of the content of a node
531+
abi
532+
}
463533
None => panic!("expected foreign mod or inlined parent, found {}",
464534
self.node_to_string(parent))
465535
}
466536
}
467537

468538
pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
469-
let vis = self.expect_foreign_item(id).vis;
470-
match self.find(self.get_parent(id)) {
539+
let vis = self.expect_foreign_item(id).vis; // read recorded by `expect_foreign_item`
540+
match self.find(self.get_parent(id)) { // read recorded by `find`
471541
Some(NodeItem(i)) => vis.inherit_from(i.vis),
472542
_ => vis
473543
}
474544
}
475545

476546
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
477-
match self.find(id) {
547+
match self.find(id) { // read recorded by `id`
478548
Some(NodeItem(item)) => item,
479549
_ => panic!("expected item, found {}", self.node_to_string(id))
480550
}
@@ -521,7 +591,7 @@ impl<'ast> Map<'ast> {
521591
}
522592

523593
pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
524-
match self.find(id) {
594+
match self.find(id) { // read recorded by find
525595
Some(NodeExpr(expr)) => expr,
526596
_ => panic!("expected expr, found {}", self.node_to_string(id))
527597
}
@@ -571,6 +641,11 @@ impl<'ast> Map<'ast> {
571641
fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
572642
F: FnOnce(PathElems) -> T,
573643
{
644+
// This function reveals the name of the item and hence is a
645+
// kind of read. This is inefficient, since it walks ancestors
646+
// and we are walking them anyhow, but whatever.
647+
self.read(id);
648+
574649
let parent = self.get_parent(id);
575650
let parent = match self.find_entry(id) {
576651
Some(EntryForeignItem(..)) => {
@@ -602,6 +677,7 @@ impl<'ast> Map<'ast> {
602677
/// Given a node ID, get a list of attributes associated with the AST
603678
/// corresponding to the Node ID
604679
pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
680+
self.read(id); // reveals attributes on the node
605681
let attrs = match self.find(id) {
606682
Some(NodeItem(i)) => Some(&i.attrs[..]),
607683
Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
@@ -655,6 +731,7 @@ impl<'ast> Map<'ast> {
655731
}
656732

657733
pub fn span(&self, id: NodeId) -> Span {
734+
self.read(id); // reveals span from node
658735
self.opt_span(id)
659736
.unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
660737
}
@@ -833,6 +910,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
833910

834911
Map {
835912
forest: forest,
913+
dep_graph: forest.dep_graph.clone(),
836914
map: RefCell::new(map),
837915
definitions: RefCell::new(definitions),
838916
}

src/librustc/middle/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ impl<'tcx> ctxt<'tcx> {
509509
{
510510
let interner = RefCell::new(FnvHashMap());
511511
let common_types = CommonTypes::new(&arenas.type_, &interner);
512-
let dep_graph = DepGraph::new(s.opts.incremental_compilation);
512+
let dep_graph = map.dep_graph.clone();
513513
let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
514514
tls::enter(ctxt {
515515
arenas: arenas,

src/librustc/session/config.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,13 @@ pub struct Options {
137137
pub no_trans: bool,
138138
pub error_format: ErrorOutputType,
139139
pub treat_err_as_bug: bool,
140-
pub incremental_compilation: bool,
140+
141+
/// if true, build up the dep-graph
142+
pub build_dep_graph: bool,
143+
144+
/// if true, -Z dump-dep-graph was passed to dump out the dep-graph
141145
pub dump_dep_graph: bool,
146+
142147
pub no_analysis: bool,
143148
pub debugging_opts: DebuggingOptions,
144149
pub prints: Vec<PrintRequest>,
@@ -246,7 +251,7 @@ pub fn basic_options() -> Options {
246251
parse_only: false,
247252
no_trans: false,
248253
treat_err_as_bug: false,
249-
incremental_compilation: false,
254+
build_dep_graph: false,
250255
dump_dep_graph: false,
251256
no_analysis: false,
252257
debugging_opts: basic_debugging_options(),
@@ -1145,7 +1150,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
11451150
parse_only: parse_only,
11461151
no_trans: no_trans,
11471152
treat_err_as_bug: treat_err_as_bug,
1148-
incremental_compilation: incremental_compilation || dump_dep_graph,
1153+
build_dep_graph: incremental_compilation || dump_dep_graph,
11491154
dump_dep_graph: dump_dep_graph,
11501155
no_analysis: no_analysis,
11511156
debugging_opts: debugging_opts,

src/librustdoc/core.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub use self::MaybeTyped::*;
1111

1212
use rustc_lint;
1313
use rustc_driver::{driver, target_features, abort_on_err};
14+
use rustc::dep_graph::DepGraph;
1415
use rustc::session::{self, config};
1516
use rustc::middle::def_id::DefId;
1617
use rustc::middle::privacy::AccessLevels;
@@ -143,7 +144,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
143144
let krate = driver::assign_node_ids(&sess, krate);
144145
// Lower ast -> hir.
145146
let lcx = LoweringContext::new(&sess, Some(&krate));
146-
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
147+
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), DepGraph::new(false));
147148
let arenas = ty::CtxtArenas::new();
148149
let hir_map = driver::make_map(&sess, &mut hir_forest);
149150

src/librustdoc/test.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::sync::{Arc, Mutex};
2525

2626
use testing;
2727
use rustc_lint;
28+
use rustc::dep_graph::DepGraph;
2829
use rustc::front::map as hir_map;
2930
use rustc::session::{self, config};
3031
use rustc::session::config::{get_unstable_features_setting, OutputType};
@@ -99,7 +100,9 @@ pub fn run(input: &str,
99100

100101
let opts = scrape_test_config(&krate);
101102

102-
let mut forest = hir_map::Forest::new(krate);
103+
let dep_graph = DepGraph::new(false);
104+
let _ignore = dep_graph.in_ignore();
105+
let mut forest = hir_map::Forest::new(krate, dep_graph.clone());
103106
let map = hir_map::map_crate(&mut forest);
104107

105108
let ctx = core::DocContext {

src/test/run-make/execution-engine/test.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use std::path::PathBuf;
2626
use std::rc::Rc;
2727
use std::thread::Builder;
2828

29+
use rustc::dep_graph::DepGraph;
2930
use rustc::front::map as ast_map;
3031
use rustc::llvm;
3132
use rustc::middle::cstore::{CrateStore, LinkagePreference};
@@ -236,7 +237,8 @@ fn compile_program(input: &str, sysroot: PathBuf)
236237

237238
let krate = driver::assign_node_ids(&sess, krate);
238239
let lcx = LoweringContext::new(&sess, Some(&krate));
239-
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate));
240+
let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
241+
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
240242
let arenas = ty::CtxtArenas::new();
241243
let ast_map = driver::make_map(&sess, &mut hir_forest);
242244

0 commit comments

Comments
 (0)