]> git.lizzy.rs Git - rust.git/blob - src/librustc/dep_graph/graph.rs
Move the Lock into OpenTask
[rust.git] / src / librustc / dep_graph / graph.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use errors::DiagnosticBuilder;
12 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
15 use rustc_data_structures::sync::{Lrc, RwLock, ReadGuard, Lock};
16 use std::env;
17 use std::hash::Hash;
18 use ty::{self, TyCtxt};
19 use util::common::{ProfileQueriesMsg, profq_msg};
20
21 use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint};
22
23 use super::debug::EdgeFilter;
24 use super::dep_node::{DepNode, DepKind, WorkProductId};
25 use super::query::DepGraphQuery;
26 use super::safe::DepGraphSafe;
27 use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
28 use super::prev::PreviousDepGraph;
29
30 #[derive(Clone)]
31 pub struct DepGraph {
32     data: Option<Lrc<DepGraphData>>,
33
34     // A vector mapping depnodes from the current graph to their associated
35     // result value fingerprints. Do not rely on the length of this vector
36     // being the same as the number of nodes in the graph. The vector can
37     // contain an arbitrary number of zero-entries at the end.
38     fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>>
39 }
40
41
42 newtype_index!(DepNodeIndex);
43
44 impl DepNodeIndex {
45     const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX);
46 }
47
48 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
49 pub enum DepNodeColor {
50     Red,
51     Green(DepNodeIndex)
52 }
53
54 impl DepNodeColor {
55     pub fn is_green(self) -> bool {
56         match self {
57             DepNodeColor::Red => false,
58             DepNodeColor::Green(_) => true,
59         }
60     }
61 }
62
63 struct DepGraphData {
64     /// The new encoding of the dependency graph, optimized for red/green
65     /// tracking. The `current` field is the dependency graph of only the
66     /// current compilation session: We don't merge the previous dep-graph into
67     /// current one anymore.
68     current: Lock<CurrentDepGraph>,
69
70     /// The dep-graph from the previous compilation session. It contains all
71     /// nodes and edges as well as all fingerprints of nodes that have them.
72     previous: PreviousDepGraph,
73
74     colors: Lock<DepNodeColorMap>,
75
76     /// When we load, there may be `.o` files, cached mir, or other such
77     /// things available to us. If we find that they are not dirty, we
78     /// load the path to the file storing those work-products here into
79     /// this map. We can later look for and extract that data.
80     previous_work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>,
81
82     /// Work-products that we generate in this run.
83     work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>,
84
85     dep_node_debug: Lock<FxHashMap<DepNode, String>>,
86
87     // Used for testing, only populated when -Zquery-dep-graph is specified.
88     loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>,
89 }
90
91 impl DepGraph {
92
93     pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
94         // Pre-allocate the fingerprints array. We over-allocate a little so
95         // that we hopefully don't have to re-allocate during this compilation
96         // session.
97         let prev_graph_node_count = prev_graph.node_count();
98
99         let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
100                                                  (prev_graph_node_count * 115) / 100);
101         DepGraph {
102             data: Some(Lrc::new(DepGraphData {
103                 previous_work_products: RwLock::new(FxHashMap()),
104                 work_products: RwLock::new(FxHashMap()),
105                 dep_node_debug: Lock::new(FxHashMap()),
106                 current: Lock::new(CurrentDepGraph::new()),
107                 previous: prev_graph,
108                 colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
109                 loaded_from_cache: Lock::new(FxHashMap()),
110             })),
111             fingerprints: Lrc::new(Lock::new(fingerprints)),
112         }
113     }
114
115     pub fn new_disabled() -> DepGraph {
116         DepGraph {
117             data: None,
118             fingerprints: Lrc::new(Lock::new(IndexVec::new())),
119         }
120     }
121
122     /// True if we are actually building the full dep-graph.
123     #[inline]
124     pub fn is_fully_enabled(&self) -> bool {
125         self.data.is_some()
126     }
127
128     pub fn query(&self) -> DepGraphQuery {
129         let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
130         let nodes: Vec<_> = current_dep_graph.nodes.iter().cloned().collect();
131         let mut edges = Vec::new();
132         for (index, edge_targets) in current_dep_graph.edges.iter_enumerated() {
133             let from = current_dep_graph.nodes[index];
134             for &edge_target in edge_targets {
135                 let to = current_dep_graph.nodes[edge_target];
136                 edges.push((from, to));
137             }
138         }
139
140         DepGraphQuery::new(&nodes[..], &edges[..])
141     }
142
143     pub fn assert_ignored(&self)
144     {
145         if let Some(..) = self.data {
146             ty::tls::with_context_opt(|icx| {
147                 let icx = if let Some(icx) = icx { icx } else { return };
148                 match *icx.task {
149                     OpenTask::Ignore => {
150                         // ignored
151                     }
152                     _ => panic!("expected an ignore context")
153                 }
154             })
155         }
156     }
157
158     pub fn with_ignore<OP,R>(&self, op: OP) -> R
159         where OP: FnOnce() -> R
160     {
161         ty::tls::with_context(|icx| {
162             let icx = ty::tls::ImplicitCtxt {
163                 task: &OpenTask::Ignore,
164                 ..icx.clone()
165             };
166
167             ty::tls::enter_context(&icx, |_| {
168                 op()
169             })
170         })
171     }
172
173     /// Starts a new dep-graph task. Dep-graph tasks are specified
174     /// using a free function (`task`) and **not** a closure -- this
175     /// is intentional because we want to exercise tight control over
176     /// what state they have access to. In particular, we want to
177     /// prevent implicit 'leaks' of tracked state into the task (which
178     /// could then be read without generating correct edges in the
179     /// dep-graph -- see the [rustc guide] for more details on
180     /// the dep-graph). To this end, the task function gets exactly two
181     /// pieces of state: the context `cx` and an argument `arg`. Both
182     /// of these bits of state must be of some type that implements
183     /// `DepGraphSafe` and hence does not leak.
184     ///
185     /// The choice of two arguments is not fundamental. One argument
186     /// would work just as well, since multiple values can be
187     /// collected using tuples. However, using two arguments works out
188     /// to be quite convenient, since it is common to need a context
189     /// (`cx`) and some argument (e.g., a `DefId` identifying what
190     /// item to process).
191     ///
192     /// For cases where you need some other number of arguments:
193     ///
194     /// - If you only need one argument, just use `()` for the `arg`
195     ///   parameter.
196     /// - If you need 3+ arguments, use a tuple for the
197     ///   `arg` parameter.
198     ///
199     /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/incremental-compilation.html
200     pub fn with_task<'gcx, C, A, R>(&self,
201                                    key: DepNode,
202                                    cx: C,
203                                    arg: A,
204                                    task: fn(C, A) -> R)
205                                    -> (R, DepNodeIndex)
206         where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
207               R: HashStable<StableHashingContext<'gcx>>,
208     {
209         self.with_task_impl(key, cx, arg, false, task,
210             |key| OpenTask::Regular(Lock::new(RegularOpenTask {
211                 node: key,
212                 reads: Vec::new(),
213                 read_set: FxHashSet(),
214             })),
215             |data, key, task| data.borrow_mut().complete_task(key, task))
216     }
217
218     /// Creates a new dep-graph input with value `input`
219     pub fn input_task<'gcx, C, R>(&self,
220                                    key: DepNode,
221                                    cx: C,
222                                    input: R)
223                                    -> (R, DepNodeIndex)
224         where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
225               R: HashStable<StableHashingContext<'gcx>>,
226     {
227         fn identity_fn<C, A>(_: C, arg: A) -> A {
228             arg
229         }
230
231         self.with_task_impl(key, cx, input, true, identity_fn,
232             |_| OpenTask::Ignore,
233             |data, key, _| data.borrow_mut().alloc_node(key, Vec::new()))
234     }
235
236     fn with_task_impl<'gcx, C, A, R>(
237         &self,
238         key: DepNode,
239         cx: C,
240         arg: A,
241         no_tcx: bool,
242         task: fn(C, A) -> R,
243         create_task: fn(DepNode) -> OpenTask,
244         finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
245                                           DepNode,
246                                           OpenTask) -> DepNodeIndex
247     ) -> (R, DepNodeIndex)
248     where
249         C: DepGraphSafe + StableHashingContextProvider<'gcx>,
250         R: HashStable<StableHashingContext<'gcx>>,
251     {
252         if let Some(ref data) = self.data {
253             let open_task = create_task(key);
254
255             // In incremental mode, hash the result of the task. We don't
256             // do anything with the hash yet, but we are computing it
257             // anyway so that
258             //  - we make sure that the infrastructure works and
259             //  - we can get an idea of the runtime cost.
260             let mut hcx = cx.get_stable_hashing_context();
261
262             if cfg!(debug_assertions) {
263                 profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
264             };
265
266             let result = if no_tcx {
267                 task(cx, arg)
268             } else {
269                 ty::tls::with_context(|icx| {
270                     let icx = ty::tls::ImplicitCtxt {
271                         task: &open_task,
272                         ..icx.clone()
273                     };
274
275                     ty::tls::enter_context(&icx, |_| {
276                         task(cx, arg)
277                     })
278                 })
279             };
280
281             if cfg!(debug_assertions) {
282                 profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
283             };
284
285             let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task);
286
287             let mut stable_hasher = StableHasher::new();
288             result.hash_stable(&mut hcx, &mut stable_hasher);
289
290             let current_fingerprint = stable_hasher.finish();
291
292             // Store the current fingerprint
293             {
294                 let mut fingerprints = self.fingerprints.borrow_mut();
295
296                 if dep_node_index.index() >= fingerprints.len() {
297                     fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
298                 }
299
300                 debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
301                               "DepGraph::with_task() - Duplicate fingerprint \
302                                insertion for {:?}", key);
303                 fingerprints[dep_node_index] = current_fingerprint;
304             }
305
306             // Determine the color of the new DepNode.
307             if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
308                 let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
309
310                 let color = if current_fingerprint == prev_fingerprint {
311                     DepNodeColor::Green(dep_node_index)
312                 } else {
313                     DepNodeColor::Red
314                 };
315
316                 let mut colors = data.colors.borrow_mut();
317                 debug_assert!(colors.get(prev_index).is_none(),
318                               "DepGraph::with_task() - Duplicate DepNodeColor \
319                                insertion for {:?}", key);
320
321                 colors.insert(prev_index, color);
322             }
323
324             (result, dep_node_index)
325         } else {
326             if key.kind.fingerprint_needed_for_crate_hash() {
327                 let mut hcx = cx.get_stable_hashing_context();
328                 let result = task(cx, arg);
329                 let mut stable_hasher = StableHasher::new();
330                 result.hash_stable(&mut hcx, &mut stable_hasher);
331                 let fingerprint = stable_hasher.finish();
332
333                 let mut fingerprints = self.fingerprints.borrow_mut();
334                 let dep_node_index = DepNodeIndex::new(fingerprints.len());
335                 fingerprints.push(fingerprint);
336
337                 debug_assert!(fingerprints[dep_node_index] == fingerprint,
338                               "DepGraph::with_task() - Assigned fingerprint to \
339                                unexpected index for {:?}", key);
340
341                 (result, dep_node_index)
342             } else {
343                 (task(cx, arg), DepNodeIndex::INVALID)
344             }
345         }
346     }
347
348     /// Execute something within an "anonymous" task, that is, a task the
349     /// DepNode of which is determined by the list of inputs it read from.
350     pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
351         where OP: FnOnce() -> R
352     {
353         if let Some(ref data) = self.data {
354             let (result, open_task) = ty::tls::with_context(|icx| {
355                 let task = OpenTask::Anon(Lock::new(AnonOpenTask {
356                     reads: Vec::new(),
357                     read_set: FxHashSet(),
358                 }));
359
360                 let r = {
361                     let icx = ty::tls::ImplicitCtxt {
362                         task: &task,
363                         ..icx.clone()
364                     };
365
366                     ty::tls::enter_context(&icx, |_| {
367                         op()
368                     })
369                 };
370
371                 (r, task)
372             });
373             let dep_node_index = data.current
374                                      .borrow_mut()
375                                      .pop_anon_task(dep_kind, open_task);
376             (result, dep_node_index)
377         } else {
378             (op(), DepNodeIndex::INVALID)
379         }
380     }
381
382     /// Execute something within an "eval-always" task which is a task
383     // that runs whenever anything changes.
384     pub fn with_eval_always_task<'gcx, C, A, R>(&self,
385                                    key: DepNode,
386                                    cx: C,
387                                    arg: A,
388                                    task: fn(C, A) -> R)
389                                    -> (R, DepNodeIndex)
390         where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
391               R: HashStable<StableHashingContext<'gcx>>,
392     {
393         self.with_task_impl(key, cx, arg, false, task,
394             |key| OpenTask::EvalAlways { node: key },
395             |data, key, task| data.borrow_mut().complete_eval_always_task(key, task))
396     }
397
398     #[inline]
399     pub fn read(&self, v: DepNode) {
400         if let Some(ref data) = self.data {
401             let mut current = data.current.borrow_mut();
402             if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
403                 current.read_index(dep_node_index);
404             } else {
405                 bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
406             }
407         }
408     }
409
410     #[inline]
411     pub fn read_index(&self, dep_node_index: DepNodeIndex) {
412         if let Some(ref data) = self.data {
413             data.current.borrow_mut().read_index(dep_node_index);
414         }
415     }
416
417     #[inline]
418     pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
419         self.data
420             .as_ref()
421             .unwrap()
422             .current
423             .borrow_mut()
424             .node_to_node_index
425             .get(dep_node)
426             .cloned()
427             .unwrap()
428     }
429
430     #[inline]
431     pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
432         if let Some(ref data) = self.data {
433             data.current.borrow_mut().node_to_node_index.contains_key(dep_node)
434         } else {
435             false
436         }
437     }
438
439     #[inline]
440     pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
441         match self.fingerprints.borrow().get(dep_node_index) {
442             Some(&fingerprint) => fingerprint,
443             None => {
444                 if let Some(ref data) = self.data {
445                     let dep_node = data.current.borrow().nodes[dep_node_index];
446                     bug!("Could not find current fingerprint for {:?}", dep_node)
447                 } else {
448                     bug!("Could not find current fingerprint for {:?}", dep_node_index)
449                 }
450             }
451         }
452     }
453
454     pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
455         self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
456     }
457
458     #[inline]
459     pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
460         self.data.as_ref().unwrap().previous.node_to_index(dep_node)
461     }
462
463     /// Indicates that a previous work product exists for `v`. This is
464     /// invoked during initial start-up based on what nodes are clean
465     /// (and what files exist in the incr. directory).
466     pub fn insert_previous_work_product(&self, v: &WorkProductId, data: WorkProduct) {
467         debug!("insert_previous_work_product({:?}, {:?})", v, data);
468         self.data
469             .as_ref()
470             .unwrap()
471             .previous_work_products
472             .borrow_mut()
473             .insert(v.clone(), data);
474     }
475
476     /// Indicates that we created the given work-product in this run
477     /// for `v`. This record will be preserved and loaded in the next
478     /// run.
479     pub fn insert_work_product(&self, v: &WorkProductId, data: WorkProduct) {
480         debug!("insert_work_product({:?}, {:?})", v, data);
481         self.data
482             .as_ref()
483             .unwrap()
484             .work_products
485             .borrow_mut()
486             .insert(v.clone(), data);
487     }
488
489     /// Check whether a previous work product exists for `v` and, if
490     /// so, return the path that leads to it. Used to skip doing work.
491     pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
492         self.data
493             .as_ref()
494             .and_then(|data| {
495                 data.previous_work_products.borrow().get(v).cloned()
496             })
497     }
498
499     /// Access the map of work-products created during this run. Only
500     /// used during saving of the dep-graph.
501     pub fn work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> {
502         self.data.as_ref().unwrap().work_products.borrow()
503     }
504
505     /// Access the map of work-products created during the cached run. Only
506     /// used during saving of the dep-graph.
507     pub fn previous_work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> {
508         self.data.as_ref().unwrap().previous_work_products.borrow()
509     }
510
511     #[inline(always)]
512     pub fn register_dep_node_debug_str<F>(&self,
513                                           dep_node: DepNode,
514                                           debug_str_gen: F)
515         where F: FnOnce() -> String
516     {
517         let dep_node_debug = &self.data.as_ref().unwrap().dep_node_debug;
518
519         if dep_node_debug.borrow().contains_key(&dep_node) {
520             return
521         }
522         let debug_str = debug_str_gen();
523         dep_node_debug.borrow_mut().insert(dep_node, debug_str);
524     }
525
526     pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
527         self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned())
528     }
529
530     pub fn edge_deduplication_data(&self) -> (u64, u64) {
531         let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
532
533         (current_dep_graph.total_read_count, current_dep_graph.total_duplicate_read_count)
534     }
535
536     pub fn serialize(&self) -> SerializedDepGraph {
537         let mut fingerprints = self.fingerprints.borrow_mut();
538         let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
539
540         // Make sure we don't run out of bounds below.
541         if current_dep_graph.nodes.len() > fingerprints.len() {
542             fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
543         }
544
545         let fingerprints = fingerprints.clone().convert_index_type();
546         let nodes = current_dep_graph.nodes.clone().convert_index_type();
547
548         let total_edge_count: usize = current_dep_graph.edges.iter()
549                                                              .map(|v| v.len())
550                                                              .sum();
551
552         let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
553         let mut edge_list_data = Vec::with_capacity(total_edge_count);
554
555         for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() {
556             let start = edge_list_data.len() as u32;
557             // This should really just be a memcpy :/
558             edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index())));
559             let end = edge_list_data.len() as u32;
560
561             debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
562             edge_list_indices.push((start, end));
563         }
564
565         debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
566         debug_assert_eq!(edge_list_data.len(), total_edge_count);
567
568         SerializedDepGraph {
569             nodes,
570             fingerprints,
571             edge_list_indices,
572             edge_list_data,
573         }
574     }
575
576     pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
577         if let Some(ref data) = self.data {
578             if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
579                 return data.colors.borrow().get(prev_index)
580             } else {
581                 // This is a node that did not exist in the previous compilation
582                 // session, so we consider it to be red.
583                 return Some(DepNodeColor::Red)
584             }
585         }
586
587         None
588     }
589
590     pub fn try_mark_green<'tcx>(&self,
591                                 tcx: TyCtxt<'_, 'tcx, 'tcx>,
592                                 dep_node: &DepNode)
593                                 -> Option<DepNodeIndex> {
594         debug!("try_mark_green({:?}) - BEGIN", dep_node);
595         let data = self.data.as_ref().unwrap();
596
597         #[cfg(not(parallel_queries))]
598         debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
599
600         if dep_node.kind.is_input() {
601             // We should only hit try_mark_green() for inputs that do not exist
602             // anymore in the current compilation session. Existing inputs are
603             // eagerly marked as either red/green before any queries are
604             // executed.
605             debug_assert!(dep_node.extract_def_id(tcx).is_none());
606             debug!("try_mark_green({:?}) - END - DepNode is deleted input", dep_node);
607             return None;
608         }
609
610         let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
611             Some(prev) => {
612                 // This DepNode and the corresponding query invocation existed
613                 // in the previous compilation session too, so we can try to
614                 // mark it as green by recursively marking all of its
615                 // dependencies green.
616                 prev
617             }
618             None => {
619                 // This DepNode did not exist in the previous compilation session,
620                 // so we cannot mark it as green.
621                 debug!("try_mark_green({:?}) - END - DepNode does not exist in \
622                         current compilation session anymore", dep_node);
623                 return None
624             }
625         };
626
627         debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());
628
629         let mut current_deps = Vec::new();
630
631         for &dep_dep_node_index in prev_deps {
632             let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
633
634             match dep_dep_node_color {
635                 Some(DepNodeColor::Green(node_index)) => {
636                     // This dependency has been marked as green before, we are
637                     // still fine and can continue with checking the other
638                     // dependencies.
639                     debug!("try_mark_green({:?}) --- found dependency {:?} to \
640                             be immediately green",
641                             dep_node,
642                             data.previous.index_to_node(dep_dep_node_index));
643                     current_deps.push(node_index);
644                 }
645                 Some(DepNodeColor::Red) => {
646                     // We found a dependency the value of which has changed
647                     // compared to the previous compilation session. We cannot
648                     // mark the DepNode as green and also don't need to bother
649                     // with checking any of the other dependencies.
650                     debug!("try_mark_green({:?}) - END - dependency {:?} was \
651                             immediately red",
652                             dep_node,
653                             data.previous.index_to_node(dep_dep_node_index));
654                     return None
655                 }
656                 None => {
657                     let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index);
658
659                     // We don't know the state of this dependency. If it isn't
660                     // an input node, let's try to mark it green recursively.
661                     if !dep_dep_node.kind.is_input() {
662                          debug!("try_mark_green({:?}) --- state of dependency {:?} \
663                                  is unknown, trying to mark it green", dep_node,
664                                  dep_dep_node);
665
666                         if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
667                             debug!("try_mark_green({:?}) --- managed to MARK \
668                                     dependency {:?} as green", dep_node, dep_dep_node);
669                             current_deps.push(node_index);
670                             continue;
671                         }
672                     } else {
673                         match dep_dep_node.kind {
674                             DepKind::Hir |
675                             DepKind::HirBody |
676                             DepKind::CrateMetadata => {
677                                 if dep_node.extract_def_id(tcx).is_none() {
678                                     // If the node does not exist anymore, we
679                                     // just fail to mark green.
680                                     return None
681                                 } else {
682                                     // If the node does exist, it should have
683                                     // been pre-allocated.
684                                     bug!("DepNode {:?} should have been \
685                                           pre-allocated but wasn't.",
686                                           dep_dep_node)
687                                 }
688                             }
689                             _ => {
690                                 // For other kinds of inputs it's OK to be
691                                 // forced.
692                             }
693                         }
694                     }
695
696                     // We failed to mark it green, so we try to force the query.
697                     debug!("try_mark_green({:?}) --- trying to force \
698                             dependency {:?}", dep_node, dep_dep_node);
699                     if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
700                         let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
701
702                         match dep_dep_node_color {
703                             Some(DepNodeColor::Green(node_index)) => {
704                                 debug!("try_mark_green({:?}) --- managed to \
705                                         FORCE dependency {:?} to green",
706                                         dep_node, dep_dep_node);
707                                 current_deps.push(node_index);
708                             }
709                             Some(DepNodeColor::Red) => {
710                                 debug!("try_mark_green({:?}) - END - \
711                                         dependency {:?} was red after forcing",
712                                        dep_node,
713                                        dep_dep_node);
714                                 return None
715                             }
716                             None => {
717                                 if !tcx.sess.has_errors() {
718                                     bug!("try_mark_green() - Forcing the DepNode \
719                                           should have set its color")
720                                 } else {
721                                     // If the query we just forced has resulted
722                                     // in some kind of compilation error, we
723                                     // don't expect that the corresponding
724                                     // dep-node color has been updated.
725                                 }
726                             }
727                         }
728                     } else {
729                         // The DepNode could not be forced.
730                         debug!("try_mark_green({:?}) - END - dependency {:?} \
731                                 could not be forced", dep_node, dep_dep_node);
732                         return None
733                     }
734                 }
735             }
736         }
737
738         // If we got here without hitting a `return` that means that all
739         // dependencies of this DepNode could be marked as green. Therefore we
740         // can also mark this DepNode as green.
741
742         // There may be multiple threads trying to mark the same dep node green concurrently
743
744         let (dep_node_index, did_allocation) = {
745             let mut current = data.current.borrow_mut();
746
747             if let Some(&dep_node_index) = current.node_to_node_index.get(&dep_node) {
748                 // Someone else allocated it before us
749                 (dep_node_index, false)
750             } else {
751                 // We allocating an entry for the node in the current dependency graph and
752                 // adding all the appropriate edges imported from the previous graph
753                 (current.alloc_node(*dep_node, current_deps), true)
754             }
755         };
756
757         // ... copying the fingerprint from the previous graph too, so we don't
758         // have to recompute it ...
759         {
760             let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
761             let mut fingerprints = self.fingerprints.borrow_mut();
762
763             if dep_node_index.index() >= fingerprints.len() {
764                 fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
765             }
766
767             // Multiple threads can all write the same fingerprint here
768             #[cfg(not(parallel_queries))]
769             debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
770                 "DepGraph::try_mark_green() - Duplicate fingerprint \
771                 insertion for {:?}", dep_node);
772
773             fingerprints[dep_node_index] = fingerprint;
774         }
775
776         // ... emitting any stored diagnostic ...
777         if did_allocation {
778             // Only the thread which did the allocation emits the error messages
779
780             // FIXME: Ensure that these are printed before returning for all threads.
781             // Currently threads where did_allocation = false can continue on
782             // and emit other diagnostics before these diagnostics are emitted.
783             // Such diagnostics should be emitted after these.
784             // See https://github.com/rust-lang/rust/issues/48685
785             let diagnostics = tcx.on_disk_query_result_cache
786                                  .load_diagnostics(tcx, prev_dep_node_index);
787
788             if diagnostics.len() > 0 {
789                 let handle = tcx.sess.diagnostic();
790
791                 // Promote the previous diagnostics to the current session.
792                 tcx.on_disk_query_result_cache
793                    .store_diagnostics(dep_node_index, diagnostics.clone());
794
795                 for diagnostic in diagnostics {
796                     DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
797                 }
798             }
799         }
800
801         // ... and finally storing a "Green" entry in the color map.
802         let mut colors = data.colors.borrow_mut();
803         // Multiple threads can all write the same color here
804         #[cfg(not(parallel_queries))]
805         debug_assert!(colors.get(prev_dep_node_index).is_none(),
806                       "DepGraph::try_mark_green() - Duplicate DepNodeColor \
807                       insertion for {:?}", dep_node);
808
809         colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
810
811         debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
812         Some(dep_node_index)
813     }
814
815     // Returns true if the given node has been marked as green during the
816     // current compilation session. Used in various assertions
817     pub fn is_green(&self, dep_node: &DepNode) -> bool {
818         self.node_color(dep_node).map(|c| c.is_green()).unwrap_or(false)
819     }
820
821     // This method loads all on-disk cacheable query results into memory, so
822     // they can be written out to the new cache file again. Most query results
823     // will already be in memory but in the case where we marked something as
824     // green but then did not need the value, that value will never have been
825     // loaded from disk.
826     //
827     // This method will only load queries that will end up in the disk cache.
828     // Other queries will not be executed.
829     pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
830         let green_nodes: Vec<DepNode> = {
831             let data = self.data.as_ref().unwrap();
832             let colors = data.colors.borrow();
833             colors.values.indices().filter_map(|prev_index| {
834                 match colors.get(prev_index) {
835                     Some(DepNodeColor::Green(_)) => {
836                         let dep_node = data.previous.index_to_node(prev_index);
837                         if dep_node.cache_on_disk(tcx) {
838                             Some(dep_node)
839                         } else {
840                             None
841                         }
842                     }
843                     None |
844                     Some(DepNodeColor::Red) => {
845                         // We can skip red nodes because a node can only be marked
846                         // as red if the query result was recomputed and thus is
847                         // already in memory.
848                         None
849                     }
850                 }
851             }).collect()
852         };
853
854         for dep_node in green_nodes {
855             dep_node.load_from_on_disk_cache(tcx);
856         }
857     }
858
859     pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) {
860         debug!("mark_loaded_from_cache({:?}, {})",
861                self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index],
862                state);
863
864         self.data
865             .as_ref()
866             .unwrap()
867             .loaded_from_cache
868             .borrow_mut()
869             .insert(dep_node_index, state);
870     }
871
872     pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option<bool> {
873         let data = self.data.as_ref().unwrap();
874         let dep_node_index = data.current.borrow().node_to_node_index[dep_node];
875         data.loaded_from_cache.borrow().get(&dep_node_index).cloned()
876     }
877 }
878
879 /// A "work product" is an intermediate result that we save into the
880 /// incremental directory for later re-use. The primary example are
881 /// the object files that we save for each partition at code
882 /// generation time.
883 ///
884 /// Each work product is associated with a dep-node, representing the
885 /// process that produced the work-product. If that dep-node is found
886 /// to be dirty when we load up, then we will delete the work-product
887 /// at load time. If the work-product is found to be clean, then we
888 /// will keep a record in the `previous_work_products` list.
889 ///
890 /// In addition, work products have an associated hash. This hash is
891 /// an extra hash that can be used to decide if the work-product from
892 /// a previous compilation can be re-used (in addition to the dirty
893 /// edges check).
894 ///
895 /// As the primary example, consider the object files we generate for
896 /// each partition. In the first run, we create partitions based on
897 /// the symbols that need to be compiled. For each partition P, we
898 /// hash the symbols in P and create a `WorkProduct` record associated
899 /// with `DepNode::TransPartition(P)`; the hash is the set of symbols
900 /// in P.
901 ///
902 /// The next time we compile, if the `DepNode::TransPartition(P)` is
903 /// judged to be clean (which means none of the things we read to
904 /// generate the partition were found to be dirty), it will be loaded
905 /// into previous work products. We will then regenerate the set of
906 /// symbols in the partition P and hash them (note that new symbols
907 /// may be added -- for example, new monomorphizations -- even if
908 /// nothing in P changed!). We will compare that hash against the
909 /// previous hash. If it matches up, we can reuse the object file.
910 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
911 pub struct WorkProduct {
912     pub cgu_name: String,
913     /// Saved files associated with this CGU
914     pub saved_files: Vec<(WorkProductFileKind, String)>,
915 }
916
917 #[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
918 pub enum WorkProductFileKind {
919     Object,
920     Bytecode,
921     BytecodeCompressed,
922 }
923
924 pub(super) struct CurrentDepGraph {
925     nodes: IndexVec<DepNodeIndex, DepNode>,
926     edges: IndexVec<DepNodeIndex, Vec<DepNodeIndex>>,
927     node_to_node_index: FxHashMap<DepNode, DepNodeIndex>,
928     forbidden_edge: Option<EdgeFilter>,
929
930     // Anonymous DepNodes are nodes the ID of which we compute from the list of
931     // their edges. This has the beneficial side-effect that multiple anonymous
932     // nodes can be coalesced into one without changing the semantics of the
933     // dependency graph. However, the merging of nodes can lead to a subtle
934     // problem during red-green marking: The color of an anonymous node from
935     // the current session might "shadow" the color of the node with the same
936     // ID from the previous session. In order to side-step this problem, we make
937     // sure that anon-node IDs allocated in different sessions don't overlap.
938     // This is implemented by mixing a session-key into the ID fingerprint of
939     // each anon node. The session-key is just a random number generated when
940     // the DepGraph is created.
941     anon_id_seed: Fingerprint,
942
943     total_read_count: u64,
944     total_duplicate_read_count: u64,
945 }
946
947 impl CurrentDepGraph {
948     fn new() -> CurrentDepGraph {
949         use std::time::{SystemTime, UNIX_EPOCH};
950
951         let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
952         let nanos = duration.as_secs() * 1_000_000_000 +
953                     duration.subsec_nanos() as u64;
954         let mut stable_hasher = StableHasher::new();
955         nanos.hash(&mut stable_hasher);
956
957         let forbidden_edge = if cfg!(debug_assertions) {
958             match env::var("RUST_FORBID_DEP_GRAPH_EDGE") {
959                 Ok(s) => {
960                     match EdgeFilter::new(&s) {
961                         Ok(f) => Some(f),
962                         Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err),
963                     }
964                 }
965                 Err(_) => None,
966             }
967         } else {
968             None
969         };
970
971         CurrentDepGraph {
972             nodes: IndexVec::new(),
973             edges: IndexVec::new(),
974             node_to_node_index: FxHashMap(),
975             anon_id_seed: stable_hasher.finish(),
976             forbidden_edge,
977             total_read_count: 0,
978             total_duplicate_read_count: 0,
979         }
980     }
981
982     fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex {
983         if let OpenTask::Regular(task) = task {
984             let RegularOpenTask {
985                 node,
986                 read_set: _,
987                 reads
988             } = task.into_inner();
989             assert_eq!(node, key);
990
991             // If this is an input node, we expect that it either has no
992             // dependencies, or that it just depends on DepKind::CrateMetadata
993             // or DepKind::Krate. This happens for some "thin wrapper queries"
994             // like `crate_disambiguator` which sometimes have zero deps (for
995             // when called for LOCAL_CRATE) or they depend on a CrateMetadata
996             // node.
997             if cfg!(debug_assertions) {
998                 if node.kind.is_input() && reads.len() > 0 &&
999                    // FIXME(mw): Special case for DefSpan until Spans are handled
1000                    //            better in general.
1001                    node.kind != DepKind::DefSpan &&
1002                     reads.iter().any(|&i| {
1003                         !(self.nodes[i].kind == DepKind::CrateMetadata ||
1004                           self.nodes[i].kind == DepKind::Krate)
1005                     })
1006                 {
1007                     bug!("Input node {:?} with unexpected reads: {:?}",
1008                         node,
1009                         reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>())
1010                 }
1011             }
1012
1013             self.alloc_node(node, reads)
1014         } else {
1015             bug!("complete_task() - Expected regular task to be popped")
1016         }
1017     }
1018
1019     fn pop_anon_task(&mut self, kind: DepKind, task: OpenTask) -> DepNodeIndex {
1020         if let OpenTask::Anon(task) = task {
1021             let AnonOpenTask {
1022                 read_set: _,
1023                 reads
1024             } = task.into_inner();
1025             debug_assert!(!kind.is_input());
1026
1027             let mut fingerprint = self.anon_id_seed;
1028             let mut hasher = StableHasher::new();
1029
1030             for &read in reads.iter() {
1031                 let read_dep_node = self.nodes[read];
1032
1033                 ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);
1034
1035                 // Fingerprint::combine() is faster than sending Fingerprint
1036                 // through the StableHasher (at least as long as StableHasher
1037                 // is so slow).
1038                 fingerprint = fingerprint.combine(read_dep_node.hash);
1039             }
1040
1041             fingerprint = fingerprint.combine(hasher.finish());
1042
1043             let target_dep_node = DepNode {
1044                 kind,
1045                 hash: fingerprint,
1046             };
1047
1048             if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
1049                 index
1050             } else {
1051                 self.alloc_node(target_dep_node, reads)
1052             }
1053         } else {
1054             bug!("pop_anon_task() - Expected anonymous task to be popped")
1055         }
1056     }
1057
1058     fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex {
1059         if let OpenTask::EvalAlways {
1060             node,
1061         } = task {
1062             debug_assert_eq!(node, key);
1063             let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)];
1064             self.alloc_node(node, vec![krate_idx])
1065         } else {
1066             bug!("complete_eval_always_task() - Expected eval always task to be popped");
1067         }
1068     }
1069
1070     fn read_index(&mut self, source: DepNodeIndex) {
1071         ty::tls::with_context_opt(|icx| {
1072             let icx = if let Some(icx) = icx { icx } else { return };
1073             match *icx.task {
1074                 OpenTask::Regular(ref task) => {
1075                     let mut task = task.lock();
1076                     self.total_read_count += 1;
1077                     if task.read_set.insert(source) {
1078                         task.reads.push(source);
1079
1080                         if cfg!(debug_assertions) {
1081                             if let Some(ref forbidden_edge) = self.forbidden_edge {
1082                                 let target = &task.node;
1083                                 let source = self.nodes[source];
1084                                 if forbidden_edge.test(&source, &target) {
1085                                     bug!("forbidden edge {:?} -> {:?} created",
1086                                         source,
1087                                         target)
1088                                 }
1089                             }
1090                         }
1091                     } else {
1092                         self.total_duplicate_read_count += 1;
1093                     }
1094                 }
1095                 OpenTask::Anon(ref task) => {
1096                     let mut task = task.lock();
1097                     if task.read_set.insert(source) {
1098                         task.reads.push(source);
1099                     }
1100                 }
1101                 OpenTask::Ignore | OpenTask::EvalAlways { .. } => {
1102                     // ignore
1103                 }
1104             }
1105         })
1106     }
1107
1108     fn alloc_node(&mut self,
1109                   dep_node: DepNode,
1110                   edges: Vec<DepNodeIndex>)
1111                   -> DepNodeIndex {
1112         debug_assert_eq!(self.edges.len(), self.nodes.len());
1113         debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
1114         debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
1115         let dep_node_index = DepNodeIndex::new(self.nodes.len());
1116         self.nodes.push(dep_node);
1117         self.node_to_node_index.insert(dep_node, dep_node_index);
1118         self.edges.push(edges);
1119         dep_node_index
1120     }
1121 }
1122
1123 pub struct RegularOpenTask {
1124     node: DepNode,
1125     reads: Vec<DepNodeIndex>,
1126     read_set: FxHashSet<DepNodeIndex>,
1127 }
1128
1129 pub struct AnonOpenTask {
1130     reads: Vec<DepNodeIndex>,
1131     read_set: FxHashSet<DepNodeIndex>,
1132 }
1133
1134 pub enum OpenTask {
1135     Regular(Lock<RegularOpenTask>),
1136     Anon(Lock<AnonOpenTask>),
1137     Ignore,
1138     EvalAlways {
1139         node: DepNode,
1140     },
1141 }
1142
1143 // A data structure that stores Option<DepNodeColor> values as a contiguous
1144 // array, using one u32 per entry.
1145 struct DepNodeColorMap {
1146     values: IndexVec<SerializedDepNodeIndex, u32>,
1147 }
1148
1149 const COMPRESSED_NONE: u32 = 0;
1150 const COMPRESSED_RED: u32 = 1;
1151 const COMPRESSED_FIRST_GREEN: u32 = 2;
1152
1153 impl DepNodeColorMap {
1154     fn new(size: usize) -> DepNodeColorMap {
1155         DepNodeColorMap {
1156             values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
1157         }
1158     }
1159
1160     fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
1161         match self.values[index] {
1162             COMPRESSED_NONE => None,
1163             COMPRESSED_RED => Some(DepNodeColor::Red),
1164             value => Some(DepNodeColor::Green(DepNodeIndex(value - COMPRESSED_FIRST_GREEN)))
1165         }
1166     }
1167
1168     fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
1169         self.values[index] = match color {
1170             DepNodeColor::Red => COMPRESSED_RED,
1171             DepNodeColor::Green(index) => index.0 + COMPRESSED_FIRST_GREEN,
1172         }
1173     }
1174 }