Skip to content

Commit 24a40da

Browse files
committed
Make AllocId decoding thread-safe
1 parent c8e10e3 commit 24a40da

File tree

5 files changed

+68
-166
lines changed

5 files changed

+68
-166
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@ use mir;
1717
use hir::def_id::DefId;
1818
use ty::{self, TyCtxt, Instance};
1919
use ty::layout::{self, Align, HasDataLayout, Size};
20+
use ty::codec::{TyEncoder, TyDecoder};
2021
use middle::region;
2122
use std::iter;
2223
use std::io;
2324
use std::ops::{Deref, DerefMut};
2425
use std::hash::Hash;
2526
use syntax::ast::Mutability;
26-
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
27+
use rustc_serialize::{Decodable, Encodable};
2728
use rustc_data_structures::sorted_map::SortedMap;
2829
use rustc_data_structures::fx::FxHashMap;
30+
use rustc_data_structures::sync::{HashMapExt, LockGuard};
2931
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
3032

3133
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
@@ -162,25 +164,37 @@ impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
162164
#[derive(RustcDecodable, RustcEncodable)]
163165
enum AllocKind {
164166
Alloc,
167+
AllocAtPos,
165168
Fn,
166169
Static,
167170
}
168171

169172
pub fn specialized_encode_alloc_id<
170173
'a, 'tcx,
171-
E: Encoder,
174+
E: TyEncoder,
175+
M,
172176
>(
173177
encoder: &mut E,
174178
tcx: TyCtxt<'a, 'tcx, 'tcx>,
179+
cache: M,
175180
alloc_id: AllocId,
176-
) -> Result<(), E::Error> {
181+
) -> Result<(), E::Error>
182+
where
183+
M: Fn(&mut E) -> &mut FxHashMap<AllocId, usize>
184+
{
177185
let alloc_type: AllocType<'tcx, &'tcx Allocation> =
178186
tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId");
179187
match alloc_type {
180188
AllocType::Memory(alloc) => {
189+
if let Some(alloc_pos) = cache(encoder).get(&alloc_id).cloned() {
190+
AllocKind::AllocAtPos.encode(encoder)?;
191+
return encoder.emit_usize(alloc_pos);
192+
}
193+
let pos = encoder.position();
181194
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
182195
AllocKind::Alloc.encode(encoder)?;
183196
alloc.encode(encoder)?;
197+
cache(encoder).insert_same(alloc_id, pos);
184198
}
185199
AllocType::Function(fn_instance) => {
186200
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
@@ -199,23 +213,32 @@ pub fn specialized_encode_alloc_id<
199213

200214
pub fn specialized_decode_alloc_id<
201215
'a, 'tcx,
202-
D: Decoder,
203-
CACHE: FnOnce(&mut D, AllocId),
216+
D: TyDecoder<'a, 'tcx>,
217+
CACHE: FnOnce(&mut D) -> LockGuard<'_, FxHashMap<usize, AllocId>>,
204218
>(
205219
decoder: &mut D,
206220
tcx: TyCtxt<'a, 'tcx, 'tcx>,
207221
cache: CACHE,
208222
) -> Result<AllocId, D::Error> {
209223
match AllocKind::decode(decoder)? {
224+
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)
230+
},
210231
AllocKind::Alloc => {
211-
let alloc_id = tcx.alloc_map.lock().reserve();
212-
trace!("creating alloc id {:?}", alloc_id);
232+
let pos = decoder.position();
213233
// insert early to allow recursive allocs
214-
cache(decoder, alloc_id);
234+
let alloc_id = *cache(decoder).entry(pos)
235+
.or_insert_with(|| tcx.alloc_map.lock().reserve());
236+
trace!("creating alloc id {:?}", alloc_id);
215237

216238
let allocation = <&'tcx Allocation as Decodable>::decode(decoder)?;
217239
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
218-
tcx.alloc_map.lock().set_id_memory(alloc_id, allocation);
240+
// This may overwrite with the same allocation
241+
tcx.alloc_map.lock().set_id_same_memory(alloc_id, allocation);
219242

220243
Ok(alloc_id)
221244
},
@@ -225,14 +248,12 @@ pub fn specialized_decode_alloc_id<
225248
trace!("decoded fn alloc instance: {:?}", instance);
226249
let id = tcx.alloc_map.lock().create_fn_alloc(instance);
227250
trace!("created fn alloc id: {:?}", id);
228-
cache(decoder, id);
229251
Ok(id)
230252
},
231253
AllocKind::Static => {
232254
trace!("creating extern static alloc id at");
233255
let did = DefId::decode(decoder)?;
234256
let alloc_id = tcx.alloc_map.lock().intern_static(did);
235-
cache(decoder, alloc_id);
236257
Ok(alloc_id)
237258
},
238259
}
@@ -333,6 +354,10 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
333354
bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old);
334355
}
335356
}
357+
358+
fn set_id_same_memory(&mut self, id: AllocId, mem: M) {
359+
self.id_to_type.insert_same(id, AllocType::Memory(mem));
360+
}
336361
}
337362

