Skip to content

Commit 62c0501

Browse files
committed
Stop referring to statics' AllocIds directly
1 parent a67ded0 commit 62c0501

File tree

7 files changed

+68
-162
lines changed

7 files changed

+68
-162
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
416416
ty::tls::with_opt(|tcx| {
417417
trace!("hashing {:?}", *self);
418418
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
419-
if let Some(def_id) = tcx.interpret_interner
420-
.get_corresponding_static_def_id(*self) {
419+
if let Some(def_id) = tcx.interpret_interner.get_static(*self) {
421420
AllocDiscriminant::Static.hash_stable(hcx, hasher);
422421
trace!("hashing {:?} as static {:?}", *self, def_id);
423422
def_id.hash_stable(hcx, hasher);

src/librustc/mir/interpret/mod.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
158158
enum AllocKind {
159159
Alloc,
160160
Fn,
161-
ExternStatic,
161+
Static,
162162
}
163163

164164
pub fn specialized_encode_alloc_id<
@@ -173,17 +173,13 @@ pub fn specialized_encode_alloc_id<
173173
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
174174
AllocKind::Alloc.encode(encoder)?;
175175
alloc.encode(encoder)?;
176-
// encode whether this allocation is the root allocation of a static
177-
tcx.interpret_interner
178-
.get_corresponding_static_def_id(alloc_id)
179-
.encode(encoder)?;
180176
} else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
181177
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
182178
AllocKind::Fn.encode(encoder)?;
183179
fn_instance.encode(encoder)?;
184-
} else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
185-
// extern "C" statics don't have allocations, just encode its def_id
186-
AllocKind::ExternStatic.encode(encoder)?;
180+
} else if let Some(did) = tcx.interpret_interner.get_static(alloc_id) {
181+
// referring to statics doesn't need to know about their allocations, just hash the DefId
182+
AllocKind::Static.encode(encoder)?;
187183
did.encode(encoder)?;
188184
} else {
189185
bug!("alloc id without corresponding allocation: {}", alloc_id);
@@ -212,10 +208,6 @@ pub fn specialized_decode_alloc_id<
212208
let allocation = tcx.intern_const_alloc(allocation);
213209
tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
214210

215-
if let Some(glob) = Option::<DefId>::decode(decoder)? {
216-
tcx.interpret_interner.cache(glob, alloc_id);
217-
}
218-
219211
Ok(alloc_id)
220212
},
221213
AllocKind::Fn => {
@@ -227,12 +219,11 @@ pub fn specialized_decode_alloc_id<
227219
cache(decoder, id);
228220
Ok(id)
229221
},
230-
AllocKind::ExternStatic => {
222+
AllocKind::Static => {
231223
trace!("creating extern static alloc id at");
232224
let did = DefId::decode(decoder)?;
233-
let alloc_id = tcx.interpret_interner.reserve();
225+
let alloc_id = tcx.interpret_interner.cache_static(did);
234226
cache(decoder, alloc_id);
235-
tcx.interpret_interner.cache(did, alloc_id);
236227
Ok(alloc_id)
237228
},
238229
}

src/librustc/ty/context.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -956,18 +956,16 @@ struct InterpretInternerInner<'tcx> {
956956
/// Allows obtaining const allocs via a unique identifier
957957
alloc_by_id: FxHashMap<interpret::AllocId, &'tcx interpret::Allocation>,
958958

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

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

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

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

1004-
pub fn get_cached(
1005-
&self,
1006-
static_id: DefId,
1007-
) -> Option<interpret::AllocId> {
1008-
self.inner.borrow().alloc_cache.get(&static_id).cloned()
1009-
}
1010-
1011-
pub fn cache(
1002+
pub fn cache_static(
10121003
&self,
10131004
static_id: DefId,
1014-
alloc_id: interpret::AllocId,
1015-
) {
1016-
let mut inner = self.inner.borrow_mut();
1017-
inner.global_cache.insert(alloc_id, static_id);
1018-
if let Some(old) = inner.alloc_cache.insert(static_id, alloc_id) {
1019-
bug!("tried to cache {:?}, but was already existing as {:#?}", static_id, old);
1005+
) -> interpret::AllocId {
1006+
if let Some(alloc_id) = self.inner.borrow().static_cache.get(&static_id).cloned() {
1007+
return alloc_id;
10201008
}
1009+
let alloc_id = self.reserve();
1010+
let mut inner = self.inner.borrow_mut();
1011+
inner.static_cache.insert(static_id, alloc_id);
1012+
inner.statics.insert(alloc_id, static_id);
1013+
alloc_id
10211014
}
10221015

1023-
pub fn get_corresponding_static_def_id(
1016+
pub fn get_static(
10241017
&self,
10251018
ptr: interpret::AllocId,
10261019
) -> Option<DefId> {
1027-
self.inner.borrow().global_cache.get(&ptr).cloned()
1020+
self.inner.borrow().statics.get(&ptr).cloned()
10281021
}
10291022

10301023
pub fn intern_at_reserved(

src/librustc_mir/interpret/const_eval.rs

Lines changed: 31 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc::mir;
55
use rustc::ty::{self, TyCtxt, Ty, Instance};
66
use rustc::ty::layout::{self, LayoutOf};
77
use rustc::ty::subst::Subst;
8-
use rustc::util::nodemap::FxHashSet;
98

109
use syntax::ast::Mutability;
1110
use syntax::codemap::Span;
@@ -110,53 +109,38 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
110109
}
111110
span = mir.span;
112111
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
113-
let alloc = tcx.interpret_interner.get_cached(cid.instance.def_id());
114-
let is_static = tcx.is_static(cid.instance.def_id()).is_some();
115-
let alloc = match alloc {
116-
Some(alloc) => {
117-
assert!(cid.promoted.is_none());
118-
assert!(param_env.caller_bounds.is_empty());
119-
alloc
120-
},
121-
None => {
122-
assert!(!layout.is_unsized());
123-
let ptr = ecx.memory.allocate(
124-
layout.size.bytes(),
125-
layout.align,
126-
None,
127-
)?;
128-
if is_static {
129-
tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id);
130-
}
131-
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
132-
let mutability = tcx.is_static(cid.instance.def_id());
133-
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
134-
Mutability::Mutable
135-
} else {
136-
Mutability::Immutable
137-
};
138-
let cleanup = StackPopCleanup::MarkStatic(mutability);
139-
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
140-
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
141-
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
142-
assert!(mir.arg_count == 0);
143-
ecx.push_stack_frame(
144-
cid.instance,
145-
mir.span,
146-
mir,
147-
Place::from_ptr(ptr, layout.align),
148-
cleanup,
149-
)?;
150-
151-
while ecx.step()? {}
152-
ptr.alloc_id
153-
}
112+
assert!(!layout.is_unsized());
113+
let ptr = ecx.memory.allocate(
114+
layout.size.bytes(),
115+
layout.align,
116+
None,
117+
)?;
118+
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
119+
let mutability = tcx.is_static(cid.instance.def_id());
120+
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
121+
Mutability::Mutable
122+
} else {
123+
Mutability::Immutable
154124
};
155-
let ptr = MemoryPointer::new(alloc, 0).into();
125+
let cleanup = StackPopCleanup::MarkStatic(mutability);
126+
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
127+
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
128+
trace!("const_eval: pushing stack frame for global: {}{}", name, prom);
129+
assert!(mir.arg_count == 0);
130+
ecx.push_stack_frame(
131+
cid.instance,
132+
mir.span,
133+
mir,
134+
Place::from_ptr(ptr, layout.align),
135+
cleanup,
136+
)?;
137+
138+
while ecx.step()? {}
139+
let ptr = ptr.into();
156140
// always try to read the value and report errors
157141
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
158142
// if it's a constant (so it needs no address, directly compute its value)
159-
Some(val) if !is_static => val,
143+
Some(val) if tcx.is_static(cid.instance.def_id()).is_none() => val,
160144
// point at the allocation
161145
_ => Value::ByRef(ptr, layout.align),
162146
};
@@ -340,21 +324,10 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
340324
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
341325
cid: GlobalId<'tcx>,
342326
) -> EvalResult<'tcx, AllocId> {
343-
let alloc = ecx
344-
.tcx
345-
.interpret_interner
346-
.get_cached(cid.instance.def_id());
347-
// Don't evaluate when already cached to prevent cycles
348-
if let Some(alloc) = alloc {
349-
return Ok(alloc)
350-
}
351-
// ensure the static is computed
352-
ecx.const_eval(cid)?;
353327
Ok(ecx
354328
.tcx
355329
.interpret_interner
356-
.get_cached(cid.instance.def_id())
357-
.expect("uncached static"))
330+
.cache_static(cid.instance.def_id()))
358331
}
359332

