]> git.proxmox.com Git - rustc.git/blame - src/librustc/dep_graph/dep_tracking_map.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / librustc / dep_graph / dep_tracking_map.rs
CommitLineData
9cc50fc6
SL
1// Copyright 2012-2015 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
476ff2be 11use rustc_data_structures::fx::FxHashMap;
9cc50fc6 12use std::cell::RefCell;
9cc50fc6
SL
13use std::hash::Hash;
14use std::marker::PhantomData;
15use util::common::MemoizationMap;
16
3b2f2976 17use super::{DepKind, DepNodeIndex, DepGraph};
9cc50fc6
SL
18
19/// A DepTrackingMap offers a subset of the `Map` API and ensures that
20/// we make calls to `read` and `write` as appropriate. We key the
21/// maps with a unique type for brevity.
22pub struct DepTrackingMap<M: DepTrackingMapConfig> {
23 phantom: PhantomData<M>,
24 graph: DepGraph,
3b2f2976 25 map: FxHashMap<M::Key, (M::Value, DepNodeIndex)>,
9cc50fc6
SL
26}
27
28pub trait DepTrackingMapConfig {
29 type Key: Eq + Hash + Clone;
30 type Value: Clone;
3b2f2976 31 fn to_dep_kind() -> DepKind;
9cc50fc6
SL
32}
33
34impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
35 pub fn new(graph: DepGraph) -> DepTrackingMap<M> {
36 DepTrackingMap {
37 phantom: PhantomData,
041b39d2 38 graph,
cc61c64b 39 map: FxHashMap(),
9cc50fc6
SL
40 }
41 }
9cc50fc6
SL
42}
43
44impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
45 type Key = M::Key;
46 type Value = M::Value;
47
48 /// Memoizes an entry in the dep-tracking-map. If the entry is not
49 /// already present, then `op` will be executed to compute its value.
50 /// The resulting dependency graph looks like this:
51 ///
52 /// [op] -> Map(key) -> CurrentTask
53 ///
54 /// Here, `[op]` represents whatever nodes `op` reads in the
55 /// course of execution; `Map(key)` represents the node for this
56 /// map; and `CurrentTask` represents the current task when
57 /// `memoize` is invoked.
58 ///
59 /// **Important:* when `op` is invoked, the current task will be
60 /// switched to `Map(key)`. Therefore, if `op` makes use of any
61 /// HIR nodes or shared state accessed through its closure
62 /// environment, it must explicitly register a read of that
476ff2be 63 /// state. As an example, see `type_of_item` in `collect`,
9cc50fc6
SL
64 /// which looks something like this:
65 ///
66 /// ```
476ff2be 67 /// fn type_of_item(..., item: &hir::Item) -> Ty<'tcx> {
32a655c1 68 /// let item_def_id = ccx.tcx.hir.local_def_id(it.id);
476ff2be 69 /// ccx.tcx.item_types.memoized(item_def_id, || {
9cc50fc6 70 /// ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // (*)
476ff2be 71 /// compute_type_of_item(ccx, item)
9cc50fc6
SL
72 /// });
73 /// }
74 /// ```
75 ///
76 /// The key is the line marked `(*)`: the closure implicitly
77 /// accesses the body of the item `item`, so we register a read
78 /// from `Hir(item_def_id)`.
3b2f2976 79 fn memoize<OP>(&self, key: M::Key, op: OP) -> M::Value
9cc50fc6
SL
80 where OP: FnOnce() -> M::Value
81 {
82 let graph;
83 {
84 let this = self.borrow();
3b2f2976
XL
85 if let Some(&(ref result, dep_node)) = this.map.get(&key) {
86 this.graph.read_index(dep_node);
9cc50fc6
SL
87 return result.clone();
88 }
89 graph = this.graph.clone();
90 }
91
3b2f2976
XL
92 let (result, dep_node) = graph.with_anon_task(M::to_dep_kind(), op);
93 self.borrow_mut().map.insert(key, (result.clone(), dep_node));
94 graph.read_index(dep_node);
9cc50fc6
SL
95 result
96 }
97}