mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-18 10:38:11 +00:00
Don't recurse into allocations, use a global table instead
This commit is contained in:
parent
fb730d75d4
commit
a67ded06a3
@ -398,12 +398,12 @@ impl_stable_hash_for!(struct mir::interpret::MemoryPointer {
|
|||||||
|
|
||||||
enum AllocDiscriminant {
|
enum AllocDiscriminant {
|
||||||
Alloc,
|
Alloc,
|
||||||
ExternStatic,
|
Static,
|
||||||
Function,
|
Function,
|
||||||
}
|
}
|
||||||
impl_stable_hash_for!(enum self::AllocDiscriminant {
|
impl_stable_hash_for!(enum self::AllocDiscriminant {
|
||||||
Alloc,
|
Alloc,
|
||||||
ExternStatic,
|
Static,
|
||||||
Function
|
Function
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -414,24 +414,26 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
|
|||||||
hasher: &mut StableHasher<W>,
|
hasher: &mut StableHasher<W>,
|
||||||
) {
|
) {
|
||||||
ty::tls::with_opt(|tcx| {
|
ty::tls::with_opt(|tcx| {
|
||||||
|
trace!("hashing {:?}", *self);
|
||||||
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
|
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
|
||||||
if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
|
if let Some(def_id) = tcx.interpret_interner
|
||||||
|
.get_corresponding_static_def_id(*self) {
|
||||||
|
AllocDiscriminant::Static.hash_stable(hcx, hasher);
|
||||||
|
trace!("hashing {:?} as static {:?}", *self, def_id);
|
||||||
|
def_id.hash_stable(hcx, hasher);
|
||||||
|
} else if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
|
||||||
AllocDiscriminant::Alloc.hash_stable(hcx, hasher);
|
AllocDiscriminant::Alloc.hash_stable(hcx, hasher);
|
||||||
if hcx.alloc_id_recursion_tracker.insert(*self) {
|
if hcx.alloc_id_recursion_tracker.insert(*self) {
|
||||||
tcx
|
trace!("hashing {:?} as alloc {:#?}", *self, alloc);
|
||||||
.interpret_interner
|
|
||||||
.get_corresponding_static_def_id(*self)
|
|
||||||
.hash_stable(hcx, hasher);
|
|
||||||
alloc.hash_stable(hcx, hasher);
|
alloc.hash_stable(hcx, hasher);
|
||||||
assert!(hcx.alloc_id_recursion_tracker.remove(self));
|
assert!(hcx.alloc_id_recursion_tracker.remove(self));
|
||||||
|
} else {
|
||||||
|
trace!("skipping hashing of {:?} due to recursion", *self);
|
||||||
}
|
}
|
||||||
} else if let Some(inst) = tcx.interpret_interner.get_fn(*self) {
|
} else if let Some(inst) = tcx.interpret_interner.get_fn(*self) {
|
||||||
|
trace!("hashing {:?} as fn {:#?}", *self, inst);
|
||||||
AllocDiscriminant::Function.hash_stable(hcx, hasher);
|
AllocDiscriminant::Function.hash_stable(hcx, hasher);
|
||||||
inst.hash_stable(hcx, hasher);
|
inst.hash_stable(hcx, hasher);
|
||||||
} else if let Some(def_id) = tcx.interpret_interner
|
|
||||||
.get_corresponding_static_def_id(*self) {
|
|
||||||
AllocDiscriminant::ExternStatic.hash_stable(hcx, hasher);
|
|
||||||
def_id.hash_stable(hcx, hasher);
|
|
||||||
} else {
|
} else {
|
||||||
bug!("no allocation for {}", self);
|
bug!("no allocation for {}", self);
|
||||||
}
|
}
|
||||||
|
@ -154,10 +154,12 @@ pub struct AllocId(pub u64);
|
|||||||
impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
|
impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
|
||||||
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
|
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
|
||||||
|
|
||||||
pub const ALLOC_DISCRIMINANT: usize = 0;
|
#[derive(RustcDecodable, RustcEncodable)]
|
||||||
pub const FN_DISCRIMINANT: usize = 1;
|
enum AllocKind {
|
||||||
pub const EXTERN_STATIC_DISCRIMINANT: usize = 2;
|
Alloc,
|
||||||
pub const SHORTHAND_START: usize = 3;
|
Fn,
|
||||||
|
ExternStatic,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn specialized_encode_alloc_id<
|
pub fn specialized_encode_alloc_id<
|
||||||
'a, 'tcx,
|
'a, 'tcx,
|
||||||
@ -166,14 +168,10 @@ pub fn specialized_encode_alloc_id<
|
|||||||
encoder: &mut E,
|
encoder: &mut E,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
shorthand: Option<usize>,
|
|
||||||
) -> Result<(), E::Error> {
|
) -> Result<(), E::Error> {
|
||||||
if let Some(shorthand) = shorthand {
|
|
||||||
return shorthand.encode(encoder);
|
|
||||||
}
|
|
||||||
if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
|
if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
|
||||||
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
|
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
|
||||||
ALLOC_DISCRIMINANT.encode(encoder)?;
|
AllocKind::Alloc.encode(encoder)?;
|
||||||
alloc.encode(encoder)?;
|
alloc.encode(encoder)?;
|
||||||
// encode whether this allocation is the root allocation of a static
|
// encode whether this allocation is the root allocation of a static
|
||||||
tcx.interpret_interner
|
tcx.interpret_interner
|
||||||
@ -181,11 +179,11 @@ pub fn specialized_encode_alloc_id<
|
|||||||
.encode(encoder)?;
|
.encode(encoder)?;
|
||||||
} else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
|
} else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
|
||||||
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
|
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
|
||||||
FN_DISCRIMINANT.encode(encoder)?;
|
AllocKind::Fn.encode(encoder)?;
|
||||||
fn_instance.encode(encoder)?;
|
fn_instance.encode(encoder)?;
|
||||||
} else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
|
} else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
|
||||||
// extern "C" statics don't have allocations, just encode its def_id
|
// extern "C" statics don't have allocations, just encode its def_id
|
||||||
EXTERN_STATIC_DISCRIMINANT.encode(encoder)?;
|
AllocKind::ExternStatic.encode(encoder)?;
|
||||||
did.encode(encoder)?;
|
did.encode(encoder)?;
|
||||||
} else {
|
} else {
|
||||||
bug!("alloc id without corresponding allocation: {}", alloc_id);
|
bug!("alloc id without corresponding allocation: {}", alloc_id);
|
||||||
@ -196,21 +194,18 @@ pub fn specialized_encode_alloc_id<
|
|||||||
pub fn specialized_decode_alloc_id<
|
pub fn specialized_decode_alloc_id<
|
||||||
'a, 'tcx,
|
'a, 'tcx,
|
||||||
D: Decoder,
|
D: Decoder,
|
||||||
CACHE: FnOnce(&mut D, usize, AllocId),
|
CACHE: FnOnce(&mut D, AllocId),
|
||||||
SHORT: FnOnce(&mut D, usize) -> Result<AllocId, D::Error>
|
|
||||||
>(
|
>(
|
||||||
decoder: &mut D,
|
decoder: &mut D,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
pos: usize,
|
|
||||||
cache: CACHE,
|
cache: CACHE,
|
||||||
short: SHORT,
|
|
||||||
) -> Result<AllocId, D::Error> {
|
) -> Result<AllocId, D::Error> {
|
||||||
match usize::decode(decoder)? {
|
match AllocKind::decode(decoder)? {
|
||||||
ALLOC_DISCRIMINANT => {
|
AllocKind::Alloc => {
|
||||||
let alloc_id = tcx.interpret_interner.reserve();
|
let alloc_id = tcx.interpret_interner.reserve();
|
||||||
trace!("creating alloc id {:?} at {}", alloc_id, pos);
|
trace!("creating alloc id {:?}", alloc_id);
|
||||||
// insert early to allow recursive allocs
|
// insert early to allow recursive allocs
|
||||||
cache(decoder, pos, alloc_id);
|
cache(decoder, alloc_id);
|
||||||
|
|
||||||
let allocation = Allocation::decode(decoder)?;
|
let allocation = Allocation::decode(decoder)?;
|
||||||
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
|
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
|
||||||
@ -223,26 +218,23 @@ pub fn specialized_decode_alloc_id<
|
|||||||
|
|
||||||
Ok(alloc_id)
|
Ok(alloc_id)
|
||||||
},
|
},
|
||||||
FN_DISCRIMINANT => {
|
AllocKind::Fn => {
|
||||||
trace!("creating fn alloc id at {}", pos);
|
trace!("creating fn alloc id");
|
||||||
let instance = ty::Instance::decode(decoder)?;
|
let instance = ty::Instance::decode(decoder)?;
|
||||||
trace!("decoded fn alloc instance: {:?}", instance);
|
trace!("decoded fn alloc instance: {:?}", instance);
|
||||||
let id = tcx.interpret_interner.create_fn_alloc(instance);
|
let id = tcx.interpret_interner.create_fn_alloc(instance);
|
||||||
trace!("created fn alloc id: {:?}", id);
|
trace!("created fn alloc id: {:?}", id);
|
||||||
cache(decoder, pos, id);
|
cache(decoder, id);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
},
|
},
|
||||||
EXTERN_STATIC_DISCRIMINANT => {
|
AllocKind::ExternStatic => {
|
||||||
trace!("creating extern static alloc id at {}", pos);
|
trace!("creating extern static alloc id at");
|
||||||
let did = DefId::decode(decoder)?;
|
let did = DefId::decode(decoder)?;
|
||||||
let alloc_id = tcx.interpret_interner.reserve();
|
let alloc_id = tcx.interpret_interner.reserve();
|
||||||
|
cache(decoder, alloc_id);
|
||||||
tcx.interpret_interner.cache(did, alloc_id);
|
tcx.interpret_interner.cache(did, alloc_id);
|
||||||
Ok(alloc_id)
|
Ok(alloc_id)
|
||||||
},
|
},
|
||||||
shorthand => {
|
|
||||||
trace!("loading shorthand {}", shorthand);
|
|
||||||
short(decoder, shorthand)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +77,11 @@ pub struct OnDiskCache<'sess> {
|
|||||||
// `serialized_data`.
|
// `serialized_data`.
|
||||||
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
||||||
|
|
||||||
// A cache to ensure we don't read allocations twice
|
// Alloc indices to memory location map
|
||||||
interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
|
prev_interpret_alloc_index: Vec<AbsoluteBytePos>,
|
||||||
|
|
||||||
// A map from positions to size of the serialized allocation
|
/// Deserialization: A cache to ensure we don't read allocations twice
|
||||||
// so we can skip over already processed allocations
|
interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
|
||||||
interpret_alloc_size: RefCell<FxHashMap<usize, usize>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This type is used only for (de-)serialization.
|
// This type is used only for (de-)serialization.
|
||||||
@ -92,6 +91,8 @@ struct Footer {
|
|||||||
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
|
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
|
||||||
query_result_index: EncodedQueryResultIndex,
|
query_result_index: EncodedQueryResultIndex,
|
||||||
diagnostics_index: EncodedQueryResultIndex,
|
diagnostics_index: EncodedQueryResultIndex,
|
||||||
|
// the location of all allocations
|
||||||
|
interpret_alloc_index: Vec<AbsoluteBytePos>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
|
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
|
||||||
@ -148,8 +149,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
query_result_index: footer.query_result_index.into_iter().collect(),
|
query_result_index: footer.query_result_index.into_iter().collect(),
|
||||||
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
|
prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
|
||||||
synthetic_expansion_infos: Lock::new(FxHashMap()),
|
synthetic_expansion_infos: Lock::new(FxHashMap()),
|
||||||
|
prev_interpret_alloc_index: footer.interpret_alloc_index,
|
||||||
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
|
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
|
||||||
interpret_alloc_size: RefCell::new(FxHashMap::default()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +166,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
query_result_index: FxHashMap(),
|
query_result_index: FxHashMap(),
|
||||||
prev_diagnostics_index: FxHashMap(),
|
prev_diagnostics_index: FxHashMap(),
|
||||||
synthetic_expansion_infos: Lock::new(FxHashMap()),
|
synthetic_expansion_infos: Lock::new(FxHashMap()),
|
||||||
|
prev_interpret_alloc_index: Vec::new(),
|
||||||
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
|
interpret_alloc_cache: RefCell::new(FxHashMap::default()),
|
||||||
interpret_alloc_size: RefCell::new(FxHashMap::default()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +200,9 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
type_shorthands: FxHashMap(),
|
type_shorthands: FxHashMap(),
|
||||||
predicate_shorthands: FxHashMap(),
|
predicate_shorthands: FxHashMap(),
|
||||||
expn_info_shorthands: FxHashMap(),
|
expn_info_shorthands: FxHashMap(),
|
||||||
interpret_alloc_shorthands: FxHashMap(),
|
interpret_allocs: FxHashMap(),
|
||||||
|
interpret_alloc_ids: FxHashSet(),
|
||||||
|
interpret_allocs_inverse: Vec::new(),
|
||||||
codemap: CachingCodemapView::new(tcx.sess.codemap()),
|
codemap: CachingCodemapView::new(tcx.sess.codemap()),
|
||||||
file_to_file_index,
|
file_to_file_index,
|
||||||
};
|
};
|
||||||
@ -277,6 +280,31 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
diagnostics_index
|
diagnostics_index
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let interpret_alloc_index = {
|
||||||
|
let mut interpret_alloc_index = Vec::new();
|
||||||
|
let mut n = 0;
|
||||||
|
loop {
|
||||||
|
let new_n = encoder.interpret_alloc_ids.len();
|
||||||
|
for idx in n..new_n {
|
||||||
|
let id = encoder.interpret_allocs_inverse[idx];
|
||||||
|
let pos = AbsoluteBytePos::new(encoder.position());
|
||||||
|
interpret_alloc_index.push(pos);
|
||||||
|
interpret::specialized_encode_alloc_id(
|
||||||
|
&mut encoder,
|
||||||
|
tcx,
|
||||||
|
id,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
// if we have found new ids, serialize those, too
|
||||||
|
if n == new_n {
|
||||||
|
// otherwise, abort
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n = new_n;
|
||||||
|
}
|
||||||
|
interpret_alloc_index
|
||||||
|
};
|
||||||
|
|
||||||
let sorted_cnums = sorted_cnums_including_local_crate(tcx);
|
let sorted_cnums = sorted_cnums_including_local_crate(tcx);
|
||||||
let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
|
let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
|
||||||
let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
|
let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
|
||||||
@ -291,6 +319,7 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
prev_cnums,
|
prev_cnums,
|
||||||
query_result_index,
|
query_result_index,
|
||||||
diagnostics_index,
|
diagnostics_index,
|
||||||
|
interpret_alloc_index,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Encode the position of the footer as the last 8 bytes of the
|
// Encode the position of the footer as the last 8 bytes of the
|
||||||
@ -396,8 +425,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
file_index_to_file: &self.file_index_to_file,
|
file_index_to_file: &self.file_index_to_file,
|
||||||
file_index_to_stable_id: &self.file_index_to_stable_id,
|
file_index_to_stable_id: &self.file_index_to_stable_id,
|
||||||
synthetic_expansion_infos: &self.synthetic_expansion_infos,
|
synthetic_expansion_infos: &self.synthetic_expansion_infos,
|
||||||
|
prev_interpret_alloc_index: &self.prev_interpret_alloc_index,
|
||||||
interpret_alloc_cache: &self.interpret_alloc_cache,
|
interpret_alloc_cache: &self.interpret_alloc_cache,
|
||||||
interpret_alloc_size: &self.interpret_alloc_size,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match decode_tagged(&mut decoder, dep_node_index) {
|
match decode_tagged(&mut decoder, dep_node_index) {
|
||||||
@ -460,7 +489,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
|
|||||||
file_index_to_file: &'x Lock<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
|
file_index_to_file: &'x Lock<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
|
||||||
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
|
file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
|
||||||
interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
|
interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
|
||||||
interpret_alloc_size: &'x RefCell<FxHashMap<usize, usize>>,
|
/// maps from index in the cache file to location in the cache file
|
||||||
|
prev_interpret_alloc_index: &'x [AbsoluteBytePos],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
|
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
|
||||||
@ -584,36 +614,29 @@ implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
|
|||||||
impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
|
impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
|
||||||
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
|
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let pos = TyDecoder::position(self);
|
let idx = usize::decode(self)?;
|
||||||
trace!("specialized_decode_alloc_id: {:?}", pos);
|
trace!("loading index {}", idx);
|
||||||
if let Some(cached) = self.interpret_alloc_cache.borrow().get(&pos).cloned() {
|
|
||||||
// if there's no end position we are currently deserializing a recursive
|
if let Some(cached) = self.interpret_alloc_cache.borrow().get(&idx).cloned() {
|
||||||
// allocation
|
trace!("loading alloc id {:?} from alloc_cache", cached);
|
||||||
if let Some(end) = self.interpret_alloc_size.borrow().get(&pos).cloned() {
|
return Ok(cached);
|
||||||
trace!("{} already cached as {:?}", pos, cached);
|
|
||||||
// skip ahead
|
|
||||||
self.opaque.set_position(end);
|
|
||||||
return Ok(cached)
|
|
||||||
}
|
}
|
||||||
}
|
let pos = self.prev_interpret_alloc_index[idx].to_usize();
|
||||||
let id = interpret::specialized_decode_alloc_id(
|
trace!("loading position {}", pos);
|
||||||
self,
|
self.with_position(pos, |this| {
|
||||||
|
interpret::specialized_decode_alloc_id(
|
||||||
|
this,
|
||||||
tcx,
|
tcx,
|
||||||
pos,
|
|this, alloc_id| {
|
||||||
|this, pos, alloc_id| {
|
trace!("caching idx {} for alloc id {} at position {}", idx, alloc_id, pos);
|
||||||
assert!(this.interpret_alloc_cache.borrow_mut().insert(pos, alloc_id).is_none());
|
assert!(this
|
||||||
},
|
.interpret_alloc_cache
|
||||||
|this, shorthand| {
|
|
||||||
// need to load allocation
|
|
||||||
this.with_position(shorthand, |this| interpret::AllocId::decode(this))
|
|
||||||
}
|
|
||||||
)?;
|
|
||||||
assert!(self
|
|
||||||
.interpret_alloc_size
|
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(pos, TyDecoder::position(self))
|
.insert(idx, alloc_id)
|
||||||
.is_none());
|
.is_none());
|
||||||
Ok(id)
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
|
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
|
||||||
@ -777,7 +800,9 @@ struct CacheEncoder<'enc, 'a, 'tcx, E>
|
|||||||
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
|
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
|
||||||
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||||
expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
|
expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
|
||||||
interpret_alloc_shorthands: FxHashMap<interpret::AllocId, usize>,
|
interpret_allocs: FxHashMap<interpret::AllocId, usize>,
|
||||||
|
interpret_allocs_inverse: Vec<interpret::AllocId>,
|
||||||
|
interpret_alloc_ids: FxHashSet<interpret::AllocId>,
|
||||||
codemap: CachingCodemapView<'tcx>,
|
codemap: CachingCodemapView<'tcx>,
|
||||||
file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>,
|
file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>,
|
||||||
}
|
}
|
||||||
@ -814,27 +839,17 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<
|
|||||||
where E: 'enc + ty_codec::TyEncoder
|
where E: 'enc + ty_codec::TyEncoder
|
||||||
{
|
{
|
||||||
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
|
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
|
||||||
use std::collections::hash_map::Entry;
|
let index = if self.interpret_alloc_ids.insert(*alloc_id) {
|
||||||
let tcx = self.tcx;
|
let idx = self.interpret_alloc_ids.len() - 1;
|
||||||
let pos = self.position();
|
assert_eq!(idx, self.interpret_allocs_inverse.len());
|
||||||
let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
|
self.interpret_allocs_inverse.push(*alloc_id);
|
||||||
Entry::Occupied(entry) => Some(entry.get().clone()),
|
assert!(self.interpret_allocs.insert(*alloc_id, idx).is_none());
|
||||||
Entry::Vacant(entry) => {
|
idx
|
||||||
// ensure that we don't place any AllocIds at the very beginning
|
} else {
|
||||||
// of the metadata file, because that would end up making our indices
|
self.interpret_allocs[alloc_id]
|
||||||
// not special. It is essentially impossible for that to happen,
|
|
||||||
// but let's make sure
|
|
||||||
assert!(pos >= interpret::SHORTHAND_START);
|
|
||||||
entry.insert(pos);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
interpret::specialized_encode_alloc_id(
|
|
||||||
self,
|
index.encode(self)
|
||||||
tcx,
|
|
||||||
*alloc_id,
|
|
||||||
shorthand,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
|
|||||||
|
|
||||||
// interpreter allocation cache
|
// interpreter allocation cache
|
||||||
interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
|
interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
|
||||||
// a cache for sizes of interpreter allocations
|
|
||||||
// needed to skip already deserialized allocations
|
|
||||||
interpret_alloc_size: FxHashMap<usize, usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abstract over the various ways one can create metadata decoders.
|
/// Abstract over the various ways one can create metadata decoders.
|
||||||
@ -81,7 +78,6 @@ pub trait Metadata<'a, 'tcx>: Copy {
|
|||||||
last_filemap_index: 0,
|
last_filemap_index: 0,
|
||||||
lazy_state: LazyState::NoNode,
|
lazy_state: LazyState::NoNode,
|
||||||
interpret_alloc_cache: FxHashMap::default(),
|
interpret_alloc_cache: FxHashMap::default(),
|
||||||
interpret_alloc_size: FxHashMap::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,34 +286,25 @@ impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
|
impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
|
||||||
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
|
fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
|
||||||
let tcx = self.tcx.expect("need tcx for AllocId decoding");
|
let tcx = self.tcx.unwrap();
|
||||||
let pos = self.position();
|
let idx = usize::decode(self)?;
|
||||||
if let Some(cached) = self.interpret_alloc_cache.get(&pos).cloned() {
|
|
||||||
// if there's no end position we are currently deserializing a recursive
|
if let Some(cached) = self.interpret_alloc_cache.get(&idx).cloned() {
|
||||||
// allocation
|
return Ok(cached);
|
||||||
if let Some(end) = self.interpret_alloc_size.get(&pos).cloned() {
|
|
||||||
trace!("{} already cached as {:?}", pos, cached);
|
|
||||||
// skip ahead
|
|
||||||
self.opaque.set_position(end);
|
|
||||||
return Ok(cached)
|
|
||||||
}
|
}
|
||||||
}
|
let pos = self
|
||||||
let id = interpret::specialized_decode_alloc_id(
|
.cdata()
|
||||||
self,
|
.root
|
||||||
|
.interpret_alloc_index[idx];
|
||||||
|
self.with_position(pos as usize, |this| {
|
||||||
|
interpret::specialized_decode_alloc_id(
|
||||||
|
this,
|
||||||
tcx,
|
tcx,
|
||||||
pos,
|
|this, alloc_id| {
|
||||||
|this, pos, alloc_id| { this.interpret_alloc_cache.insert(pos, alloc_id); },
|
assert!(this.interpret_alloc_cache.insert(idx, alloc_id).is_none());
|
||||||
|this, shorthand| {
|
},
|
||||||
// need to load allocation
|
)
|
||||||
this.with_position(shorthand, |this| interpret::AllocId::decode(this))
|
})
|
||||||
}
|
|
||||||
)?;
|
|
||||||
let end_pos = self.position();
|
|
||||||
assert!(self
|
|
||||||
.interpret_alloc_size
|
|
||||||
.insert(pos, end_pos)
|
|
||||||
.is_none());
|
|
||||||
Ok(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
|
|||||||
use rustc::ty::codec::{self as ty_codec, TyEncoder};
|
use rustc::ty::codec::{self as ty_codec, TyEncoder};
|
||||||
|
|
||||||
use rustc::session::config::{self, CrateTypeProcMacro};
|
use rustc::session::config::{self, CrateTypeProcMacro};
|
||||||
use rustc::util::nodemap::FxHashMap;
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use rustc_data_structures::stable_hasher::StableHasher;
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
|
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
|
||||||
@ -59,7 +59,10 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
|||||||
lazy_state: LazyState,
|
lazy_state: LazyState,
|
||||||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||||
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||||
interpret_alloc_shorthands: FxHashMap<interpret::AllocId, usize>,
|
|
||||||
|
interpret_allocs: FxHashMap<interpret::AllocId, usize>,
|
||||||
|
interpret_allocs_inverse: Vec<interpret::AllocId>,
|
||||||
|
interpret_alloc_ids: FxHashSet<interpret::AllocId>,
|
||||||
|
|
||||||
// This is used to speed up Span encoding.
|
// This is used to speed up Span encoding.
|
||||||
filemap_cache: Lrc<FileMap>,
|
filemap_cache: Lrc<FileMap>,
|
||||||
@ -196,26 +199,17 @@ impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
|
impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
|
||||||
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
|
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
|
||||||
use std::collections::hash_map::Entry;
|
let index = if self.interpret_alloc_ids.insert(*alloc_id) {
|
||||||
let tcx = self.tcx;
|
let idx = self.interpret_alloc_ids.len() - 1;
|
||||||
let pos = self.position();
|
assert_eq!(idx, self.interpret_allocs_inverse.len());
|
||||||
let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
|
self.interpret_allocs_inverse.push(*alloc_id);
|
||||||
Entry::Occupied(entry) => Some(entry.get().clone()),
|
assert!(self.interpret_allocs.insert(*alloc_id, idx).is_none());
|
||||||
Entry::Vacant(entry) => {
|
idx
|
||||||
// ensure that we don't place any AllocIds at the very beginning
|
} else {
|
||||||
// of the metadata file, because that would end up making our indices
|
self.interpret_allocs[alloc_id]
|
||||||
// not special. This is essentially impossible, but let's make sure
|
|
||||||
assert!(pos >= interpret::SHORTHAND_START);
|
|
||||||
entry.insert(pos);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
interpret::specialized_encode_alloc_id(
|
|
||||||
self,
|
index.encode(self)
|
||||||
tcx,
|
|
||||||
*alloc_id,
|
|
||||||
shorthand,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +454,33 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
let has_default_lib_allocator =
|
let has_default_lib_allocator =
|
||||||
attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator");
|
attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator");
|
||||||
let has_global_allocator = *tcx.sess.has_global_allocator.get();
|
let has_global_allocator = *tcx.sess.has_global_allocator.get();
|
||||||
|
|
||||||
|
// Encode the allocation index
|
||||||
|
let interpret_alloc_index = {
|
||||||
|
let mut interpret_alloc_index = Vec::new();
|
||||||
|
let mut n = 0;
|
||||||
|
loop {
|
||||||
|
let new_n = self.interpret_alloc_ids.len();
|
||||||
|
for idx in n..new_n {
|
||||||
|
let id = self.interpret_allocs_inverse[idx];
|
||||||
|
let pos = self.position() as u32;
|
||||||
|
interpret_alloc_index.push(pos);
|
||||||
|
interpret::specialized_encode_alloc_id(
|
||||||
|
self,
|
||||||
|
tcx,
|
||||||
|
id,
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
// if we have found new ids, serialize those, too
|
||||||
|
if n == new_n {
|
||||||
|
// otherwise, abort
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n = new_n;
|
||||||
|
}
|
||||||
|
interpret_alloc_index
|
||||||
|
};
|
||||||
|
|
||||||
let root = self.lazy(&CrateRoot {
|
let root = self.lazy(&CrateRoot {
|
||||||
name: tcx.crate_name(LOCAL_CRATE),
|
name: tcx.crate_name(LOCAL_CRATE),
|
||||||
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
|
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
|
||||||
@ -492,6 +513,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
exported_symbols,
|
exported_symbols,
|
||||||
wasm_custom_sections,
|
wasm_custom_sections,
|
||||||
index,
|
index,
|
||||||
|
interpret_alloc_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
let total_bytes = self.position();
|
let total_bytes = self.position();
|
||||||
@ -1760,7 +1782,9 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
type_shorthands: Default::default(),
|
type_shorthands: Default::default(),
|
||||||
predicate_shorthands: Default::default(),
|
predicate_shorthands: Default::default(),
|
||||||
filemap_cache: tcx.sess.codemap().files()[0].clone(),
|
filemap_cache: tcx.sess.codemap().files()[0].clone(),
|
||||||
interpret_alloc_shorthands: Default::default(),
|
interpret_allocs: Default::default(),
|
||||||
|
interpret_allocs_inverse: Default::default(),
|
||||||
|
interpret_alloc_ids: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Encode the rustc version string in a predictable location.
|
// Encode the rustc version string in a predictable location.
|
||||||
|
@ -207,6 +207,7 @@ pub struct CrateRoot {
|
|||||||
pub impls: LazySeq<TraitImpls>,
|
pub impls: LazySeq<TraitImpls>,
|
||||||
pub exported_symbols: EncodedExportedSymbols,
|
pub exported_symbols: EncodedExportedSymbols,
|
||||||
pub wasm_custom_sections: LazySeq<DefIndex>,
|
pub wasm_custom_sections: LazySeq<DefIndex>,
|
||||||
|
pub interpret_alloc_index: Vec<u32>,
|
||||||
|
|
||||||
pub index: LazySeq<index::Index>,
|
pub index: LazySeq<index::Index>,
|
||||||
}
|
}
|
||||||
|
19
src/test/incremental/static_cycle/b.rs
Normal file
19
src/test/incremental/static_cycle/b.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// revisions:rpass1 rpass2
|
||||||
|
|
||||||
|
#![cfg_attr(rpass2, warn(dead_code))]
|
||||||
|
|
||||||
|
pub static mut BAA: *const i8 = unsafe { &BOO as *const _ as *const i8 };
|
||||||
|
|
||||||
|
pub static mut BOO: *const i8 = unsafe { &BAA as *const _ as *const i8 };
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user