360333
fn box_alloc<'a>(
@@ -460,16 +433,7 @@ pub fn const_eval_provider<'a, 'tcx>(
460433
let def_id = cid.instance.def.def_id();
461434

462435
if tcx.is_foreign_item(def_id) {
463-
let id = tcx.interpret_interner.get_cached(def_id);
464-
let id = match id {
465-
// FIXME: due to caches this shouldn't happen, add some assertions
466-
Some(id) => id,
467-
None => {
468-
let id = tcx.interpret_interner.reserve();
469-
tcx.interpret_interner.cache(def_id, id);
470-
id
471-
},
472-
};
436+
let id = tcx.interpret_interner.cache_static(def_id);
473437
let ty = tcx.type_of(def_id);
474438
let layout = tcx.layout_of(key.param_env.and(ty)).unwrap();
475439
let ptr = MemoryPointer::new(id, 0);
@@ -505,13 +469,7 @@ pub fn const_eval_provider<'a, 'tcx>(
505469
};
506470

507471
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
508-
res.map(|(miri_value, ptr, miri_ty)| {
509-
if tcx.is_static(def_id).is_some() {
510-
if let Ok(ptr) = ptr.primval.to_ptr() {
511-
let mut seen = FxHashSet::default();
512-
create_depgraph_edges(tcx, ptr.alloc_id, &mut seen);
513-
}
514-
}
472+
res.map(|(miri_value, _, miri_ty)| {
515473
tcx.mk_const(ty::Const {
516474
val: ConstVal::Value(miri_value),
517475
ty: miri_ty,
@@ -528,35 +486,3 @@ pub fn const_eval_provider<'a, 'tcx>(
528486
}
529487
})
530488
}
531-
532-
// This function creates dep graph edges from statics to all referred to statics.
533-
// This is necessary, because the `const_eval` query cannot directly call itself
534-
// for other statics, because we cannot prevent recursion in queries.
535-
//
536-
// see test/incremental/static_refering_to_other_static2/issue.rs for an example
537-
// where not creating those edges would cause static A, which refers to static B
538-
// to point to the old allocation of static B, even though B has changed.
539-
//
540-
// In the future we will want to remove this funcion in favour of a system that
541-
// makes sure that statics don't need to have edges to other statics as long as
542-
// they are only referring by reference and not inspecting the other static's body.
543-
fn create_depgraph_edges<'a, 'tcx>(
544-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
545-
alloc_id: AllocId,
546-
seen: &mut FxHashSet<AllocId>,
547-
) {
548-
trace!("create_depgraph_edges: {:?}, {:?}", alloc_id, seen);
549-
if seen.insert(alloc_id) {
550-
trace!("seen: {:?}, {:?}", alloc_id, seen);
551-
if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
552-
trace!("get_alloc: {:?}, {:?}, {:?}", alloc_id, seen, alloc);
553-
for (_, &reloc) in &alloc.relocations {
554-
if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(reloc) {
555-
trace!("get_corresponding: {:?}, {:?}, {:?}, {:?}, {:?}", alloc_id, seen, alloc, did, reloc);
556-
let _ = tcx.maybe_optimized_mir(did);
557-
}
558-
create_depgraph_edges(tcx, reloc, seen);
559-
}
560-
}
561-
}
562-
}

src/librustc_mir/interpret/eval_context.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -938,16 +938,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
938938
}
939939

940940
pub fn read_global_as_value(&self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
941-
if gid.promoted.is_none() {
942-
let cached = self
941+
if self.tcx.is_static(gid.instance.def_id()).is_some() {
942+
let alloc_id = self
943943
.tcx
944944
.interpret_interner
945-
.get_cached(gid.instance.def_id());
946-
if let Some(alloc_id) = cached {
947-
let layout = self.layout_of(ty)?;
948-
let ptr = MemoryPointer::new(alloc_id, 0);
949-
return Ok(Value::ByRef(ptr.into(), layout.align))
950-
}
945+
.cache_static(gid.instance.def_id());
946+
let layout = self.layout_of(ty)?;
947+
let ptr = MemoryPointer::new(alloc_id, 0);
948+
return Ok(Value::ByRef(ptr.into(), layout.align))
951949
}
952950
let cv = self.const_eval(gid)?;
953951
self.const_to_value(&cv.val, ty)

src/librustc_mir/monomorphize/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ fn collect_miri<'a, 'tcx>(
11421142
alloc_id: AllocId,
11431143
output: &mut Vec<MonoItem<'tcx>>,
11441144
) {
1145-
if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
1145+
if let Some(did) = tcx.interpret_interner.get_static(alloc_id) {
11461146
let instance = Instance::mono(tcx, did);
11471147
if should_monomorphize_locally(tcx, &instance) {
11481148
trace!("collecting static {:?}", did);

src/librustc_trans/mir/constant.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn primval_to_llvm(cx: &CodegenCx,
5050
let static_ = cx
5151
.tcx
5252
.interpret_interner
53-
.get_corresponding_static_def_id(ptr.alloc_id);
53+
.get_static(ptr.alloc_id);
5454
let base_addr = if let Some(def_id) = static_ {
5555
assert!(cx.tcx.is_static(def_id).is_some());
5656
consts::get_static(cx, def_id)
@@ -126,18 +126,17 @@ pub fn trans_static_initializer<'a, 'tcx>(
126126
promoted: None
127127
};
128128
let param_env = ty::ParamEnv::reveal_all();
129-
cx.tcx.const_eval(param_env.and(cid))?;
129+
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
130130

131-
let alloc_id = cx
132-
.tcx
133-
.interpret_interner
134-
.get_cached(def_id)
135-
.expect("global not cached");
131+
let ptr = match static_.val {
132+
ConstVal::Value(MiriValue::ByRef(ptr, _)) => ptr,
133+
_ => bug!("static const eval returned {:#?}", static_),
134+
};
136135

137136
let alloc = cx
138137
.tcx
139138
.interpret_interner
140-
.get_alloc(alloc_id)
139+
.get_alloc(ptr.primval.to_ptr().expect("static has integer pointer").alloc_id)
141140
.expect("miri allocation never successfully created");
142141
Ok(global_initializer(cx, alloc))
143142
}

0 commit comments

Comments
 (0)