Skip to content

Commit 2546ff8

Browse files
committed
Don't recurse into allocations, use a global table instead
1 parent 32a2a12 commit 2546ff8

File tree

7 files changed

+192
-152
lines changed

7 files changed

+192
-152
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -380,12 +380,12 @@ impl_stable_hash_for!(struct mir::interpret::MemoryPointer {
380380

381381
enum AllocDiscriminant {
382382
Alloc,
383-
ExternStatic,
383+
Static,
384384
Function,
385385
}
386386
impl_stable_hash_for!(enum self::AllocDiscriminant {
387387
Alloc,
388-
ExternStatic,
388+
Static,
389389
Function
390390
});
391391

@@ -396,24 +396,26 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
396396
hasher: &mut StableHasher<W>,
397397
) {
398398
ty::tls::with_opt(|tcx| {
399+
trace!("hashing {:?}", *self);
399400
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
400-
if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
401+
if let Some(def_id) = tcx.interpret_interner
402+
.get_corresponding_static_def_id(*self) {
403+
AllocDiscriminant::Static.hash_stable(hcx, hasher);
404+
trace!("hashing {:?} as static {:?}", *self, def_id);
405+
def_id.hash_stable(hcx, hasher);
406+
} else if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
401407
AllocDiscriminant::Alloc.hash_stable(hcx, hasher);
402408
if hcx.alloc_id_recursion_tracker.insert(*self) {
403-
tcx
404-
.interpret_interner
405-
.get_corresponding_static_def_id(*self)
406-
.hash_stable(hcx, hasher);
409+
trace!("hashing {:?} as alloc {:#?}", *self, alloc);
407410
alloc.hash_stable(hcx, hasher);
408411
assert!(hcx.alloc_id_recursion_tracker.remove(self));
412+
} else {
413+
trace!("skipping hashing of {:?} due to recursion", *self);
409414
}
410415
} else if let Some(inst) = tcx.interpret_interner.get_fn(*self) {
416+
trace!("hashing {:?} as fn {:#?}", *self, inst);
411417
AllocDiscriminant::Function.hash_stable(hcx, hasher);
412418
inst.hash_stable(hcx, hasher);
413-
} else if let Some(def_id) = tcx.interpret_interner
414-
.get_corresponding_static_def_id(*self) {
415-
AllocDiscriminant::ExternStatic.hash_stable(hcx, hasher);
416-
def_id.hash_stable(hcx, hasher);
417419
} else {
418420
bug!("no allocation for {}", self);
419421
}

src/librustc/mir/interpret/mod.rs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,12 @@ pub struct AllocId(pub u64);
154154
impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
155155
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
156156

157-
pub const ALLOC_DISCRIMINANT: usize = 0;
158-
pub const FN_DISCRIMINANT: usize = 1;
159-
pub const EXTERN_STATIC_DISCRIMINANT: usize = 2;
160-
pub const SHORTHAND_START: usize = 3;
157+
#[derive(RustcDecodable, RustcEncodable)]
158+
enum AllocKind {
159+
Alloc,
160+
Fn,
161+
ExternStatic,
162+
}
161163

162164
pub fn specialized_encode_alloc_id<
163165
'a, 'tcx,
@@ -166,26 +168,22 @@ pub fn specialized_encode_alloc_id<
166168
encoder: &mut E,
167169
tcx: TyCtxt<'a, 'tcx, 'tcx>,
168170
alloc_id: AllocId,
169-
shorthand: Option<usize>,
170171
) -> Result<(), E::Error> {
171-
if let Some(shorthand) = shorthand {
172-
return shorthand.encode(encoder);
173-
}
174172
if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
175173
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
176-
ALLOC_DISCRIMINANT.encode(encoder)?;
174+
AllocKind::Alloc.encode(encoder)?;
177175
alloc.encode(encoder)?;
178176
// encode whether this allocation is the root allocation of a static
179177
tcx.interpret_interner
180178
.get_corresponding_static_def_id(alloc_id)
181179
.encode(encoder)?;
182180
} else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
183181
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
184-
FN_DISCRIMINANT.encode(encoder)?;
182+
AllocKind::Fn.encode(encoder)?;
185183
fn_instance.encode(encoder)?;
186184
} else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
187185
// extern "C" statics don't have allocations, just encode its def_id
188-
EXTERN_STATIC_DISCRIMINANT.encode(encoder)?;
186+
AllocKind::ExternStatic.encode(encoder)?;
189187
did.encode(encoder)?;
190188
} else {
191189
bug!("alloc id without corresponding allocation: {}", alloc_id);
@@ -196,21 +194,18 @@ pub fn specialized_encode_alloc_id<
196194
pub fn specialized_decode_alloc_id<
197195
'a, 'tcx,
198196
D: Decoder,
199-
CACHE: FnOnce(&mut D, usize, AllocId),
200-
SHORT: FnOnce(&mut D, usize) -> Result<AllocId, D::Error>
197+
CACHE: FnOnce(&mut D, AllocId),
201198
>(
202199
decoder: &mut D,
203200
tcx: TyCtxt<'a, 'tcx, 'tcx>,
204-
pos: usize,
205201
cache: CACHE,
206-
short: SHORT,
207202
) -> Result<AllocId, D::Error> {
208-
match usize::decode(decoder)? {
209-
ALLOC_DISCRIMINANT => {
203+
match AllocKind::decode(decoder)? {
204+
AllocKind::Alloc => {
210205
let alloc_id = tcx.interpret_interner.reserve();
211-
trace!("creating alloc id {:?} at {}", alloc_id, pos);
206+
trace!("creating alloc id {:?}", alloc_id);
212207
// insert early to allow recursive allocs
213-
cache(decoder, pos, alloc_id);
208+
cache(decoder, alloc_id);
214209

215210
let allocation = Allocation::decode(decoder)?;
216211
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
@@ -223,26 +218,23 @@ pub fn specialized_decode_alloc_id<
223218

224219
Ok(alloc_id)
225220
},
226-
FN_DISCRIMINANT => {
227-
trace!("creating fn alloc id at {}", pos);
221+
AllocKind::Fn => {
222+
trace!("creating fn alloc id");
228223
let instance = ty::Instance::decode(decoder)?;
229224
trace!("decoded fn alloc instance: {:?}", instance);
230225
let id = tcx.interpret_interner.create_fn_alloc(instance);
231226
trace!("created fn alloc id: {:?}", id);
232-
cache(decoder, pos, id);
227+
cache(decoder, id);
233228
Ok(id)
234229
},
235-
EXTERN_STATIC_DISCRIMINANT => {
236-
trace!("creating extern static alloc id at {}", pos);
230+
AllocKind::ExternStatic => {
231+
trace!("creating extern static alloc id at");
237232
let did = DefId::decode(decoder)?;
238233
let alloc_id = tcx.interpret_interner.reserve();
234+
cache(decoder, alloc_id);
239235
tcx.interpret_interner.cache(did, alloc_id);
240236
Ok(alloc_id)
241237
},
242-
shorthand => {
243-
trace!("loading shorthand {}", shorthand);
244-
short(decoder, shorthand)
245-
},
246238
}
247239
}
248240

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 75 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,11 @@ pub struct OnDiskCache<'sess> {
7676
// `serialized_data`.
7777
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7878

79-
// A cache to ensure we don't read allocations twice
80-
interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
79+
// Alloc indices to memory location map
80+
prev_interpret_alloc_index: Vec<AbsoluteBytePos>,
8181

82-
// A map from positions to size of the serialized allocation
83-
// so we can skip over already processed allocations
84-
interpret_alloc_size: RefCell<FxHashMap<usize, usize>>,
82+
/// Deserialization: A cache to ensure we don't read allocations twice
83+
interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
8584
}
8685

8786
// This type is used only for (de-)serialization.
@@ -91,6 +90,8 @@ struct Footer {
9190
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
9291
query_result_index: EncodedQueryResultIndex,
9392
diagnostics_index: EncodedQueryResultIndex,
93+
// the location of all allocations
94+
interpret_alloc_index: Vec<AbsoluteBytePos>,
9495
}
9596

9697
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -147,8 +148,8 @@ impl<'sess> OnDiskCache<'sess> {
147148
query_result_index: footer.query_result_index.into_iter().collect(),
148149
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
149150
synthetic_expansion_infos: RefCell::new(FxHashMap()),
151+
prev_interpret_alloc_index: footer.interpret_alloc_index,
150152
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
151-
interpret_alloc_size: RefCell::new(FxHashMap::default()),
152153
}
153154
}
154155

@@ -164,8 +165,8 @@ impl<'sess> OnDiskCache<'sess> {
164165
query_result_index: FxHashMap(),
165166
prev_diagnostics_index: FxHashMap(),
166167
synthetic_expansion_infos: RefCell::new(FxHashMap()),
168+
prev_interpret_alloc_index: Vec::new(),
167169
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
168-
interpret_alloc_size: RefCell::new(FxHashMap::default()),
169170
}
170171
}
171172

@@ -198,7 +199,9 @@ impl<'sess> OnDiskCache<'sess> {
198199
type_shorthands: FxHashMap(),
199200
predicate_shorthands: FxHashMap(),
200201
expn_info_shorthands: FxHashMap(),
201-
interpret_alloc_shorthands: FxHashMap(),
202+
interpret_allocs: FxHashMap(),
203+
interpret_alloc_ids: FxHashSet(),
204+
interpret_allocs_inverse: Vec::new(),
202205
codemap: CachingCodemapView::new(tcx.sess.codemap()),
203206
file_to_file_index,
204207
};
@@ -272,6 +275,31 @@ impl<'sess> OnDiskCache<'sess> {
272275
diagnostics_index
273276
};
274277

278+
let interpret_alloc_index = {
279+
let mut interpret_alloc_index = Vec::new();
280+
let mut n = 0;
281+
loop {
282+
let new_n = encoder.interpret_alloc_ids.len();
283+
for idx in n..new_n {
284+
let id = encoder.interpret_allocs_inverse[idx];
285+
let pos = AbsoluteBytePos::new(encoder.position());
286+
interpret_alloc_index.push(pos);
287+
interpret::specialized_encode_alloc_id(
288+
&mut encoder,
289+
tcx,
290+
id,
291+
)?;
292+
}
293+
// if we have found new ids, serialize those, too
294+
if n == new_n {
295+
// otherwise, abort
296+
break;
297+
}
298+
n = new_n;
299+
}
300+
interpret_alloc_index
301+
};
302+
275303
let sorted_cnums = sorted_cnums_including_local_crate(tcx);
276304
let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
277305
let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
@@ -286,6 +314,7 @@ impl<'sess> OnDiskCache<'sess> {
286314
prev_cnums,
287315
query_result_index,
288316
diagnostics_index,
317+
interpret_alloc_index,
289318
})?;
290319

291320
// Encode the position of the footer as the last 8 bytes of the
@@ -393,8 +422,8 @@ impl<'sess> OnDiskCache<'sess> {
393422
file_index_to_file: &self.file_index_to_file,
394423
file_index_to_stable_id: &self.file_index_to_stable_id,
395424
synthetic_expansion_infos: &self.synthetic_expansion_infos,
425+
prev_interpret_alloc_index: &self.prev_interpret_alloc_index,
396426
interpret_alloc_cache: &self.interpret_alloc_cache,
397-
interpret_alloc_size: &self.interpret_alloc_size,
398427
};
399428

400429
match decode_tagged(&mut decoder, dep_node_index) {
@@ -457,7 +486,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
457486
file_index_to_file: &'x RefCell<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
458487
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
459488
interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
460-
interpret_alloc_size: &'x RefCell<FxHashMap<usize, usize>>,
489+
/// maps from index in the cache file to location in the cache file
490+
prev_interpret_alloc_index: &'x [AbsoluteBytePos],
461491
}
462492

463493
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
@@ -580,36 +610,29 @@ implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
580610
impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
581611
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
582612
let tcx = self.tcx;
583-
let pos = TyDecoder::position(self);
584-
trace!("specialized_decode_alloc_id: {:?}", pos);
585-
if let Some(cached) = self.interpret_alloc_cache.borrow().get(&pos).cloned() {
586-
// if there's no end position we are currently deserializing a recursive
587-
// allocation
588-
if let Some(end) = self.interpret_alloc_size.borrow().get(&pos).cloned() {
589-
trace!("{} already cached as {:?}", pos, cached);
590-
// skip ahead
591-
self.opaque.set_position(end);
592-
return Ok(cached)
593-
}
613+
let idx = usize::decode(self)?;
614+
trace!("loading index {}", idx);
615+
616+
if let Some(cached) = self.interpret_alloc_cache.borrow().get(&idx).cloned() {
617+
trace!("loading alloc id {:?} from alloc_cache", cached);
618+
return Ok(cached);
594619
}
595-
let id = interpret::specialized_decode_alloc_id(
596-
self,
597-
tcx,
598-
pos,
599-
|this, pos, alloc_id| {
600-
assert!(this.interpret_alloc_cache.borrow_mut().insert(pos, alloc_id).is_none());
601-
},
602-
|this, shorthand| {
603-
// need to load allocation
604-
this.with_position(shorthand, |this| interpret::AllocId::decode(this))
605-
}
606-
)?;
607-
assert!(self
608-
.interpret_alloc_size
609-
.borrow_mut()
610-
.insert(pos, TyDecoder::position(self))
611-
.is_none());
612-
Ok(id)
620+
let pos = self.prev_interpret_alloc_index[idx].to_usize();
621+
trace!("loading position {}", pos);
622+
self.with_position(pos, |this| {
623+
interpret::specialized_decode_alloc_id(
624+
this,
625+
tcx,
626+
|this, alloc_id| {
627+
trace!("caching idx {} for alloc id {} at position {}", idx, alloc_id, pos);
628+
assert!(this
629+
.interpret_alloc_cache
630+
.borrow_mut()
631+
.insert(idx, alloc_id)
632+
.is_none());
633+
},
634+
)
635+
})
613636
}
614637
}
615638
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
@@ -773,7 +796,9 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
773796
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
774797
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
775798
expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
776-
interpret_alloc_shorthands: FxHashMap<interpret::AllocId, usize>,
799+
interpret_allocs: FxHashMap<interpret::AllocId, usize>,
800+
interpret_allocs_inverse: Vec<interpret::AllocId>,
801+
interpret_alloc_ids: FxHashSet<interpret::AllocId>,
777802
codemap: CachingCodemapView<'tcx>,
778803
file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>,
779804
}
@@ -810,27 +835,17 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<
810835
where E: 'enc + ty_codec::TyEncoder
811836
{
812837
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
813-
use std::collections::hash_map::Entry;
814-
let tcx = self.tcx;
815-
let pos = self.position();
816-
let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
817-
Entry::Occupied(entry) => Some(entry.get().clone()),
818-
Entry::Vacant(entry) => {
819-
// ensure that we don't place any AllocIds at the very beginning
820-
// of the metadata file, because that would end up making our indices
821-
// not special. It is essentially impossible for that to happen,
822-
// but let's make sure
823-
assert!(pos >= interpret::SHORTHAND_START);
824-
entry.insert(pos);
825-
None
826-
},
838+
let index = if self.interpret_alloc_ids.insert(*alloc_id) {
839+
let idx = self.interpret_alloc_ids.len() - 1;
840+
assert_eq!(idx, self.interpret_allocs_inverse.len());
841+
self.interpret_allocs_inverse.push(*alloc_id);
842+
assert!(self.interpret_allocs.insert(*alloc_id, idx).is_none());
843+
idx
844+
} else {
845+
self.interpret_allocs[alloc_id]
827846
};
828-
interpret::specialized_encode_alloc_id(
829-
self,
830-
tcx,
831-
*alloc_id,
832-
shorthand,
833-
)
847+
848+
index.encode(self)
834849
}
835850
}
836851

0 commit comments

Comments
 (0)