]> git.proxmox.com Git - rustc.git/blame - src/librustc_incremental/persist/hash.rs
New upstream version 1.15.0+dfsg1
[rustc.git] / src / librustc_incremental / persist / hash.rs
CommitLineData
a7813a04
XL
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
a7813a04 11use rustc::dep_graph::DepNode;
9e0c209e 12use rustc::hir::def_id::{CrateNum, DefId};
a7813a04
XL
13use rustc::hir::svh::Svh;
14use rustc::ty::TyCtxt;
476ff2be 15use rustc_data_structures::fx::FxHashMap;
9e0c209e 16use rustc_data_structures::flock;
a7813a04 17use rustc_serialize::Decodable;
9e0c209e 18use rustc_serialize::opaque::Decoder;
a7813a04 19
9e0c209e 20use IncrementalHashesMap;
c30ab7b3 21use ich::Fingerprint;
a7813a04 22use super::data::*;
9e0c209e
SL
23use super::fs::*;
24use super::file_format;
a7813a04
XL
25
26pub struct HashContext<'a, 'tcx: 'a> {
27 pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
9e0c209e 28 incremental_hashes_map: &'a IncrementalHashesMap,
476ff2be
SL
29 item_metadata_hashes: FxHashMap<DefId, Fingerprint>,
30 crate_hashes: FxHashMap<CrateNum, Svh>,
a7813a04
XL
31}
32
33impl<'a, 'tcx> HashContext<'a, 'tcx> {
9e0c209e
SL
34 pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
35 incremental_hashes_map: &'a IncrementalHashesMap)
36 -> Self {
a7813a04
XL
37 HashContext {
38 tcx: tcx,
9e0c209e 39 incremental_hashes_map: incremental_hashes_map,
476ff2be
SL
40 item_metadata_hashes: FxHashMap(),
41 crate_hashes: FxHashMap(),
a7813a04
XL
42 }
43 }
44
5bcae85e
SL
45 pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
46 match *dep_node {
9e0c209e 47 DepNode::Krate |
476ff2be
SL
48 DepNode::Hir(_) |
49 DepNode::HirBody(_) =>
50 true,
5bcae85e
SL
51 DepNode::MetaData(def_id) => !def_id.is_local(),
52 _ => false,
53 }
54 }
55
c30ab7b3 56 pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
3157f602 57 match *dep_node {
9e0c209e
SL
58 DepNode::Krate => {
59 Some(self.incremental_hashes_map[dep_node])
60 }
61
a7813a04 62 // HIR nodes (which always come from our crate) are an input:
476ff2be 63 DepNode::Hir(def_id) | DepNode::HirBody(def_id) => {
9e0c209e
SL
64 assert!(def_id.is_local(),
65 "cannot hash HIR for non-local def-id {:?} => {:?}",
66 def_id,
67 self.tcx.item_path_str(def_id));
68
69 assert!(!self.tcx.map.is_inlined_def_id(def_id),
70 "cannot hash HIR for inlined def-id {:?} => {:?}",
71 def_id,
72 self.tcx.item_path_str(def_id));
73
74 Some(self.incremental_hashes_map[dep_node])
a7813a04
XL
75 }
76
77 // MetaData from other crates is an *input* to us.
78 // MetaData nodes from *our* crates are an *output*; we
79 // don't hash them, but we do compute a hash for them and
80 // save it for others to use.
81 DepNode::MetaData(def_id) if !def_id.is_local() => {
9e0c209e 82 Some(self.metadata_hash(def_id))
a7813a04
XL
83 }
84
85 _ => {
86 // Other kinds of nodes represent computed by-products
87 // that we don't hash directly; instead, they should
88 // have some transitive dependency on a Hir or
89 // MetaData node, so we'll just hash that
90 None
91 }
92 }
93 }
94
c30ab7b3 95 fn metadata_hash(&mut self, def_id: DefId) -> Fingerprint {
a7813a04
XL
96 debug!("metadata_hash(def_id={:?})", def_id);
97
98 assert!(!def_id.is_local());
99 loop {
100 // check whether we have a result cached for this def-id
101 if let Some(&hash) = self.item_metadata_hashes.get(&def_id) {
102 debug!("metadata_hash: def_id={:?} hash={:?}", def_id, hash);
103 return hash;
104 }
105
106 // check whether we did not find detailed metadata for this
107 // krate; in that case, we just use the krate's overall hash
c30ab7b3
SL
108 if let Some(&svh) = self.crate_hashes.get(&def_id.krate) {
109 debug!("metadata_hash: def_id={:?} crate_hash={:?}", def_id, svh);
a7813a04
XL
110
111 // micro-"optimization": avoid a cache miss if we ask
112 // for metadata from this particular def-id again.
c30ab7b3
SL
113 let fingerprint = svh_to_fingerprint(svh);
114 self.item_metadata_hashes.insert(def_id, fingerprint);
a7813a04 115
c30ab7b3 116 return fingerprint;
a7813a04
XL
117 }
118
119 // otherwise, load the data and repeat.
120 self.load_data(def_id.krate);
121 assert!(self.crate_hashes.contains_key(&def_id.krate));
122 }
123 }
124
9e0c209e 125 fn load_data(&mut self, cnum: CrateNum) {
a7813a04
XL
126 debug!("load_data(cnum={})", cnum);
127
128 let svh = self.tcx.sess.cstore.crate_hash(cnum);
129 let old = self.crate_hashes.insert(cnum, svh);
130 debug!("load_data: svh={}", svh);
131 assert!(old.is_none(), "loaded data for crate {:?} twice", cnum);
132
9e0c209e
SL
133 if let Some(session_dir) = find_metadata_hashes_for(self.tcx, cnum) {
134 debug!("load_data: session_dir={:?}", session_dir);
135
136 // Lock the directory we'll be reading the hashes from.
137 let lock_file_path = lock_file_path(&session_dir);
138 let _lock = match flock::Lock::new(&lock_file_path,
139 false, // don't wait
140 false, // don't create the lock-file
141 false) { // shared lock
142 Ok(lock) => lock,
143 Err(err) => {
144 debug!("Could not acquire lock on `{}` while trying to \
145 load metadata hashes: {}",
146 lock_file_path.display(),
147 err);
148
149 // Could not acquire the lock. The directory is probably in
150 // in the process of being deleted. It's OK to just exit
151 // here. It's the same scenario as if the file had not
152 // existed in the first place.
153 return
154 }
155 };
156
157 let hashes_file_path = metadata_hash_import_path(&session_dir);
158
476ff2be 159 match file_format::read_file(self.tcx.sess, &hashes_file_path)
a7813a04 160 {
9e0c209e
SL
161 Ok(Some(data)) => {
162 match self.load_from_data(cnum, &data, svh) {
a7813a04
XL
163 Ok(()) => { }
164 Err(err) => {
165 bug!("decoding error in dep-graph from `{}`: {}",
9e0c209e 166 &hashes_file_path.display(), err);
a7813a04
XL
167 }
168 }
169 }
9e0c209e
SL
170 Ok(None) => {
171 // If the file is not found, that's ok.
172 }
a7813a04 173 Err(err) => {
9e0c209e
SL
174 self.tcx.sess.err(
175 &format!("could not load dep information from `{}`: {}",
176 hashes_file_path.display(), err));
a7813a04
XL
177 }
178 }
179 }
180 }
181
9e0c209e
SL
182 fn load_from_data(&mut self,
183 cnum: CrateNum,
184 data: &[u8],
185 expected_svh: Svh) -> Result<(), String> {
a7813a04
XL
186 debug!("load_from_data(cnum={})", cnum);
187
188 // Load up the hashes for the def-ids from this crate.
189 let mut decoder = Decoder::new(data, 0);
9e0c209e
SL
190 let svh_in_hashes_file = Svh::decode(&mut decoder)?;
191
192 if svh_in_hashes_file != expected_svh {
193 // We should not be able to get here. If we do, then
194 // `fs::find_metadata_hashes_for()` has messed up.
195 bug!("mismatch between SVH in crate and SVH in incr. comp. hashes")
196 }
197
198 let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder)?;
a7813a04
XL
199 for serialized_hash in serialized_hashes.hashes {
200 // the hashes are stored with just a def-index, which is
201 // always relative to the old crate; convert that to use
202 // our internal crate number
203 let def_id = DefId { krate: cnum, index: serialized_hash.def_index };
204
205 // record the hash for this dep-node
206 let old = self.item_metadata_hashes.insert(def_id, serialized_hash.hash);
207 debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash);
208 assert!(old.is_none(), "already have hash for {:?}", def_id);
209 }
210 Ok(())
211 }
212}
c30ab7b3
SL
213
214fn svh_to_fingerprint(svh: Svh) -> Fingerprint {
215 Fingerprint::from_smaller_hash(svh.as_u64())
216}