graph.rs 44.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use errors::DiagnosticBuilder;
12
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13 14
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
15
use smallvec::SmallVec;
16
use rustc_data_structures::sync::{Lrc, Lock};
17
use std::env;
18
use std::hash::Hash;
J
John Kåre Alsaker 已提交
19
use ty::{self, TyCtxt};
20
use util::common::{ProfileQueriesMsg, profq_msg};
21

22
use ich::{StableHashingContext, StableHashingContextProvider, Fingerprint};
23

24
use super::debug::EdgeFilter;
25
use super::dep_node::{DepNode, DepKind, WorkProductId};
26
use super::query::DepGraphQuery;
N
Niko Matsakis 已提交
27
use super::safe::DepGraphSafe;
28 29
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
use super::prev::PreviousDepGraph;
30 31 32

#[derive(Clone)]
pub struct DepGraph {
33
    data: Option<Lrc<DepGraphData>>,
34

35 36 37 38
    // A vector mapping depnodes from the current graph to their associated
    // result value fingerprints. Do not rely on the length of this vector
    // being the same as the number of nodes in the graph. The vector can
    // contain an arbitrary number of zero-entries at the end.
J
John Kåre Alsaker 已提交
39
    fingerprints: Lrc<Lock<IndexVec<DepNodeIndex, Fingerprint>>>
40 41
}

42
newtype_index!(DepNodeIndex);
43 44

impl DepNodeIndex {
45
    const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX);
46 47
}

48 49 50
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum DepNodeColor {
    Red,
51
    Green(DepNodeIndex)
52 53
}

54 55 56 57 58 59 60 61 62
impl DepNodeColor {
    pub fn is_green(self) -> bool {
        match self {
            DepNodeColor::Red => false,
            DepNodeColor::Green(_) => true,
        }
    }
}

63
struct DepGraphData {
64 65 66 67
    /// The new encoding of the dependency graph, optimized for red/green
    /// tracking. The `current` field is the dependency graph of only the
    /// current compilation session: We don't merge the previous dep-graph into
    /// current one anymore.
J
John Kåre Alsaker 已提交
68
    current: Lock<CurrentDepGraph>,
69

70 71 72 73
    /// The dep-graph from the previous compilation session. It contains all
    /// nodes and edges as well as all fingerprints of nodes that have them.
    previous: PreviousDepGraph,

J
John Kåre Alsaker 已提交
74
    colors: Lock<DepNodeColorMap>,
75

N
Niko Matsakis 已提交
76
    /// When we load, there may be `.o` files, cached mir, or other such
77 78 79
    /// things available to us. If we find that they are not dirty, we
    /// load the path to the file storing those work-products here into
    /// this map. We can later look for and extract that data.
80
    previous_work_products: FxHashMap<WorkProductId, WorkProduct>,
81

J
John Kåre Alsaker 已提交
82
    dep_node_debug: Lock<FxHashMap<DepNode, String>>,
83 84

    // Used for testing, only populated when -Zquery-dep-graph is specified.
J
John Kåre Alsaker 已提交
85
    loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>,
86 87 88
}

impl DepGraph {
89

90 91
    pub fn new(prev_graph: PreviousDepGraph,
               prev_work_products: FxHashMap<WorkProductId, WorkProduct>) -> DepGraph {
92 93 94
        // Pre-allocate the fingerprints array. We over-allocate a little so
        // that we hopefully don't have to re-allocate during this compilation
        // session.
95 96
        let prev_graph_node_count = prev_graph.node_count();

97
        let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
98
                                                 (prev_graph_node_count * 115) / 100);
99
        DepGraph {
100
            data: Some(Lrc::new(DepGraphData {
101
                previous_work_products: prev_work_products,
J
John Kåre Alsaker 已提交
102 103
                dep_node_debug: Lock::new(FxHashMap()),
                current: Lock::new(CurrentDepGraph::new()),
104
                previous: prev_graph,
J
John Kåre Alsaker 已提交
105 106
                colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
                loaded_from_cache: Lock::new(FxHashMap()),
107
            })),
J
John Kåre Alsaker 已提交
108
            fingerprints: Lrc::new(Lock::new(fingerprints)),
109 110 111 112 113 114
        }
    }

    pub fn new_disabled() -> DepGraph {
        DepGraph {
            data: None,
J
John Kåre Alsaker 已提交
115
            fingerprints: Lrc::new(Lock::new(IndexVec::new())),
116 117 118
        }
    }

119 120 121
    /// True if we are actually building the full dep-graph.
    #[inline]
    pub fn is_fully_enabled(&self) -> bool {
122
        self.data.is_some()
123 124
    }

125
    pub fn query(&self) -> DepGraphQuery {
126 127 128 129 130
        let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
        let nodes: Vec<_> = current_dep_graph.nodes.iter().cloned().collect();
        let mut edges = Vec::new();
        for (index, edge_targets) in current_dep_graph.edges.iter_enumerated() {
            let from = current_dep_graph.nodes[index];
131
            for &edge_target in edge_targets.iter() {
132 133 134 135 136 137
                let to = current_dep_graph.nodes[edge_target];
                edges.push((from, to));
            }
        }

        DepGraphQuery::new(&nodes[..], &edges[..])
138 139
    }