338363
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 17 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
2323
SpecializedDecoder, SpecializedEncoder,
2424
UseSpecializedDecodable, UseSpecializedEncodable};
2525
use session::{CrateDisambiguator, Session};
26-
use std::cell::RefCell;
2726
use std::mem;
2827
use syntax::ast::NodeId;
2928
use syntax::codemap::{CodeMap, StableFilemapId};
@@ -77,11 +76,8 @@ pub struct OnDiskCache<'sess> {
7776
// `serialized_data`.
7877
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7978

80-
// Alloc indices to memory location map
81-
prev_interpret_alloc_index: Vec<AbsoluteBytePos>,
82-
8379
/// Deserialization: A cache to ensure we don't read allocations twice
84-
interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
80+
interpret_alloc_cache: Lock<FxHashMap<usize, interpret::AllocId>>,
8581
}
8682

8783
// This type is used only for (de-)serialization.
@@ -91,8 +87,6 @@ struct Footer {
9187
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
9288
query_result_index: EncodedQueryResultIndex,
9389
diagnostics_index: EncodedQueryResultIndex,
94-
// the location of all allocations
95-
interpret_alloc_index: Vec<AbsoluteBytePos>,
9690
}
9791

9892
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -149,8 +143,7 @@ impl<'sess> OnDiskCache<'sess> {
149143
query_result_index: footer.query_result_index.into_iter().collect(),
150144
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
151145
synthetic_expansion_infos: Lock::new(FxHashMap()),
152-
prev_interpret_alloc_index: footer.interpret_alloc_index,
153-
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
146+
interpret_alloc_cache: Lock::new(FxHashMap::default()),
154147
}
155148
}
156149

@@ -166,8 +159,7 @@ impl<'sess> OnDiskCache<'sess> {
166159
query_result_index: FxHashMap(),
167160
prev_diagnostics_index: FxHashMap(),
168161
synthetic_expansion_infos: Lock::new(FxHashMap()),
169-
prev_interpret_alloc_index: Vec::new(),
170-
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
162+
interpret_alloc_cache: Lock::new(FxHashMap::default()),
171163
}
172164
}
173165

@@ -201,7 +193,6 @@ impl<'sess> OnDiskCache<'sess> {
201193
predicate_shorthands: FxHashMap(),
202194
expn_info_shorthands: FxHashMap(),
203195
interpret_allocs: FxHashMap(),
204-
interpret_allocs_inverse: Vec::new(),
205196
codemap: CachingCodemapView::new(tcx.sess.codemap()),
206197
file_to_file_index,
207198
};
@@ -279,31 +270,6 @@ impl<'sess> OnDiskCache<'sess> {
279270
diagnostics_index
280271
};
281272

282-
let interpret_alloc_index = {
283-
let mut interpret_alloc_index = Vec::new();
284-
let mut n = 0;
285-
loop {
286-
let new_n = encoder.interpret_allocs_inverse.len();
287-
// if we have found new ids, serialize those, too
288-
if n == new_n {
289-
// otherwise, abort
290-
break;
291-
}
292-
for idx in n..new_n {
293-
let id = encoder.interpret_allocs_inverse[idx];
294-
let pos = AbsoluteBytePos::new(encoder.position());
295-
interpret_alloc_index.push(pos);
296-
interpret::specialized_encode_alloc_id(
297-
&mut encoder,
298-
tcx,
299-
id,
300-
)?;
301-
}
302-
n = new_n;
303-
}
304-
interpret_alloc_index
305-
};
306-
307273
let sorted_cnums = sorted_cnums_including_local_crate(tcx);
308274
let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
309275
let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
@@ -318,7 +284,6 @@ impl<'sess> OnDiskCache<'sess> {
318284
prev_cnums,
319285
query_result_index,
320286
diagnostics_index,
321-
interpret_alloc_index,
322287
})?;
323288

324289
// Encode the position of the footer as the last 8 bytes of the
@@ -424,7 +389,6 @@ impl<'sess> OnDiskCache<'sess> {
424389
file_index_to_file: &self.file_index_to_file,
425390
file_index_to_stable_id: &self.file_index_to_stable_id,
426391
synthetic_expansion_infos: &self.synthetic_expansion_infos,
427-
prev_interpret_alloc_index: &self.prev_interpret_alloc_index,
428392
interpret_alloc_cache: &self.interpret_alloc_cache,
429393
};
430394

@@ -487,9 +451,7 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
487451
synthetic_expansion_infos: &'x Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
488452
file_index_to_file: &'x Lock<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
489453
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
490-
interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
491-
/// maps from index in the cache file to location in the cache file
492-
prev_interpret_alloc_index: &'x [AbsoluteBytePos],
454+
interpret_alloc_cache: &'x Lock<FxHashMap<usize, interpret::AllocId>>,
493455
}
494456

