@@ -35,7 +35,7 @@ pub struct GlobalStateInner {
35
35
/// `AllocExtra` because function pointers also have a base address, and
36
36
/// they do not have an `AllocExtra`.
37
37
/// This is the inverse of `int_to_ptr_map`.
38
- base_addr : FxHashMap < AllocId , u64 > ,
38
+ base_addr : FxHashMap < AllocId , ( u64 , bool ) > ,
39
39
/// Whether an allocation has been exposed or not. This cannot be put
40
40
/// into `AllocExtra` for the same reason as `base_addr`.
41
41
exposed : FxHashSet < AllocId > ,
@@ -78,7 +78,7 @@ impl GlobalStateInner {
78
78
pub fn remove_unreachable_allocs ( & mut self , allocs : & LiveAllocs < ' _ , ' _ , ' _ > ) {
79
79
// `exposed` and `int_to_ptr_map` are cleared immediately when an allocation
80
80
// is freed, so `base_addr` is the only one we have to clean up based on the GC.
81
- self . base_addr . retain ( |id, _ | allocs. is_live ( * id) ) ;
81
+ self . base_addr . retain ( |id, ( _ , is_global ) | allocs. is_live ( * id, is_global ) ) ;
82
82
}
83
83
}
84
84
@@ -125,7 +125,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
125
125
// We only use this provenance if it has been exposed.
126
126
if global_state. exposed . contains ( & alloc_id) {
127
127
// This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
128
- debug_assert ! ( ecx. is_alloc_live( alloc_id) ) ;
128
+ debug_assert ! ( !matches! ( ecx. is_alloc_live( alloc_id) , Liveness :: Dead ) ) ;
129
129
Some ( alloc_id)
130
130
} else {
131
131
None
@@ -138,7 +138,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
138
138
let global_state = & mut * global_state;
139
139
140
140
Ok ( match global_state. base_addr . entry ( alloc_id) {
141
- Entry :: Occupied ( entry) => * entry. get ( ) ,
141
+ Entry :: Occupied ( entry) => entry. get ( ) . 0 ,
142
142
Entry :: Vacant ( entry) => {
143
143
let ( size, align, kind) = ecx. get_alloc_info ( alloc_id) ;
144
144
// This is either called immediately after allocation (and then cached), or when
@@ -161,7 +161,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
161
161
. checked_add ( slack)
162
162
. ok_or_else ( || err_exhaust ! ( AddressSpaceFull ) ) ?;
163
163
let base_addr = align_addr ( base_addr, align. bytes ( ) ) ;
164
- entry. insert ( base_addr) ;
164
+ entry. insert ( ( base_addr, kind . is_global ( ) ) ) ;
165
165
trace ! (
166
166
"Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})" ,
167
167
base_addr,
@@ -204,7 +204,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
204
204
}
205
205
// Exposing a dead alloc is a no-op, because it's not possible to get a dead allocation
206
206
// via int2ptr.
207
- if ! ecx. is_alloc_live ( alloc_id) {
207
+ if matches ! ( ecx. is_alloc_live( alloc_id) , Liveness :: Dead ) {
208
208
return Ok ( ( ) ) ;
209
209
}
210
210
trace ! ( "Exposing allocation id {alloc_id:?}" ) ;
@@ -312,7 +312,7 @@ impl GlobalStateInner {
312
312
// returns a dead allocation.
313
313
// To avoid a linear scan we first look up the address in `base_addr`, and then find it in
314
314
// `int_to_ptr_map`.
315
- let addr = * self . base_addr . get ( & dead_id) . unwrap ( ) ;
315
+ let addr = self . base_addr . get ( & dead_id) . unwrap ( ) . 0 ;
316
316
let pos = self . int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) . unwrap ( ) ;
317
317
let removed = self . int_to_ptr_map . remove ( pos) ;
318
318
assert_eq ! ( removed, ( addr, dead_id) ) ; // double-check that we removed the right thing
0 commit comments