140 141
    pub fn assert_ignored(&self)
    {
J
John Kåre Alsaker 已提交
142 143 144
        if let Some(..) = self.data {
            ty::tls::with_context_opt(|icx| {
                let icx = if let Some(icx) = icx { icx } else { return };
J
John Kåre Alsaker 已提交
145
                match *icx.task {
J
John Kåre Alsaker 已提交
146 147 148 149
                    OpenTask::Ignore => {
                        // ignored
                    }
                    _ => panic!("expected an ignore context")
150
                }
J
John Kåre Alsaker 已提交
151
            })
152
        }
153 154 155 156 157
    }

    pub fn with_ignore<OP,R>(&self, op: OP) -> R
        where OP: FnOnce() -> R
    {
J
John Kåre Alsaker 已提交
158 159
        ty::tls::with_context(|icx| {
            let icx = ty::tls::ImplicitCtxt {
J
John Kåre Alsaker 已提交
160
                task: &OpenTask::Ignore,
J
John Kåre Alsaker 已提交
161 162 163 164 165 166 167
                ..icx.clone()
            };

            ty::tls::enter_context(&icx, |_| {
                op()
            })
        })
168 169
    }

170 171 172 173 174 175
    /// Starts a new dep-graph task. Dep-graph tasks are specified
    /// using a free function (`task`) and **not** a closure -- this
    /// is intentional because we want to exercise tight control over
    /// what state they have access to. In particular, we want to
    /// prevent implicit 'leaks' of tracked state into the task (which
    /// could then be read without generating correct edges in the
M
Mark Mansi 已提交
176
    /// dep-graph -- see the [rustc guide] for more details on
M
Malo Jaffré 已提交
177
    /// the dep-graph). To this end, the task function gets exactly two
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
    /// pieces of state: the context `cx` and an argument `arg`. Both
    /// of these bits of state must be of some type that implements
    /// `DepGraphSafe` and hence does not leak.
    ///
    /// The choice of two arguments is not fundamental. One argument
    /// would work just as well, since multiple values can be
    /// collected using tuples. However, using two arguments works out
    /// to be quite convenient, since it is common to need a context
    /// (`cx`) and some argument (e.g., a `DefId` identifying what
    /// item to process).
    ///
    /// For cases where you need some other number of arguments:
    ///
    /// - If you only need one argument, just use `()` for the `arg`
    ///   parameter.
    /// - If you need 3+ arguments, use a tuple for the
    ///   `arg` parameter.
    ///
M
Mark Mansi 已提交
196
    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/incremental-compilation.html
197
    pub fn with_task<'gcx, C, A, R>(&self,
198 199 200 201 202
                                   key: DepNode,
                                   cx: C,
                                   arg: A,
                                   task: fn(C, A) -> R)
                                   -> (R, DepNodeIndex)
203 204
        where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
              R: HashStable<StableHashingContext<'gcx>>,
205
    {
J
John Kåre Alsaker 已提交
206
        self.with_task_impl(key, cx, arg, false, task,
J
John Kåre Alsaker 已提交
207
            |key| OpenTask::Regular(Lock::new(RegularOpenTask {
J
John Kåre Alsaker 已提交
208
                node: key,
209
                reads: SmallVec::new(),
J
John Kåre Alsaker 已提交
210
                read_set: FxHashSet(),
J
John Kåre Alsaker 已提交
211
            })),
J
John Kåre Alsaker 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
            |data, key, task| data.borrow_mut().complete_task(key, task))
    }

    /// Creates a new dep-graph input with value `input`
    pub fn input_task<'gcx, C, R>(&self,
                                   key: DepNode,
                                   cx: C,
                                   input: R)
                                   -> (R, DepNodeIndex)
        where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
              R: HashStable<StableHashingContext<'gcx>>,
    {
        fn identity_fn<C, A>(_: C, arg: A) -> A {
            arg
        }

        self.with_task_impl(key, cx, input, true, identity_fn,
            |_| OpenTask::Ignore,
230
            |data, key, _| data.borrow_mut().alloc_node(key, SmallVec::new()))
231 232
    }

J
John Kåre Alsaker 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    fn with_task_impl<'gcx, C, A, R>(
        &self,
        key: DepNode,
        cx: C,
        arg: A,
        no_tcx: bool,
        task: fn(C, A) -> R,
        create_task: fn(DepNode) -> OpenTask,
        finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
                                          DepNode,
                                          OpenTask) -> DepNodeIndex
    ) -> (R, DepNodeIndex)
    where
        C: DepGraphSafe + StableHashingContextProvider<'gcx>,
        R: HashStable<StableHashingContext<'gcx>>,
