]>
git.proxmox.com Git - rustc.git/blob - src/librustc/dep_graph/dep_tracking_map.rs
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.
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.
11 use hir
::def_id
::DefId
;
12 use rustc_data_structures
::fnv
::FnvHashMap
;
13 use std
::cell
::RefCell
;
16 use std
::marker
::PhantomData
;
17 use util
::common
::MemoizationMap
;
19 use super::{DepNode, DepGraph}
;
21 /// A DepTrackingMap offers a subset of the `Map` API and ensures that
22 /// we make calls to `read` and `write` as appropriate. We key the
23 /// maps with a unique type for brevity.
24 pub struct DepTrackingMap
<M
: DepTrackingMapConfig
> {
25 phantom
: PhantomData
<M
>,
27 map
: FnvHashMap
<M
::Key
, M
::Value
>,
30 pub trait DepTrackingMapConfig
{
31 type Key
: Eq
+ Hash
+ Clone
;
33 fn to_dep_node(key
: &Self::Key
) -> DepNode
<DefId
>;
36 impl<M
: DepTrackingMapConfig
> DepTrackingMap
<M
> {
37 pub fn new(graph
: DepGraph
) -> DepTrackingMap
<M
> {
45 /// Registers a (synthetic) read from the key `k`. Usually this
46 /// is invoked automatically by `get`.
47 fn read(&self, k
: &M
::Key
) {
48 let dep_node
= M
::to_dep_node(k
);
49 self.graph
.read(dep_node
);
52 /// Registers a (synthetic) write to the key `k`. Usually this is
53 /// invoked automatically by `insert`.
54 fn write(&self, k
: &M
::Key
) {
55 let dep_node
= M
::to_dep_node(k
);
56 self.graph
.write(dep_node
);
59 pub fn get(&self, k
: &M
::Key
) -> Option
<&M
::Value
> {
64 pub fn insert(&mut self, k
: M
::Key
, v
: M
::Value
) -> Option
<M
::Value
> {
69 pub fn contains_key(&self, k
: &M
::Key
) -> bool
{
71 self.map
.contains_key(k
)
75 impl<M
: DepTrackingMapConfig
> MemoizationMap
for RefCell
<DepTrackingMap
<M
>> {
77 type Value
= M
::Value
;
79 /// Memoizes an entry in the dep-tracking-map. If the entry is not
80 /// already present, then `op` will be executed to compute its value.
81 /// The resulting dependency graph looks like this:
83 /// [op] -> Map(key) -> CurrentTask
85 /// Here, `[op]` represents whatever nodes `op` reads in the
86 /// course of execution; `Map(key)` represents the node for this
87 /// map; and `CurrentTask` represents the current task when
88 /// `memoize` is invoked.
90 /// **Important:* when `op` is invoked, the current task will be
91 /// switched to `Map(key)`. Therefore, if `op` makes use of any
92 /// HIR nodes or shared state accessed through its closure
93 /// environment, it must explicitly register a read of that
94 /// state. As an example, see `type_scheme_of_item` in `collect`,
95 /// which looks something like this:
98 /// fn type_scheme_of_item(..., item: &hir::Item) -> ty::TypeScheme<'tcx> {
99 /// let item_def_id = ccx.tcx.map.local_def_id(it.id);
100 /// ccx.tcx.tcache.memoized(item_def_id, || {
101 /// ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // (*)
102 /// compute_type_scheme_of_item(ccx, item)
107 /// The key is the line marked `(*)`: the closure implicitly
108 /// accesses the body of the item `item`, so we register a read
109 /// from `Hir(item_def_id)`.
110 fn memoize
<OP
>(&self, key
: M
::Key
, op
: OP
) -> M
::Value
111 where OP
: FnOnce() -> M
::Value
115 let this
= self.borrow();
116 if let Some(result
) = this
.map
.get(&key
) {
118 return result
.clone();
120 graph
= this
.graph
.clone();
123 let _task
= graph
.in_task(M
::to_dep_node(&key
));
125 self.borrow_mut().map
.insert(key
, result
.clone());
130 impl<'k
, M
: DepTrackingMapConfig
> Index
<&'k M
::Key
> for DepTrackingMap
<M
> {
131 type Output
= M
::Value
;
134 fn index(&self, k
: &'k M
::Key
) -> &M
::Value
{