]>
Commit | Line | Data |
---|---|---|
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 | 11 | use rustc_data_structures::fx::FxHashMap; |
9cc50fc6 | 12 | use std::cell::RefCell; |
9cc50fc6 SL |
13 | use std::hash::Hash; |
14 | use std::marker::PhantomData; | |
15 | use util::common::MemoizationMap; | |
16 | ||
3b2f2976 | 17 | use 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. | |
22 | pub struct DepTrackingMap<M: DepTrackingMapConfig> { | |
23 | phantom: PhantomData<M>, | |
24 | graph: DepGraph, | |
3b2f2976 | 25 | map: FxHashMap<M::Key, (M::Value, DepNodeIndex)>, |
9cc50fc6 SL |
26 | } |
27 | ||
28 | pub trait DepTrackingMapConfig { | |
29 | type Key: Eq + Hash + Clone; | |
30 | type Value: Clone; | |
3b2f2976 | 31 | fn to_dep_kind() -> DepKind; |
9cc50fc6 SL |
32 | } |
33 | ||
34 | impl<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 | ||
44 | impl<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 | } |