248
    {
249
        if let Some(ref data) = self.data {
J
John Kåre Alsaker 已提交
250
            let open_task = create_task(key);
251 252 253 254 255 256

            // In incremental mode, hash the result of the task. We don't
            // do anything with the hash yet, but we are computing it
            // anyway so that
            //  - we make sure that the infrastructure works and
            //  - we can get an idea of the runtime cost.
257 258 259 260 261
            let mut hcx = cx.get_stable_hashing_context();

            if cfg!(debug_assertions) {
                profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
            };
262

J
John Kåre Alsaker 已提交
263 264
            let result = if no_tcx {
                task(cx, arg)
J
John Kåre Alsaker 已提交
265 266
            } else {
                ty::tls::with_context(|icx| {
J
John Kåre Alsaker 已提交
267 268 269
                    let icx = ty::tls::ImplicitCtxt {
                        task: &open_task,
                        ..icx.clone()
J
John Kåre Alsaker 已提交
270 271
                    };

J
John Kåre Alsaker 已提交
272 273 274
                    ty::tls::enter_context(&icx, |_| {
                        task(cx, arg)
                    })
J
John Kåre Alsaker 已提交
275 276
                })
            };
277

278
            if cfg!(debug_assertions) {
279
                profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
280
            };
281

J
John Kåre Alsaker 已提交
282
            let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task);
283 284 285

            let mut stable_hasher = StableHasher::new();
            result.hash_stable(&mut hcx, &mut stable_hasher);
286

287 288
            let current_fingerprint = stable_hasher.finish();

289 290
            // Store the current fingerprint
            {
291 292 293
                let mut fingerprints = self.fingerprints.borrow_mut();

                if dep_node_index.index() >= fingerprints.len() {
294
                    fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
295 296
                }

297
                debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
298 299
                              "DepGraph::with_task() - Duplicate fingerprint \
                               insertion for {:?}", key);
300
                fingerprints[dep_node_index] = current_fingerprint;
301
            }
302

303
            // Determine the color of the new DepNode.
304 305
            if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
                let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
306

307
                let color = if current_fingerprint == prev_fingerprint {
308 309 310 311
                    DepNodeColor::Green(dep_node_index)
                } else {
                    DepNodeColor::Red
                };
312

313 314
                let mut colors = data.colors.borrow_mut();
                debug_assert!(colors.get(prev_index).is_none(),
315 316
                              "DepGraph::with_task() - Duplicate DepNodeColor \
                               insertion for {:?}", key);
317 318

                colors.insert(prev_index, color);
319
            }
320

321
            (result, dep_node_index)
322
        } else {
323
            if key.kind.fingerprint_needed_for_crate_hash() {
324
                let mut hcx = cx.get_stable_hashing_context();
325 326 327
                let result = task(cx, arg);
                let mut stable_hasher = StableHasher::new();
                result.hash_stable(&mut hcx, &mut stable_hasher);
328 329 330 331 332
                let fingerprint = stable_hasher.finish();

                let mut fingerprints = self.fingerprints.borrow_mut();
                let dep_node_index = DepNodeIndex::new(fingerprints.len());
                fingerprints.push(fingerprint);
333

334 335 336
                debug_assert!(fingerprints[dep_node_index] == fingerprint,
                              "DepGraph::with_task() - Assigned fingerprint to \
                               unexpected index for {:?}", key);
337

338
                (result, dep_node_index)
339 340 341
            } else {
                (task(cx, arg), DepNodeIndex::INVALID)
            }
342
        }
343 344
    }

345 346
    /// Execute something within an "anonymous" task, that is, a task the
    /// DepNode of which is determined by the list of inputs it read from.
347
    pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
348 349 350
        where OP: FnOnce() -> R
    {
        if let Some(ref data) = self.data {
J
John Kåre Alsaker 已提交
351
            let (result, open_task) = ty::tls::with_context(|icx| {
J
John Kåre Alsaker 已提交
352
                let task = OpenTask::Anon(Lock::new(AnonOpenTask {
353
                    reads: SmallVec::new(),
J
John Kåre Alsaker 已提交
354
                    read_set: FxHashSet(),
J
John Kåre Alsaker 已提交
355
                }));
J
John Kåre Alsaker 已提交
356 357 358 359 360 361 362 363 364 365 366 367

                let r = {
                    let icx = ty::tls::ImplicitCtxt {
                        task: &task,
                        ..icx.clone()
                    };

                    ty::tls::enter_context(&icx, |_| {
                        op()
                    })
                };

J
John Kåre Alsaker 已提交
368
                (r, task)
J
John Kåre Alsaker 已提交
369
            });
370 371
            let dep_node_index = data.current
                                     .borrow_mut()
J
John Kåre Alsaker 已提交
372
                                     .pop_anon_task(dep_kind, open_task);
373
            (result, dep_node_index)
374
        } else {
375
            (op(), DepNodeIndex::INVALID)
376 377 378
        }
    }

379 380
    /// Execute something within an "eval-always" task which is a task
    // that runs whenever anything changes.
381
    pub fn with_eval_always_task<'gcx, C, A, R>(&self,
382 383 384 385 386
                                   key: DepNode,
                                   cx: C,
                                   arg: A,
                                   task: fn(C, A) -> R)
                                   -> (R, DepNodeIndex)
387 388
        where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
              R: HashStable<StableHashingContext<'gcx>>,
389
    {
J
John Kåre Alsaker 已提交
390 391 392
        self.with_task_impl(key, cx, arg, false, task,
            |key| OpenTask::EvalAlways { node: key },
            |data, key, task| data.borrow_mut().complete_eval_always_task(key, task))
393 394
    }

395
    #[inline]
396
    pub fn read(&self, v: DepNode) {
397
        if let Some(ref data) = self.data {
398
            let mut current = data.current.borrow_mut();
399 400
            if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
                current.read_index(dep_node_index);
401 402 403
            } else {
                bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
            }
404
        }
405 406
    }

407
    #[inline]
408
    pub fn read_index(&self, dep_node_index: DepNodeIndex) {
409
        if let Some(ref data) = self.data {
410
            data.current.borrow_mut().read_index(dep_node_index);
411 412 413
        }
    }

414
    #[inline]
