Skip to content

Commit 94eef34

Browse files
committed
Fixes
1 parent 24a40da commit 94eef34

File tree

3 files changed

+60
-20
lines changed

3 files changed

+60
-20
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
1212

1313
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, ConstValue};
1414

15+
use std::collections::hash_map::Entry;
1516
use std::fmt;
1617
use mir;
1718
use hir::def_id::DefId;
@@ -26,7 +27,7 @@ use std::hash::Hash;
2627
use syntax::ast::Mutability;
2728
use rustc_serialize::{Decodable, Encodable};
2829
use rustc_data_structures::sorted_map::SortedMap;
29-
use rustc_data_structures::fx::FxHashMap;
30+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3031
use rustc_data_structures::sync::{HashMapExt, LockGuard};
3132
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
3233

@@ -191,10 +192,10 @@ where
191192
return encoder.emit_usize(alloc_pos);
192193
}
193194
let pos = encoder.position();
195+
assert!(cache(encoder).insert(alloc_id, pos).is_none());
194196
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
195197
AllocKind::Alloc.encode(encoder)?;
196198
alloc.encode(encoder)?;
197-
cache(encoder).insert_same(alloc_id, pos);
198199
}
199200
AllocType::Function(fn_instance) => {
200201
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
@@ -214,32 +215,65 @@ where
214215
pub fn specialized_decode_alloc_id<
215216
'a, 'tcx,
216217
D: TyDecoder<'a, 'tcx>,
217-
CACHE: FnOnce(&mut D) -> LockGuard<'_, FxHashMap<usize, AllocId>>,
218+
GlobalCache: FnMut(&mut D) -> LockGuard<'_, FxHashMap<usize, (AllocId, bool)>>,
219+
LocalCache: FnOnce(&mut D) -> &mut FxHashSet<AllocId>,
218220
>(
219221
decoder: &mut D,
220222
tcx: TyCtxt<'a, 'tcx, 'tcx>,
221-
cache: CACHE,
223+
mut global_cache: GlobalCache,
224+
local_cache: LocalCache,
222225
) -> Result<AllocId, D::Error> {
226+
let pos = decoder.position();
223227
match AllocKind::decode(decoder)? {
224228
AllocKind::AllocAtPos => {
225-
let pos = decoder.read_usize()?;
226-
if let Some(alloc_id) = cache(decoder).get(&pos).cloned() {
227-
return Ok(alloc_id);
228-
}
229-
decoder.with_position(pos, AllocId::decode)
229+
let real_pos = decoder.read_usize()?;
230+
decoder.with_position(real_pos, AllocId::decode)
230231
},
231232
AllocKind::Alloc => {
232-
let pos = decoder.position();
233-
// insert early to allow recursive allocs
234-
let alloc_id = *cache(decoder).entry(pos)
235-
.or_insert_with(|| tcx.alloc_map.lock().reserve());
236-
trace!("creating alloc id {:?}", alloc_id);
233+
let alloc_id = {
234+
let mut cache = global_cache(decoder);
235+
let entry = cache.entry(pos);
236+
match entry {
237+
Entry::Occupied(occupied) => {
238+
let id = occupied.get().0;
239+
240+
// If the alloc id is fully loaded we just return here.
241+
if occupied.get().1 {
242+
return Ok(id)
243+
}
244+
245+
// It was only partially loaded.
246+
// This may be loading further up the stack
247+
// or concurrently in another thread.
248+
id
249+
}
250+
Entry::Vacant(vacant) => {
251+
// Insert early to allow recursive allocs
252+
let id = tcx.alloc_map.lock().reserve();
253+
vacant.insert((id, false));
254+
id
255+
}
256+
}
257+
};
258+
259+
// Insert early to allow recursive allocs and ot indicate that the current
260+
// session will eventually fully load this alloc id
261+
if !local_cache(decoder).insert(alloc_id) {
262+
// We have started decoding this alloc id already, so just return it.
263+
// Its content is already filled in or will be filled in by functions
264+
// further up the stack.
265+
return Ok(alloc_id);
266+
267+
}
237268

238269
let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?;
239270
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
240271
// This may overwrite with the same allocation
241272
tcx.alloc_map.lock().set_id_same_memory(alloc_id, allocation);
242273

274+
// Mark the alloc id as fully loaded
275+
global_cache(decoder).insert(pos, (alloc_id, true));
276+
243277
Ok(alloc_id)
244278
},
245279
AllocKind::Fn => {

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
1616
use hir::map::definitions::DefPathHash;
1717
use ich::{CachingCodemapView, Fingerprint};
1818
use mir::{self, interpret};
19-
use rustc_data_structures::fx::FxHashMap;
19+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2020
use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once};
2121
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
2222
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
@@ -77,7 +77,7 @@ pub struct OnDiskCache<'sess> {
7777
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7878

7979
/// Deserialization: A cache to ensure we don't read allocations twice
80-
interpret_alloc_cache: Lock<FxHashMap<usize, interpret::AllocId>>,
80+
interpret_alloc_cache: Lock<FxHashMap<usize, (interpret::AllocId, bool)>>,
8181
}
8282

8383
// This type is used only for (de-)serialization.
@@ -390,6 +390,7 @@ impl<'sess> OnDiskCache<'sess> {
390390
file_index_to_stable_id: &self.file_index_to_stable_id,
391391
synthetic_expansion_infos: &self.synthetic_expansion_infos,
392392
interpret_alloc_cache: &self.interpret_alloc_cache,
393+
interpret_alloc_local_cache: FxHashSet::default(),
393394
};
394395

395396
match decode_tagged(&mut decoder, dep_node_index) {
@@ -451,7 +452,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
451452
synthetic_expansion_infos: &'x Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
452453
file_index_to_file: &'x Lock<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
453454
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
454-
interpret_alloc_cache: &'x Lock<FxHashMap<usize, interpret::AllocId>>,
455+
interpret_alloc_cache: &'x Lock<FxHashMap<usize, (interpret::AllocId, bool)>>,
456+
interpret_alloc_local_cache: FxHashSet<interpret::AllocId>,
455457
}
456458

457459
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
@@ -579,6 +581,7 @@ impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, '
579581
self,
580582
tcx,
581583
|this| this.interpret_alloc_cache.lock(),
584+
|this| &mut this.interpret_alloc_local_cache,
582585
)
583586
}
584587
}

