Skip to content

Commit 8c0310d

Browse files
authored
Rollup merge of #71508 - oli-obk:alloc_map_unlock, r=RalfJung
Simplify the `tcx.alloc_map` API This PR changes all functions that require manually locking the `alloc_map` to functions on `TyCtxt` that lock the map internally. In the same step we make the `TyCtxt::alloc_map` field private. r? @RalfJung
2 parents ce05553 + b07a44d commit 8c0310d

File tree

19 files changed

+115
-107
lines changed

19 files changed

+115
-107
lines changed

src/librustc_codegen_llvm/common.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,8 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
244244
}
245245
}
246246
Scalar::Ptr(ptr) => {
247-
let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
248-
let base_addr = match alloc_kind {
249-
Some(GlobalAlloc::Memory(alloc)) => {
247+
let base_addr = match self.tcx.global_alloc(ptr.alloc_id) {
248+
GlobalAlloc::Memory(alloc) => {
250249
let init = const_alloc_to_llvm(self, alloc);
251250
let value = match alloc.mutability {
252251
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
@@ -257,12 +256,11 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
257256
}
258257
value
259258
}
260-
Some(GlobalAlloc::Function(fn_instance)) => self.get_fn_addr(fn_instance),
261-
Some(GlobalAlloc::Static(def_id)) => {
259+
GlobalAlloc::Function(fn_instance) => self.get_fn_addr(fn_instance),
260+
GlobalAlloc::Static(def_id) => {
262261
assert!(self.tcx.is_static(def_id));
263262
self.get_static(def_id)
264263
}
265-
None => bug!("missing allocation {:?}", ptr.alloc_id),
266264
};
267265
let llval = unsafe {
268266
llvm::LLVMConstInBoundsGEP(

src/librustc_codegen_ssa/mir/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
9292
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
9393
};
9494
let a = Scalar::from(Pointer::new(
95-
bx.tcx().alloc_map.lock().create_memory_alloc(data),
95+
bx.tcx().create_memory_alloc(data),
9696
Size::from_bytes(start),
9797
));
9898
let a_llval = bx.scalar_to_backend(

src/librustc_middle/ich/impls_ty.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
136136
ty::tls::with_opt(|tcx| {
137137
trace!("hashing {:?}", *self);
138138
let tcx = tcx.expect("can't hash AllocIds during hir lowering");
139-
let alloc_kind = tcx.alloc_map.lock().get(*self);
140-
alloc_kind.hash_stable(hcx, hasher);
139+
tcx.get_global_alloc(*self).hash_stable(hcx, hasher);
141140
});
142141
}
143142
}

src/librustc_middle/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#![feature(or_patterns)]
4343
#![feature(range_is_empty)]
4444
#![feature(specialization)]
45+
#![feature(track_caller)]
4546
#![feature(trusted_len)]
4647
#![feature(vec_remove_item)]
4748
#![feature(stmt_expr_attributes)]

src/librustc_middle/mir/interpret/mod.rs

+70-46
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,7 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>(
197197
tcx: TyCtxt<'tcx>,
198198
alloc_id: AllocId,
199199
) -> Result<(), E::Error> {
200-
let alloc: GlobalAlloc<'tcx> =
201-
tcx.alloc_map.lock().get(alloc_id).expect("no value for given alloc ID");
202-
match alloc {
200+
match tcx.global_alloc(alloc_id) {
203201
GlobalAlloc::Memory(alloc) => {
204202
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
205203
AllocDiscriminant::Alloc.encode(encoder)?;
@@ -294,7 +292,7 @@ impl<'s> AllocDecodingSession<'s> {
294292
AllocDiscriminant::Alloc => {
295293
// If this is an allocation, we need to reserve an
296294
// `AllocId` so we can decode cyclic graphs.
297-
let alloc_id = decoder.tcx().alloc_map.lock().reserve();
295+
let alloc_id = decoder.tcx().reserve_alloc_id();
298296
*entry =
299297
State::InProgress(TinyList::new_single(self.session_id), alloc_id);
300298
Some(alloc_id)
@@ -338,23 +336,23 @@ impl<'s> AllocDecodingSession<'s> {
338336
// We already have a reserved `AllocId`.
339337
let alloc_id = alloc_id.unwrap();
340338
trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
341-
decoder.tcx().alloc_map.lock().set_alloc_id_same_memory(alloc_id, alloc);
339+
decoder.tcx().set_alloc_id_same_memory(alloc_id, alloc);
342340
Ok(alloc_id)
343341
}
344342
AllocDiscriminant::Fn => {
345343
assert!(alloc_id.is_none());
346344
trace!("creating fn alloc ID");
347345
let instance = ty::Instance::decode(decoder)?;
348346
trace!("decoded fn alloc instance: {:?}", instance);
349-
let alloc_id = decoder.tcx().alloc_map.lock().create_fn_alloc(instance);
347+
let alloc_id = decoder.tcx().create_fn_alloc(instance);
350348
Ok(alloc_id)
351349
}
352350
AllocDiscriminant::Static => {
353351
assert!(alloc_id.is_none());
354352
trace!("creating extern static alloc ID");
355353
let did = DefId::decode(decoder)?;
356354
trace!("decoded static def-ID: {:?}", did);
357-
let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did);
355+
let alloc_id = decoder.tcx().create_static_alloc(did);
358356
Ok(alloc_id)
359357
}
360358
}
@@ -381,7 +379,29 @@ pub enum GlobalAlloc<'tcx> {
381379
Memory(&'tcx Allocation),
382380
}
383381

384-
pub struct AllocMap<'tcx> {
382+
impl GlobalAlloc<'tcx> {
383+
/// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory`
384+
#[track_caller]
385+
#[inline]
386+
pub fn unwrap_memory(&self) -> &'tcx Allocation {
387+
match *self {
388+
GlobalAlloc::Memory(mem) => mem,
389+
_ => bug!("expected memory, got {:?}", self),
390+
}
391+
}
392+
393+
/// Panics if the `GlobalAlloc` is not `GlobalAlloc::Function`
394+
#[track_caller]
395+
#[inline]
396+
pub fn unwrap_fn(&self) -> Instance<'tcx> {
397+
match *self {
398+
GlobalAlloc::Function(instance) => instance,
399+
_ => bug!("expected function, got {:?}", self),
400+
}
401+
}
402+
}
403+
404+
crate struct AllocMap<'tcx> {
385405
/// Maps `AllocId`s to their corresponding allocations.
386406
alloc_map: FxHashMap<AllocId, GlobalAlloc<'tcx>>,
387407

@@ -397,16 +417,10 @@ pub struct AllocMap<'tcx> {
397417
}
398418

399419
impl<'tcx> AllocMap<'tcx> {
400-
pub fn new() -> Self {
420+
crate fn new() -> Self {
401421
AllocMap { alloc_map: Default::default(), dedup: Default::default(), next_id: AllocId(0) }
402422
}
403-
404-
/// Obtains a new allocation ID that can be referenced but does not
405-
/// yet have an allocation backing it.
406-
///
407-
/// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
408-
/// an `AllocId` from a query.
409-
pub fn reserve(&mut self) -> AllocId {
423+
fn reserve(&mut self) -> AllocId {
410424
let next = self.next_id;
411425
self.next_id.0 = self.next_id.0.checked_add(1).expect(
412426
"You overflowed a u64 by incrementing by 1... \
@@ -415,34 +429,46 @@ impl<'tcx> AllocMap<'tcx> {
415429
);
416430
next
417431
}
432+
}
433+
434+
impl<'tcx> TyCtxt<'tcx> {
435+
/// Obtains a new allocation ID that can be referenced but does not
436+
/// yet have an allocation backing it.
437+
///
438+
/// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
439+
/// an `AllocId` from a query.
440+
pub fn reserve_alloc_id(&self) -> AllocId {
441+
self.alloc_map.lock().reserve()
442+
}
418443

419444
/// Reserves a new ID *if* this allocation has not been dedup-reserved before.
420445
/// Should only be used for function pointers and statics, we don't want
421446
/// to dedup IDs for "real" memory!
422-
fn reserve_and_set_dedup(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId {
447+
fn reserve_and_set_dedup(&self, alloc: GlobalAlloc<'tcx>) -> AllocId {
448+
let mut alloc_map = self.alloc_map.lock();
423449
match alloc {
424450
GlobalAlloc::Function(..) | GlobalAlloc::Static(..) => {}
425451
GlobalAlloc::Memory(..) => bug!("Trying to dedup-reserve memory with real data!"),
426452
}
427-
if let Some(&alloc_id) = self.dedup.get(&alloc) {
453+
if let Some(&alloc_id) = alloc_map.dedup.get(&alloc) {
428454
return alloc_id;
429455
}
430-
let id = self.reserve();
456+
let id = alloc_map.reserve();
431457
debug!("creating alloc {:?} with id {}", alloc, id);
432-
self.alloc_map.insert(id, alloc.clone());
433-
self.dedup.insert(alloc, id);
458+
alloc_map.alloc_map.insert(id, alloc.clone());
459+
alloc_map.dedup.insert(alloc, id);
434460
id
435461
}
436462

437463
/// Generates an `AllocId` for a static or return a cached one in case this function has been
438464
/// called on the same static before.
439-
pub fn create_static_alloc(&mut self, static_id: DefId) -> AllocId {
465+
pub fn create_static_alloc(&self, static_id: DefId) -> AllocId {
440466
self.reserve_and_set_dedup(GlobalAlloc::Static(static_id))
441467
}
442468

443469
/// Generates an `AllocId` for a function. Depending on the function type,
444470
/// this might get deduplicated or assigned a new ID each time.
445-
pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId {
471+
pub fn create_fn_alloc(&self, instance: Instance<'tcx>) -> AllocId {
446472
// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
447473
// by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
448474
// duplicated across crates.
@@ -456,8 +482,9 @@ impl<'tcx> AllocMap<'tcx> {
456482
});
457483
if is_generic {
458484
// Get a fresh ID.
459-
let id = self.reserve();
460-
self.alloc_map.insert(id, GlobalAlloc::Function(instance));
485+
let mut alloc_map = self.alloc_map.lock();
486+
let id = alloc_map.reserve();
487+
alloc_map.alloc_map.insert(id, GlobalAlloc::Function(instance));
461488
id
462489
} else {
463490
// Deduplicate.
@@ -470,8 +497,8 @@ impl<'tcx> AllocMap<'tcx> {
470497
/// Statics with identical content will still point to the same `Allocation`, i.e.,
471498
/// their data will be deduplicated through `Allocation` interning -- but they
472499
/// are different places in memory and as such need different IDs.
473-
pub fn create_memory_alloc(&mut self, mem: &'tcx Allocation) -> AllocId {
474-
let id = self.reserve();
500+
pub fn create_memory_alloc(&self, mem: &'tcx Allocation) -> AllocId {
501+
let id = self.reserve_alloc_id();
475502
self.set_alloc_id_memory(id, mem);
476503
id
477504
}
@@ -482,38 +509,35 @@ impl<'tcx> AllocMap<'tcx> {
482509
/// This function exists to allow const eval to detect the difference between evaluation-
483510
/// local dangling pointers and allocations in constants/statics.
484511
#[inline]
485-
pub fn get(&self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
486-
self.alloc_map.get(&id).cloned()
487-
}
488-
489-
/// Panics if the `AllocId` does not refer to an `Allocation`
490-
pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation {
491-
match self.get(id) {
492-
Some(GlobalAlloc::Memory(mem)) => mem,
493-
_ => bug!("expected allocation ID {} to point to memory", id),
494-
}
512+
pub fn get_global_alloc(&self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
513+
self.alloc_map.lock().alloc_map.get(&id).cloned()
495514
}
496515

497-
/// Panics if the `AllocId` does not refer to a function
498-
pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
499-
match self.get(id) {
500-
Some(GlobalAlloc::Function(instance)) => instance,
501-
_ => bug!("expected allocation ID {} to point to a function", id),
516+
#[inline]
517+
#[track_caller]
518+
/// Panics in case the `AllocId` is dangling. Since that is impossible for `AllocId`s in
519+
/// constants (as all constants must pass interning and validation that check for dangling
520+
/// ids), this function is frequently used throughout rustc, but should not be used within
521+
/// the miri engine.
522+
pub fn global_alloc(&self, id: AllocId) -> GlobalAlloc<'tcx> {
523+
match self.get_global_alloc(id) {
524+
Some(alloc) => alloc,
525+
None => bug!("could not find allocation for {}", id),
502526
}
503527
}
504528

505529
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
506530
/// call this function twice, even with the same `Allocation` will ICE the compiler.
507-
pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
508-
if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
531+
pub fn set_alloc_id_memory(&self, id: AllocId, mem: &'tcx Allocation) {
532+
if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
509533
bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
510534
}
511535
}
512536

513537
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
514538
/// twice for the same `(AllocId, Allocation)` pair.
515-
fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
516-
self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
539+
fn set_alloc_id_same_memory(&self, id: AllocId, mem: &'tcx Allocation) {
540+
self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
517541
}
518542
}
519543

src/librustc_middle/mir/mod.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -2404,13 +2404,9 @@ pub struct Constant<'tcx> {
24042404
impl Constant<'tcx> {
24052405
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
24062406
match self.literal.val.try_to_scalar() {
2407-
Some(Scalar::Ptr(ptr)) => match tcx.alloc_map.lock().get(ptr.alloc_id) {
2408-
Some(GlobalAlloc::Static(def_id)) => Some(def_id),
2409-
Some(_) => None,
2410-
None => {
2411-
tcx.sess.delay_span_bug(DUMMY_SP, "MIR cannot contain dangling const pointers");
2412-
None
2413-
}
2407+
Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
2408+
GlobalAlloc::Static(def_id) => Some(def_id),
2409+
_ => None,
24142410
},
24152411
_ => None,
24162412
}

src/librustc_middle/ty/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ pub struct GlobalCtxt<'tcx> {
979979
allocation_interner: ShardedHashMap<&'tcx Allocation, ()>,
980980

981981
/// Stores memory for globals (statics/consts).
982-
pub alloc_map: Lock<interpret::AllocMap<'tcx>>,
982+
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
983983

984984
layout_interner: ShardedHashMap<&'tcx Layout, ()>,
985985

@@ -1017,7 +1017,7 @@ impl<'tcx> TyCtxt<'tcx> {
10171017
// Create an allocation that just contains these bytes.
10181018
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
10191019
let alloc = self.intern_const_alloc(alloc);
1020-
self.alloc_map.lock().create_memory_alloc(alloc)
1020+
self.create_memory_alloc(alloc)
10211021
}
10221022

10231023
pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {

src/librustc_middle/ty/print/pretty.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -956,9 +956,8 @@ pub trait PrettyPrinter<'tcx>:
956956
) => {
957957
let byte_str = self
958958
.tcx()
959-
.alloc_map
960-
.lock()
961-
.unwrap_memory(ptr.alloc_id)
959+
.global_alloc(ptr.alloc_id)
960+
.unwrap_memory()
962961
.get_bytes(&self.tcx(), ptr, Size::from_bytes(*data))
963962
.unwrap();
964963
p!(pretty_print_byte_str(byte_str));
@@ -1021,10 +1020,7 @@ pub trait PrettyPrinter<'tcx>:
10211020
)?;
10221021
}
10231022
(Scalar::Ptr(ptr), ty::FnPtr(_)) => {
1024-
let instance = {
1025-
let alloc_map = self.tcx().alloc_map.lock();
1026-
alloc_map.unwrap_fn(ptr.alloc_id)
1027-
};
1023+
let instance = self.tcx().global_alloc(ptr.alloc_id).unwrap_fn();
10281024
self = self.typed_value(
10291025
|this| this.print_value_path(instance.def_id(), instance.substs),
10301026
|this| this.print_type(ty),

src/librustc_middle/ty/relate.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,8 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
549549
if a_val == b_val {
550550
Ok(ConstValue::Scalar(a_val))
551551
} else if let ty::FnPtr(_) = a.ty.kind {
552-
let alloc_map = tcx.alloc_map.lock();
553-
let a_instance = alloc_map.unwrap_fn(a_val.assert_ptr().alloc_id);
554-
let b_instance = alloc_map.unwrap_fn(b_val.assert_ptr().alloc_id);
552+
let a_instance = tcx.global_alloc(a_val.assert_ptr().alloc_id).unwrap_fn();
553+
let b_instance = tcx.global_alloc(b_val.assert_ptr().alloc_id).unwrap_fn();
555554
if a_instance == b_instance {
556555
Ok(ConstValue::Scalar(a_val))
557556
} else {

src/librustc_mir/const_eval/eval_queries.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub(super) fn op_to_const<'tcx>(
130130

131131
let to_const_value = |mplace: MPlaceTy<'_>| match mplace.ptr {
132132
Scalar::Ptr(ptr) => {
133-
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
133+
let alloc = ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory();
134134
ConstValue::ByRef { alloc, offset: ptr.offset }
135135
}
136136
Scalar::Raw { data, .. } => {
@@ -155,7 +155,7 @@ pub(super) fn op_to_const<'tcx>(
155155
Immediate::ScalarPair(a, b) => {
156156
let (data, start) = match a.not_undef().unwrap() {
157157
Scalar::Ptr(ptr) => {
158-
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
158+
(ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes())
159159
}
160160
Scalar::Raw { .. } => (
161161
ecx.tcx
@@ -203,7 +203,7 @@ fn validate_and_turn_into_const<'tcx>(
203203
if is_static || cid.promoted.is_some() {
204204
let ptr = mplace.ptr.assert_ptr();
205205
Ok(ConstValue::ByRef {
206-
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
206+
alloc: ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(),
207207
offset: ptr.offset,
208208
})
209209
} else {

0 commit comments

Comments
 (0)