415 416 417 418 419 420 421 422 423 424 425 426
    pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex {
        self.data
            .as_ref()
            .unwrap()
            .current
            .borrow_mut()
            .node_to_node_index
            .get(dep_node)
            .cloned()
            .unwrap()
    }

427 428 429 430 431 432 433 434 435
    #[inline]
    pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
        if let Some(ref data) = self.data {
            data.current.borrow_mut().node_to_node_index.contains_key(dep_node)
        } else {
            false
        }
    }

436 437 438
    #[inline]
    pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
        match self.fingerprints.borrow().get(dep_node_index) {
439 440
            Some(&fingerprint) => fingerprint,
            None => {
441 442 443 444 445 446
                if let Some(ref data) = self.data {
                    let dep_node = data.current.borrow().nodes[dep_node_index];
                    bug!("Could not find current fingerprint for {:?}", dep_node)
                } else {
                    bug!("Could not find current fingerprint for {:?}", dep_node_index)
                }
447 448
            }
        }
449 450
    }

451
    pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
452
        self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
453 454
    }

455 456 457 458 459
    #[inline]
    pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
        self.data.as_ref().unwrap().previous.node_to_index(dep_node)
    }

460 461
    /// Check whether a previous work product exists for `v` and, if
    /// so, return the path that leads to it. Used to skip doing work.
462
    pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
463 464 465
        self.data
            .as_ref()
            .and_then(|data| {
466
                data.previous_work_products.get(v).cloned()
467
            })
468 469
    }

470 471
    /// Access the map of work-products created during the cached run. Only
    /// used during saving of the dep-graph.
472 473
    pub fn previous_work_products(&self) -> &FxHashMap<WorkProductId, WorkProduct> {
        &self.data.as_ref().unwrap().previous_work_products
474
    }
475 476

    #[inline(always)]
477 478 479
    pub fn register_dep_node_debug_str<F>(&self,
                                          dep_node: DepNode,
                                          debug_str_gen: F)
480 481
        where F: FnOnce() -> String
    {
482
        let dep_node_debug = &self.data.as_ref().unwrap().dep_node_debug;
483

484 485 486 487 488
        if dep_node_debug.borrow().contains_key(&dep_node) {
            return
        }
        let debug_str = debug_str_gen();
        dep_node_debug.borrow_mut().insert(dep_node, debug_str);
489 490 491
    }

    pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
S
Shotaro Yamada 已提交
492 493 494 495 496 497
        self.data
            .as_ref()?
            .dep_node_debug
            .borrow()
            .get(&dep_node)
            .cloned()
498
    }
499

500 501 502 503 504 505
    pub fn edge_deduplication_data(&self) -> (u64, u64) {
        let current_dep_graph = self.data.as_ref().unwrap().current.borrow();

        (current_dep_graph.total_read_count, current_dep_graph.total_duplicate_read_count)
    }

506 507 508
    pub fn serialize(&self) -> SerializedDepGraph {
        let current_dep_graph = self.data.as_ref().unwrap().current.borrow();

509
        let fingerprints = self.fingerprints.borrow().clone().convert_index_type();
510
        let nodes = current_dep_graph.nodes.clone().convert_index_type();
511 512 513 514 515 516 517 518 519 520 521

        let total_edge_count: usize = current_dep_graph.edges.iter()
                                                             .map(|v| v.len())
                                                             .sum();

        let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
        let mut edge_list_data = Vec::with_capacity(total_edge_count);

        for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() {
            let start = edge_list_data.len() as u32;
            // This should really just be a memcpy :/
522
            edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index())));
523 524 525 526 527 528 529 530 531 532 533
            let end = edge_list_data.len() as u32;

            debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
            edge_list_indices.push((start, end));
        }

        debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
        debug_assert_eq!(edge_list_data.len(), total_edge_count);

        SerializedDepGraph {
            nodes,
534
            fingerprints,
535 536 537 538
            edge_list_indices,
            edge_list_data,
        }
    }
539 540

    pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
541 542 543 544 545 546 547 548 549 550 551
        if let Some(ref data) = self.data {
            if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
                return data.colors.borrow().get(prev_index)
            } else {
                // This is a node that did not exist in the previous compilation
                // session, so we consider it to be red.
                return Some(DepNodeColor::Red)
            }
        }

        None
552 553
    }

554 555 556 557
    pub fn try_mark_green<'tcx>(&self,
                                tcx: TyCtxt<'_, 'tcx, 'tcx>,
                                dep_node: &DepNode)
                                -> Option<DepNodeIndex> {
558
        debug!("try_mark_green({:?}) - BEGIN", dep_node);
559 560
        let data = self.data.as_ref().unwrap();

J
John Kåre Alsaker 已提交
561
        #[cfg(not(parallel_queries))]
562 563 564 565 566 567 568 569
        debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));

        if dep_node.kind.is_input() {
            // We should only hit try_mark_green() for inputs that do not exist
            // anymore in the current compilation session. Existing inputs are
            // eagerly marked as either red/green before any queries are
            // executed.
            debug_assert!(dep_node.extract_def_id(tcx).is_none());
570
            debug!("try_mark_green({:?}) - END - DepNode is deleted input", dep_node);
571 572 573 574 575 576 577 578 579 580 581 582 583 584
            return None;
        }

        let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
            Some(prev) => {
                // This DepNode and the corresponding query invocation existed
                // in the previous compilation session too, so we can try to
                // mark it as green by recursively marking all of its
                // dependencies green.
                prev
            }
            None => {
                // This DepNode did not exist in the previous compilation session,
                // so we cannot mark it as green.
585 586
                debug!("try_mark_green({:?}) - END - DepNode does not exist in \
                        current compilation session anymore", dep_node);
587 588 589 590
                return None
            }
        };

