Skip to content

Commit

Permalink
Auto merge of #49833 - oli-obk:incremental_miri_regression, r=michael…
Browse files Browse the repository at this point in the history
…woerister

Don't recurse into allocations, use a global table instead

r? @michaelwoerister

fixes #49663
  • Loading branch information
bors committed Apr 15, 2018
2 parents 602b395 + 7f7d4c3 commit 7360d6d
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 307 deletions.
23 changes: 12 additions & 11 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,12 @@ impl_stable_hash_for!(struct mir::interpret::MemoryPointer {

enum AllocDiscriminant {
Alloc,
ExternStatic,
Static,
Function,
}
impl_stable_hash_for!(enum self::AllocDiscriminant {
Alloc,
ExternStatic,
Static,
Function
});

Expand All @@ -414,24 +414,25 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
hasher: &mut StableHasher<W>,
) {
ty::tls::with_opt(|tcx| {
trace!("hashing {:?}", *self);
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_static(*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);
if hcx.alloc_id_recursion_tracker.insert(*self) {
tcx
.interpret_interner
.get_corresponding_static_def_id(*self)
.hash_stable(hcx, hasher);
trace!("hashing {:?} as alloc {:#?}", *self, alloc);
alloc.hash_stable(hcx, hasher);
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) {
trace!("hashing {:?} as fn {:#?}", *self, inst);
AllocDiscriminant::Function.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 {
bug!("no allocation for {}", self);
}
Expand Down
63 changes: 23 additions & 40 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ pub struct AllocId(pub u64);
impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}

pub const ALLOC_DISCRIMINANT: usize = 0;
pub const FN_DISCRIMINANT: usize = 1;
pub const EXTERN_STATIC_DISCRIMINANT: usize = 2;
pub const SHORTHAND_START: usize = 3;
#[derive(RustcDecodable, RustcEncodable)]
enum AllocKind {
Alloc,
Fn,
Static,
}

pub fn specialized_encode_alloc_id<
'a, 'tcx,
Expand All @@ -166,26 +168,18 @@ pub fn specialized_encode_alloc_id<
encoder: &mut E,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
alloc_id: AllocId,
shorthand: Option<usize>,
) -> Result<(), E::Error> {
if let Some(shorthand) = shorthand {
return shorthand.encode(encoder);
}
if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
ALLOC_DISCRIMINANT.encode(encoder)?;
AllocKind::Alloc.encode(encoder)?;
alloc.encode(encoder)?;
// encode whether this allocation is the root allocation of a static
tcx.interpret_interner
.get_corresponding_static_def_id(alloc_id)
.encode(encoder)?;
} else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
FN_DISCRIMINANT.encode(encoder)?;
AllocKind::Fn.encode(encoder)?;
fn_instance.encode(encoder)?;
} 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_STATIC_DISCRIMINANT.encode(encoder)?;
} else if let Some(did) = tcx.interpret_interner.get_static(alloc_id) {
// referring to statics doesn't need to know about their allocations, just about its DefId
AllocKind::Static.encode(encoder)?;
did.encode(encoder)?;
} else {
bug!("alloc id without corresponding allocation: {}", alloc_id);
Expand All @@ -196,53 +190,42 @@ pub fn specialized_encode_alloc_id<
pub fn specialized_decode_alloc_id<
'a, 'tcx,
D: Decoder,
CACHE: FnOnce(&mut D, usize, AllocId),
SHORT: FnOnce(&mut D, usize) -> Result<AllocId, D::Error>
CACHE: FnOnce(&mut D, AllocId),
>(
decoder: &mut D,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
pos: usize,
cache: CACHE,
short: SHORT,
) -> Result<AllocId, D::Error> {
match usize::decode(decoder)? {
ALLOC_DISCRIMINANT => {
match AllocKind::decode(decoder)? {
AllocKind::Alloc => {
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
cache(decoder, pos, alloc_id);
cache(decoder, alloc_id);

let allocation = Allocation::decode(decoder)?;
trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
let allocation = tcx.intern_const_alloc(allocation);
tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);

if let Some(glob) = Option::<DefId>::decode(decoder)? {
tcx.interpret_interner.cache(glob, alloc_id);
}

Ok(alloc_id)
},
FN_DISCRIMINANT => {
trace!("creating fn alloc id at {}", pos);
AllocKind::Fn => {
trace!("creating fn alloc id");
let instance = ty::Instance::decode(decoder)?;
trace!("decoded fn alloc instance: {:?}", instance);
let id = tcx.interpret_interner.create_fn_alloc(instance);
trace!("created fn alloc id: {:?}", id);
cache(decoder, pos, id);
cache(decoder, id);
Ok(id)
},
EXTERN_STATIC_DISCRIMINANT => {
trace!("creating extern static alloc id at {}", pos);
AllocKind::Static => {
trace!("creating extern static alloc id at");
let did = DefId::decode(decoder)?;
let alloc_id = tcx.interpret_interner.reserve();
tcx.interpret_interner.cache(did, alloc_id);
let alloc_id = tcx.interpret_interner.cache_static(did);
cache(decoder, alloc_id);
Ok(alloc_id)
},
shorthand => {
trace!("loading shorthand {}", shorthand);
short(decoder, shorthand)
},
}
}

Expand Down
39 changes: 16 additions & 23 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,18 +956,16 @@ struct InterpretInternerInner<'tcx> {
/// Allows obtaining const allocs via a unique identifier
alloc_by_id: FxHashMap<interpret::AllocId, &'tcx interpret::Allocation>,

/// Reverse map of `alloc_cache`
global_cache: FxHashMap<interpret::AllocId, DefId>,
/// Allows obtaining static def ids via a unique id
statics: FxHashMap<interpret::AllocId, DefId>,

/// The AllocId to assign to the next new regular allocation.
/// Always incremented, never gets smaller.
next_id: interpret::AllocId,

/// Allows checking whether a static already has an allocation
///
/// This is only important for detecting statics referring to themselves
// FIXME(oli-obk) move it to the EvalContext?
alloc_cache: FxHashMap<DefId, interpret::AllocId>,
/// Inverse map of `statics`
/// Used so we don't allocate a new pointer every time we need one
static_cache: FxHashMap<DefId, interpret::AllocId>,

/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
/// allocations for string and bytestring literals.
Expand Down Expand Up @@ -1001,30 +999,25 @@ impl<'tcx> InterpretInterner<'tcx> {
self.inner.borrow().alloc_by_id.get(&id).cloned()
}

pub fn get_cached(
&self,
static_id: DefId,
) -> Option<interpret::AllocId> {
self.inner.borrow().alloc_cache.get(&static_id).cloned()
}

pub fn cache(
pub fn cache_static(
&self,
static_id: DefId,
alloc_id: interpret::AllocId,
) {
let mut inner = self.inner.borrow_mut();
inner.global_cache.insert(alloc_id, static_id);
if let Some(old) = inner.alloc_cache.insert(static_id, alloc_id) {
bug!("tried to cache {:?}, but was already existing as {:#?}", static_id, old);
) -> interpret::AllocId {
if let Some(alloc_id) = self.inner.borrow().static_cache.get(&static_id).cloned() {
return alloc_id;
}
let alloc_id = self.reserve();
let mut inner = self.inner.borrow_mut();
inner.static_cache.insert(static_id, alloc_id);
inner.statics.insert(alloc_id, static_id);
alloc_id
}

pub fn get_corresponding_static_def_id(
pub fn get_static(
&self,
ptr: interpret::AllocId,
) -> Option<DefId> {
self.inner.borrow().global_cache.get(&ptr).cloned()
self.inner.borrow().statics.get(&ptr).cloned()
}

pub fn intern_at_reserved(
Expand Down
Loading

0 comments on commit 7360d6d

Please sign in to comment.