src/librustc_metadata/decoder.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc::ty::{self, Ty, TyCtxt};
3030
use rustc::ty::codec::TyDecoder;
3131
use rustc::mir::Mir;
3232
use rustc::util::captures::Captures;
33-
use rustc::util::nodemap::FxHashMap;
33+
use rustc::util::nodemap::{FxHashMap, FxHashSet};
3434

3535
use std::io;
3636
use std::mem;
@@ -56,7 +56,8 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
5656
lazy_state: LazyState,
5757

5858
// interpreter allocation cache
59-
interpret_alloc_cache: Lock<FxHashMap<usize, interpret::AllocId>>,
59+
interpret_alloc_cache: Lock<FxHashMap<usize, (interpret::AllocId, bool)>>,
60+
interpret_alloc_local_cache: FxHashSet<interpret::AllocId>,
6061
}
6162

6263
/// Abstract over the various ways one can create metadata decoders.
@@ -76,6 +77,7 @@ pub trait Metadata<'a, 'tcx>: Copy {
7677
last_filemap_index: 0,
7778
lazy_state: LazyState::NoNode,
7879
interpret_alloc_cache: Lock::new(FxHashMap::default()),
80+
interpret_alloc_local_cache: FxHashSet::default(),
7981
}
8082
}
8183
}
@@ -288,7 +290,8 @@ impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx
288290
interpret::specialized_decode_alloc_id(
289291
self,
290292
tcx,
291-
|this| this.interpret_alloc_cache.lock()
293+
|this| this.interpret_alloc_cache.lock(),
294+
|this| &mut this.interpret_alloc_local_cache,
292295
)
293296
}
294297
}

0 commit comments

Comments
 (0)