591 592
        debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());

593
        let mut current_deps = SmallVec::new();
594

595
        for &dep_dep_node_index in prev_deps {
596
            let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
597

598 599 600 601 602
            match dep_dep_node_color {
                Some(DepNodeColor::Green(node_index)) => {
                    // This dependency has been marked as green before, we are
                    // still fine and can continue with checking the other
                    // dependencies.
603
                    debug!("try_mark_green({:?}) --- found dependency {:?} to \
604 605 606
                            be immediately green",
                            dep_node,
                            data.previous.index_to_node(dep_dep_node_index));
607 608 609 610 611 612 613
                    current_deps.push(node_index);
                }
                Some(DepNodeColor::Red) => {
                    // We found a dependency the value of which has changed
                    // compared to the previous compilation session. We cannot
                    // mark the DepNode as green and also don't need to bother
                    // with checking any of the other dependencies.
614
                    debug!("try_mark_green({:?}) - END - dependency {:?} was \
615 616 617
                            immediately red",
                            dep_node,
                            data.previous.index_to_node(dep_dep_node_index));
618 619 620
                    return None
                }
                None => {
621 622
                    let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index);

623 624 625 626 627 628 629 630 631 632 633 634 635
                    // We don't know the state of this dependency. If it isn't
                    // an input node, let's try to mark it green recursively.
                    if !dep_dep_node.kind.is_input() {
                         debug!("try_mark_green({:?}) --- state of dependency {:?} \
                                 is unknown, trying to mark it green", dep_node,
                                 dep_dep_node);

                        if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
                            debug!("try_mark_green({:?}) --- managed to MARK \
                                    dependency {:?} as green", dep_node, dep_dep_node);
                            current_deps.push(node_index);
                            continue;
                        }
636
                    } else {
637 638 639 640
                        match dep_dep_node.kind {
                            DepKind::Hir |
                            DepKind::HirBody |
                            DepKind::CrateMetadata => {
641 642 643 644 645 646 647 648 649 650 651
                                if dep_node.extract_def_id(tcx).is_none() {
                                    // If the node does not exist anymore, we
                                    // just fail to mark green.
                                    return None
                                } else {
                                    // If the node does exist, it should have
                                    // been pre-allocated.
                                    bug!("DepNode {:?} should have been \
                                          pre-allocated but wasn't.",
                                          dep_dep_node)
                                }
652 653 654 655 656 657
                            }
                            _ => {
                                // For other kinds of inputs it's OK to be
                                // forced.
                            }
                        }
658 659
                    }

660 661 662
                    // We failed to mark it green, so we try to force the query.
                    debug!("try_mark_green({:?}) --- trying to force \
                            dependency {:?}", dep_node, dep_dep_node);
663
                    if ::ty::query::force_from_dep_node(tcx, dep_dep_node) {
664 665
                        let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
                        match dep_dep_node_color {
                            Some(DepNodeColor::Green(node_index)) => {
                                debug!("try_mark_green({:?}) --- managed to \
                                        FORCE dependency {:?} to green",
                                        dep_node, dep_dep_node);
                                current_deps.push(node_index);
                            }
                            Some(DepNodeColor::Red) => {
                                debug!("try_mark_green({:?}) - END - \
                                        dependency {:?} was red after forcing",
                                       dep_node,
                                       dep_dep_node);
                                return None
                            }
                            None => {
681 682 683 684 685 686 687 688 689
                                if !tcx.sess.has_errors() {
                                    bug!("try_mark_green() - Forcing the DepNode \
                                          should have set its color")
                                } else {
                                    // If the query we just forced has resulted
                                    // in some kind of compilation error, we
                                    // don't expect that the corresponding
                                    // dep-node color has been updated.
                                }
690 691
                            }
                        }
692 693 694 695 696
                    } else {
                        // The DepNode could not be forced.
                        debug!("try_mark_green({:?}) - END - dependency {:?} \
                                could not be forced", dep_node, dep_dep_node);
                        return None
697 698 699 700 701 702 703
                    }
                }
            }
        }

        // If we got here without hitting a `return` that means that all
        // dependencies of this DepNode could be marked as green. Therefore we
J
John Kåre Alsaker 已提交
704
        // can also mark this DepNode as green.
705

J
John Kåre Alsaker 已提交
706 707 708 709 710 711 712 713 714 715 716 717 718 719
        // There may be multiple threads trying to mark the same dep node green concurrently

        let (dep_node_index, did_allocation) = {
            let mut current = data.current.borrow_mut();

            if let Some(&dep_node_index) = current.node_to_node_index.get(&dep_node) {
                // Someone else allocated it before us
                (dep_node_index, false)
            } else {
                // We allocating an entry for the node in the current dependency graph and
                // adding all the appropriate edges imported from the previous graph
                (current.alloc_node(*dep_node, current_deps), true)
            }
        };
720 721 722

        // ... copying the fingerprint from the previous graph too, so we don't
        // have to recompute it ...
