Skip to content

Commit 170ea65

Browse files
committed
Stop referring to statics' AllocIds directly
1 parent 2546ff8 commit 170ea65

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
@@ -398,8 +398,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
398398
ty::tls::with_opt(|tcx| {
399399
trace!("hashing {:?}", *self);
400400
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
401-
if let Some(def_id) = tcx.interpret_interner
402-
.get_corresponding_static_def_id(*self) {
401+
if let Some(def_id) = tcx.interpret_interner.get_static(*self) {
403402
AllocDiscriminant::Static.hash_stable(hcx, hasher);
404403
trace!("hashing {:?} as static {:?}", *self, def_id);
405404
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
@@ -935,18 +935,16 @@ struct InterpretInternerInner<'tcx> {
935935
/// Allows obtaining const allocs via a unique identifier
936936
alloc_by_id: FxHashMap<interpret::AllocId, &'tcx interpret::Allocation>,
937937

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

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

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

951949
/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
952950
/// allocations for string and bytestring literals.
@@ -980,30 +978,25 @@ impl<'tcx> InterpretInterner<'tcx> {
980978
self.inner.borrow().alloc_by_id.get(&id).cloned()
981979
}
982980

983-
pub fn get_cached(
984-
&self,
985-
static_id: DefId,
986-
) -> Option<interpret::AllocId> {
987-
self.inner.borrow().alloc_cache.get(&static_id).cloned()
988-
}
989-
990-
pub fn cache(
981+
pub fn cache_static(
991982
&self,
992983
static_id: DefId,
993-
alloc_id: interpret::AllocId,
994-
) {
995-
let mut inner = self.inner.borrow_mut();
996-
inner.global_cache.insert(alloc_id, static_id);
997-
if let Some(old) = inner.alloc_cache.insert(static_id, alloc_id) {
998-
bug!("tried to cache {:?}, but was already existing as {:#?}", static_id, old);
984+
) -> interpret::AllocId {
985+
if let Some(alloc_id) = self.inner.borrow().static_cache.get(&static_id).cloned() {
986+
return alloc_id;
999987
}
988+
let alloc_id = self.reserve();
989+
let mut inner = self.inner.borrow_mut();
990+
inner.static_cache.insert(static_id, alloc_id);
991+
inner.statics.insert(alloc_id, static_id);
992+
alloc_id
1000993
}
1001994

1002-
pub fn get_corresponding_static_def_id(
995+
pub fn get_static(
1003996
&self,
1004997
ptr: interpret::AllocId,
1005998
) -> Option<DefId> {
1006-
self.inner.borrow().global_cache.get(&ptr).cloned()
999+
self.inner.borrow().statics.get(&ptr).cloned()
10071000
}
10081001

10091002
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
@@ -929,16 +929,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
929929
}
930930

931931
pub fn read_global_as_value(&self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
932-
if gid.promoted.is_none() {
933-
let cached = self
932+
if self.tcx.is_static(gid.instance.def_id()).is_some() {
933+
let alloc_id = self
934934
.tcx
935935
.interpret_interner
936-
.get_cached(gid.instance.def_id());
937-
if let Some(alloc_id) = cached {
938-
let layout = self.layout_of(ty)?;
939-
let ptr = MemoryPointer::new(alloc_id, 0);
940-
return Ok(Value::ByRef(ptr.into(), layout.align))
941-
}
936+
.cache_static(gid.instance.def_id());
937+
let layout = self.layout_of(ty)?;
938+
let ptr = MemoryPointer::new(alloc_id, 0);
939+
return Ok(Value::ByRef(ptr.into(), layout.align))
942940
}
943941
let cv = self.const_eval(gid)?;
944942
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
@@ -1111,7 +1111,7 @@ fn collect_miri<'a, 'tcx>(
11111111
alloc_id: AllocId,
11121112
output: &mut Vec<MonoItem<'tcx>>,
11131113
) {
1114-
if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
1114+
if let Some(did) = tcx.interpret_interner.get_static(alloc_id) {
11151115
let instance = Instance::mono(tcx, did);
11161116
if should_monomorphize_locally(tcx, &instance) {
11171117
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)