495457
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
@@ -613,31 +575,14 @@ implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
613575
impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
614576
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
615577
let tcx = self.tcx;
616-
let idx = usize::decode(self)?;
617-
trace!("loading index {}", idx);
618-
619-
if let Some(cached) = self.interpret_alloc_cache.borrow().get(&idx).cloned() {
620-
trace!("loading alloc id {:?} from alloc_cache", cached);
621-
return Ok(cached);
622-
}
623-
let pos = self.prev_interpret_alloc_index[idx].to_usize();
624-
trace!("loading position {}", pos);
625-
self.with_position(pos, |this| {
626-
interpret::specialized_decode_alloc_id(
627-
this,
628-
tcx,
629-
|this, alloc_id| {
630-
trace!("caching idx {} for alloc id {} at position {}", idx, alloc_id, pos);
631-
assert!(this
632-
.interpret_alloc_cache
633-
.borrow_mut()
634-
.insert(idx, alloc_id)
635-
.is_none());
636-
},
637-
)
638-
})
578+
interpret::specialized_decode_alloc_id(
579+
self,
580+
tcx,
581+
|this| this.interpret_alloc_cache.lock(),
582+
)
639583
}
640584
}
585+
641586
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
642587
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
643588
let tag: u8 = Decodable::decode(self)?;
@@ -800,7 +745,6 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
800745
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
801746
expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
802747
interpret_allocs: FxHashMap<interpret::AllocId, usize>,
803-
interpret_allocs_inverse: Vec<interpret::AllocId>,
804748
codemap: CachingCodemapView<'tcx>,
805749
file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>,
806750
}
@@ -837,18 +781,13 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<
837781
where E: 'enc + ty_codec::TyEncoder
838782
{
839783
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
840-
use std::collections::hash_map::Entry;
841-
let index = match self.interpret_allocs.entry(*alloc_id) {
842-
Entry::Occupied(e) => *e.get(),
843-
Entry::Vacant(e) => {
844-
let idx = self.interpret_allocs_inverse.len();
845-
self.interpret_allocs_inverse.push(*alloc_id);
846-
e.insert(idx);
847-
idx
848-
},
849-
};
850-
851-
index.encode(self)
784+
let tcx = self.tcx;
785+
interpret::specialized_encode_alloc_id(
786+
self,
787+
tcx,
788+
|this| &mut this.interpret_allocs,
789+
*alloc_id,
790+
)
852791
}
853792
}
854793

src/librustc_metadata/decoder.rs

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
1414
use schema::*;
1515

16-
use rustc_data_structures::sync::{Lrc, ReadGuard};
16+
use rustc_data_structures::sync::{Lrc, ReadGuard, Lock};
1717
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
1818
DisambiguatedDefPathData};
1919
use rustc::hir;
@@ -56,10 +56,7 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
5656
lazy_state: LazyState,
5757

5858
// interpreter allocation cache
59-
interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
60-
61-
// Read from the LazySeq CrateRoot::inpterpret_alloc_index on demand
62-
interpret_alloc_index: Option<Vec<u32>>,
59+
interpret_alloc_cache: Lock<FxHashMap<usize, interpret::AllocId>>,
6360
}
6461

6562
/// Abstract over the various ways one can create metadata decoders.
@@ -78,8 +75,7 @@ pub trait Metadata<'a, 'tcx>: Copy {
7875
tcx,
7976
last_filemap_index: 0,
8077
lazy_state: LazyState::NoNode,
81-
interpret_alloc_cache: FxHashMap::default(),
82-
interpret_alloc_index: None,
78+
interpret_alloc_cache: Lock::new(FxHashMap::default()),
8379
}
8480
}
8581
}
@@ -178,17 +174,6 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
178174
self.lazy_state = LazyState::Previous(position + min_size);
179175
Ok(position)
180176
}
181-
182-
fn interpret_alloc(&mut self, idx: usize) -> usize {
183-
if let Some(index) = self.interpret_alloc_index.as_mut() {
184-
return index[idx] as usize;
185-
}
186-
let cdata = self.cdata();
187-
let index: Vec<u32> = cdata.root.interpret_alloc_index.decode(cdata).collect();
188-
let pos = index[idx];
189-
self.interpret_alloc_index = Some(index);
190-
pos as usize
191-
}
192177
}
193178

194179
impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
@@ -300,21 +285,11 @@ impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
300285
impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
301286
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
302287
let tcx = self.tcx.unwrap();
303-
let idx = usize::decode(self)?;
304-
305-
if let Some(cached) = self.interpret_alloc_cache.get(&idx).cloned() {
306-
return Ok(cached);
307-
}
308-
let pos = self.interpret_alloc(idx);
309-
self.with_position(pos, |this| {
310-
interpret::specialized_decode_alloc_id(
311-
this,
312-
tcx,
313-
|this, alloc_id| {
314-
assert!(this.interpret_alloc_cache.insert(idx, alloc_id).is_none());
315-
},
316-
)
317-
})
288+
interpret::specialized_decode_alloc_id(
289+
self,
290+
tcx,
291+
|this| this.interpret_alloc_cache.lock()
292+
)
318293
}
319294
}
320295

0 commit comments

Comments
 (0)