723 724 725 726 727
        {
            let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
            let mut fingerprints = self.fingerprints.borrow_mut();

            if dep_node_index.index() >= fingerprints.len() {
728
                fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
729 730
            }

J
John Kåre Alsaker 已提交
731 732
            // Multiple threads can all write the same fingerprint here
            #[cfg(not(parallel_queries))]
733
            debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
734 735 736 737 738
                "DepGraph::try_mark_green() - Duplicate fingerprint \
                insertion for {:?}", dep_node);

            fingerprints[dep_node_index] = fingerprint;
        }
739

740
        // ... emitting any stored diagnostic ...
J
John Kåre Alsaker 已提交
741 742 743 744 745 746 747 748
        if did_allocation {
            // Only the thread which did the allocation emits the error messages

            // FIXME: Ensure that these are printed before returning for all threads.
            // Currently threads where did_allocation = false can continue on
            // and emit other diagnostics before these diagnostics are emitted.
            // Such diagnostics should be emitted after these.
            // See https://github.com/rust-lang/rust/issues/48685
749
            let diagnostics = tcx.queries.on_disk_cache
750
                                 .load_diagnostics(tcx, prev_dep_node_index);
751 752 753 754 755

            if diagnostics.len() > 0 {
                let handle = tcx.sess.diagnostic();

                // Promote the previous diagnostics to the current session.
756
                tcx.queries.on_disk_cache
757 758 759 760 761 762 763 764
                   .store_diagnostics(dep_node_index, diagnostics.clone());

                for diagnostic in diagnostics {
                    DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
                }
            }
        }

765
        // ... and finally storing a "Green" entry in the color map.
766
        let mut colors = data.colors.borrow_mut();
J
John Kåre Alsaker 已提交
767 768
        // Multiple threads can all write the same color here
        #[cfg(not(parallel_queries))]
769
        debug_assert!(colors.get(prev_dep_node_index).is_none(),
770 771
                      "DepGraph::try_mark_green() - Duplicate DepNodeColor \
                      insertion for {:?}", dep_node);
772

773 774
        colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));

775
        debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
776
        Some(dep_node_index)
777 778
    }

779 780 781 782
    // Returns true if the given node has been marked as green during the
    // current compilation session. Used in various assertions
    pub fn is_green(&self, dep_node: &DepNode) -> bool {
        self.node_color(dep_node).map(|c| c.is_green()).unwrap_or(false)
783
    }
784

785 786 787 788 789 790 791 792 793 794 795
    // This method loads all on-disk cacheable query results into memory, so
    // they can be written out to the new cache file again. Most query results
    // will already be in memory but in the case where we marked something as
    // green but then did not need the value, that value will never have been
    // loaded from disk.
    //
    // This method will only load queries that will end up in the disk cache.
    // Other queries will not be executed.
    pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
        let green_nodes: Vec<DepNode> = {
            let data = self.data.as_ref().unwrap();
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
            let colors = data.colors.borrow();
            colors.values.indices().filter_map(|prev_index| {
                match colors.get(prev_index) {
                    Some(DepNodeColor::Green(_)) => {
                        let dep_node = data.previous.index_to_node(prev_index);
                        if dep_node.cache_on_disk(tcx) {
                            Some(dep_node)
                        } else {
                            None
                        }
                    }
                    None |
                    Some(DepNodeColor::Red) => {
                        // We can skip red nodes because a node can only be marked
                        // as red if the query result was recomputed and thus is
                        // already in memory.
812 813 814 815 816 817 818 819 820 821 822
                        None
                    }
                }
            }).collect()
        };

        for dep_node in green_nodes {
            dep_node.load_from_on_disk_cache(tcx);
        }
    }

823
    pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) {
824
        debug!("mark_loaded_from_cache({:?}, {})",
825
               self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index],
826 827 828 829 830 831 832
               state);

        self.data
            .as_ref()
            .unwrap()
            .loaded_from_cache
            .borrow_mut()
833
            .insert(dep_node_index, state);
834 835 836 837 838 839 840
    }

    pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option<bool> {
        let data = self.data.as_ref().unwrap();
        let dep_node_index = data.current.borrow().node_to_node_index[dep_node];
        data.loaded_from_cache.borrow().get(&dep_node_index).cloned()
    }
841 842 843 844 845 846 847 848 849 850
}

/// A "work product" is an intermediate result that we save into the
/// incremental directory for later re-use. The primary example are
/// the object files that we save for each partition at code
/// generation time.
///
/// Each work product is associated with a dep-node, representing the
/// process that produced the work-product. If that dep-node is found
/// to be dirty when we load up, then we will delete the work-product
N
Niko Matsakis 已提交
851
/// at load time. If the work-product is found to be clean, then we
852 853 854 855 856 857 858 859 860 861 862
/// will keep a record in the `previous_work_products` list.
///
/// In addition, work products have an associated hash. This hash is
/// an extra hash that can be used to decide if the work-product from
/// a previous compilation can be re-used (in addition to the dirty
/// edges check).
///
/// As the primary example, consider the object files we generate for
/// each partition. In the first run, we create partitions based on
/// the symbols that need to be compiled. For each partition P, we
/// hash the symbols in P and create a `WorkProduct` record associated
I
Irina Popa 已提交
863
/// with `DepNode::CodegenUnit(P)`; the hash is the set of symbols
864 865
/// in P.
///
I
Irina Popa 已提交
866
/// The next time we compile, if the `DepNode::CodegenUnit(P)` is
867 868 869 870 871 872 873 874 875
/// judged to be clean (which means none of the things we read to
/// generate the partition were found to be dirty), it will be loaded
/// into previous work products. We will then regenerate the set of
/// symbols in the partition P and hash them (note that new symbols
/// may be added -- for example, new monomorphizations -- even if
/// nothing in P changed!). We will compare that hash against the
/// previous hash. If it matches up, we can reuse the object file.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct WorkProduct {
876
    pub cgu_name: String,
877
    /// Saved files associated with this CGU
878 879 880 881 882 883 884 885
    pub saved_files: Vec<(WorkProductFileKind, String)>,
}

#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
pub enum WorkProductFileKind {
    Object,
    Bytecode,
    BytecodeCompressed,
886
}
887 888

pub(super) struct CurrentDepGraph {
889
    nodes: IndexVec<DepNodeIndex, DepNode>,
890
    edges: IndexVec<DepNodeIndex, SmallVec<[DepNodeIndex; 8]>>,
891 892
    node_to_node_index: FxHashMap<DepNode, DepNodeIndex>,
    forbidden_edge: Option<EdgeFilter>,
893 894 895 896 897 898 899 900 901 902 903 904 905

    // Anonymous DepNodes are nodes the ID of which we compute from the list of
    // their edges. This has the beneficial side-effect that multiple anonymous
    // nodes can be coalesced into one without changing the semantics of the
    // dependency graph. However, the merging of nodes can lead to a subtle
    // problem during red-green marking: The color of an anonymous node from
    // the current session might "shadow" the color of the node with the same
    // ID from the previous session. In order to side-step this problem, we make
    // sure that anon-node IDs allocated in different sessions don't overlap.
    // This is implemented by mixing a session-key into the ID fingerprint of
    // each anon node. The session-key is just a random number generated when
    // the DepGraph is created.
    anon_id_seed: Fingerprint,
906 907 908

    total_read_count: u64,
    total_duplicate_read_count: u64,
909 910 911 912
}

impl CurrentDepGraph {
    fn new() -> CurrentDepGraph {
913 914 915 916 917 918 919 920
        use std::time::{SystemTime, UNIX_EPOCH};

        let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
        let nanos = duration.as_secs() * 1_000_000_000 +
                    duration.subsec_nanos() as u64;
        let mut stable_hasher = StableHasher::new();
        nanos.hash(&mut stable_hasher);

921 922 923 924 925 926 927 928 929 930 931 932 933 934
        let forbidden_edge = if cfg!(debug_assertions) {
            match env::var("RUST_FORBID_DEP_GRAPH_EDGE") {
                Ok(s) => {
                    match EdgeFilter::new(&s) {
                        Ok(f) => Some(f),
                        Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err),
                    }
                }
                Err(_) => None,
            }
        } else {
            None
        };

935 936 937 938
        CurrentDepGraph {
            nodes: IndexVec::new(),
            edges: IndexVec::new(),
            node_to_node_index: FxHashMap(),
939
            anon_id_seed: stable_hasher.finish(),
940
            forbidden_edge,
941 942
            total_read_count: 0,
            total_duplicate_read_count: 0,
943 944 945
        }
    }

J
John Kåre Alsaker 已提交
946
    fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex {
J
John Kåre Alsaker 已提交
947 948 949 950 951 952
        if let OpenTask::Regular(task) = task {
            let RegularOpenTask {
                node,
                read_set: _,
                reads
            } = task.into_inner();
953 954 955 956 957 958 959 960 961 962
            assert_eq!(node, key);

            // If this is an input node, we expect that it either has no
            // dependencies, or that it just depends on DepKind::CrateMetadata
            // or DepKind::Krate. This happens for some "thin wrapper queries"
            // like `crate_disambiguator` which sometimes have zero deps (for
            // when called for LOCAL_CRATE) or they depend on a CrateMetadata
            // node.
            if cfg!(debug_assertions) {
                if node.kind.is_input() && reads.len() > 0 &&
963 964 965
                   // FIXME(mw): Special case for DefSpan until Spans are handled
                   //            better in general.
                   node.kind != DepKind::DefSpan &&
966 967 968 969 970 971 972 973 974 975 976
                    reads.iter().any(|&i| {
                        !(self.nodes[i].kind == DepKind::CrateMetadata ||
                          self.nodes[i].kind == DepKind::Krate)
                    })
                {
                    bug!("Input node {:?} with unexpected reads: {:?}",
                        node,
                        reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>())
                }
            }

977 978
            self.alloc_node(node, reads)
        } else {
J
John Kåre Alsaker 已提交
979
            bug!("complete_task() - Expected regular task to be popped")
980 981 982
        }
    }

J
John Kåre Alsaker 已提交
983
    fn pop_anon_task(&mut self, kind: DepKind, task: OpenTask) -> DepNodeIndex {
J
John Kåre Alsaker 已提交
984 985 986 987 988
        if let OpenTask::Anon(task) = task {
            let AnonOpenTask {
                read_set: _,
                reads
            } = task.into_inner();
989 990
            debug_assert!(!kind.is_input());

991
            let mut fingerprint = self.anon_id_seed;
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
            let mut hasher = StableHasher::new();

            for &read in reads.iter() {
                let read_dep_node = self.nodes[read];

                ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);

                // Fingerprint::combine() is faster than sending Fingerprint
                // through the StableHasher (at least as long as StableHasher
                // is so slow).
                fingerprint = fingerprint.combine(read_dep_node.hash);
            }

            fingerprint = fingerprint.combine(hasher.finish());

            let target_dep_node = DepNode {
                kind,
                hash: fingerprint,
            };

            if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
1013
                index
1014
            } else {
1015
                self.alloc_node(target_dep_node, reads)
1016 1017 1018 1019 1020 1021
            }
        } else {
            bug!("pop_anon_task() - Expected anonymous task to be popped")
        }
    }

J
John Kåre Alsaker 已提交
1022
    fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex {
1023 1024
        if let OpenTask::EvalAlways {
            node,
J
John Kåre Alsaker 已提交
1025
        } = task {
1026 1027
            debug_assert_eq!(node, key);
            let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)];
1028
            self.alloc_node(node, smallvec![krate_idx])
1029
        } else {
J
John Kåre Alsaker 已提交
1030
            bug!("complete_eval_always_task() - Expected eval always task to be popped");
1031 1032 1033
        }
    }

1034
    fn read_index(&mut self, source: DepNodeIndex) {
J
John Kåre Alsaker 已提交
1035 1036
        ty::tls::with_context_opt(|icx| {
            let icx = if let Some(icx) = icx { icx } else { return };
J
John Kåre Alsaker 已提交
1037 1038 1039
            match *icx.task {
                OpenTask::Regular(ref task) => {
                    let mut task = task.lock();
J
John Kåre Alsaker 已提交
1040
                    self.total_read_count += 1;
J
John Kåre Alsaker 已提交
1041 1042
                    if task.read_set.insert(source) {
                        task.reads.push(source);
J
John Kåre Alsaker 已提交
1043 1044 1045

                        if cfg!(debug_assertions) {
                            if let Some(ref forbidden_edge) = self.forbidden_edge {
J
John Kåre Alsaker 已提交
1046
                                let target = &task.node;
J
John Kåre Alsaker 已提交
1047 1048 1049 1050 1051 1052
                                let source = self.nodes[source];
                                if forbidden_edge.test(&source, &target) {
                                    bug!("forbidden edge {:?} -> {:?} created",
                                        source,
                                        target)
                                }
1053 1054
                            }
                        }
J
John Kåre Alsaker 已提交
1055 1056
                    } else {
                        self.total_duplicate_read_count += 1;
1057
                    }
1058
                }
J
John Kåre Alsaker 已提交
1059 1060 1061 1062
                OpenTask::Anon(ref task) => {
                    let mut task = task.lock();
                    if task.read_set.insert(source) {
                        task.reads.push(source);
J
John Kåre Alsaker 已提交
1063 1064 1065 1066
                    }
                }
                OpenTask::Ignore | OpenTask::EvalAlways { .. } => {
                    // ignore
1067 1068
                }
            }
J
John Kåre Alsaker 已提交
1069
        })
1070 1071 1072 1073
    }

    fn alloc_node(&mut self,
                  dep_node: DepNode,
1074
                  edges: SmallVec<[DepNodeIndex; 8]>)
1075
                  -> DepNodeIndex {
1076 1077 1078
        debug_assert_eq!(self.edges.len(), self.nodes.len());
        debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
        debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
1079
        let dep_node_index = DepNodeIndex::new(self.nodes.len());
1080 1081 1082 1083 1084 1085 1086
        self.nodes.push(dep_node);
        self.node_to_node_index.insert(dep_node, dep_node_index);
        self.edges.push(edges);
        dep_node_index
    }
}

J
John Kåre Alsaker 已提交
1087 1088
pub struct RegularOpenTask {
    node: DepNode,
1089
    reads: SmallVec<[DepNodeIndex; 8]>,
J
John Kåre Alsaker 已提交
1090 1091 1092 1093
    read_set: FxHashSet<DepNodeIndex>,
}

pub struct AnonOpenTask {
1094
    reads: SmallVec<[DepNodeIndex; 8]>,
J
John Kåre Alsaker 已提交
1095 1096 1097
    read_set: FxHashSet<DepNodeIndex>,
}

J
John Kåre Alsaker 已提交
1098
pub enum OpenTask {
J
John Kåre Alsaker 已提交
1099 1100
    Regular(Lock<RegularOpenTask>),
    Anon(Lock<AnonOpenTask>),
1101
    Ignore,
1102 1103 1104
    EvalAlways {
        node: DepNode,
    },
1105
}
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138

// A data structure that stores Option<DepNodeColor> values as a contiguous
// array, using one u32 per entry.
struct DepNodeColorMap {
    values: IndexVec<SerializedDepNodeIndex, u32>,
}

const COMPRESSED_NONE: u32 = 0;
const COMPRESSED_RED: u32 = 1;
const COMPRESSED_FIRST_GREEN: u32 = 2;

impl DepNodeColorMap {
    fn new(size: usize) -> DepNodeColorMap {
        DepNodeColorMap {
            values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
        }
    }

    fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
        match self.values[index] {
            COMPRESSED_NONE => None,
            COMPRESSED_RED => Some(DepNodeColor::Red),
            value => Some(DepNodeColor::Green(DepNodeIndex(value - COMPRESSED_FIRST_GREEN)))
        }
    }

    fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
        self.values[index] = match color {
            DepNodeColor::Red => COMPRESSED_RED,
            DepNodeColor::Green(index) => index.0 + COMPRESSED_FIRST_GREEN,
        }
    }
}