4
4
use std:: cell:: RefCell ;
5
5
use std:: fmt;
6
6
use std:: num:: NonZeroU64 ;
7
- use std:: rc:: Rc ;
8
-
9
7
use log:: trace;
10
8
11
9
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
@@ -87,8 +85,6 @@ pub struct Stack {
87
85
pub struct Stacks {
88
86
// Even reading memory can have effects on the stack, so we need a `RefCell` here.
89
87
stacks : RefCell < RangeMap < Stack > > ,
90
- // Pointer to global state
91
- global : MemoryExtra ,
92
88
}
93
89
94
90
/// Extra global state, available to the memory access hooks.
@@ -112,7 +108,7 @@ pub struct GlobalState {
112
108
track_raw : bool ,
113
109
}
114
110
/// Memory extra state gives us interior mutable access to the global state.
115
- pub type MemoryExtra = Rc < RefCell < GlobalState > > ;
111
+ pub type MemoryExtra = RefCell < GlobalState > ;
116
112
117
113
/// Indicates which kind of access is being performed.
118
114
#[ derive( Copy , Clone , Hash , PartialEq , Eq ) ]
@@ -449,21 +445,21 @@ impl<'tcx> Stack {
449
445
/// Map per-stack operations to higher-level per-location-range operations.
450
446
impl < ' tcx > Stacks {
451
447
/// Creates new stack with initial tag.
452
- fn new ( size : Size , perm : Permission , tag : Tag , extra : MemoryExtra ) -> Self {
448
+ fn new ( size : Size , perm : Permission , tag : Tag ) -> Self {
453
449
let item = Item { perm, tag, protector : None } ;
454
450
let stack = Stack { borrows : vec ! [ item] } ;
455
451
456
- Stacks { stacks : RefCell :: new ( RangeMap :: new ( size, stack) ) , global : extra }
452
+ Stacks { stacks : RefCell :: new ( RangeMap :: new ( size, stack) ) }
457
453
}
458
454
459
455
/// Call `f` on every stack in the range.
460
456
fn for_each (
461
457
& self ,
462
458
ptr : Pointer < Tag > ,
463
459
size : Size ,
460
+ global : & GlobalState ,
464
461
f : impl Fn ( Pointer < Tag > , & mut Stack , & GlobalState ) -> InterpResult < ' tcx > ,
465
462
) -> InterpResult < ' tcx > {
466
- let global = self . global . borrow ( ) ;
467
463
let mut stacks = self . stacks . borrow_mut ( ) ;
468
464
for ( offset, stack) in stacks. iter_mut ( ptr. offset , size) {
469
465
let mut cur_ptr = ptr;
@@ -479,16 +475,17 @@ impl Stacks {
479
475
pub fn new_allocation (
480
476
id : AllocId ,
481
477
size : Size ,
482
- extra : MemoryExtra ,
478
+ extra : & MemoryExtra ,
483
479
kind : MemoryKind < MiriMemoryKind > ,
484
480
) -> ( Self , Tag ) {
481
+ let mut extra = extra. borrow_mut ( ) ;
485
482
let ( tag, perm) = match kind {
486
483
// New unique borrow. This tag is not accessible by the program,
487
484
// so it will only ever be used when using the local directly (i.e.,
488
485
// not through a pointer). That is, whenever we directly write to a local, this will pop
489
486
// everything else off the stack, invalidating all previous pointers,
490
487
// and in particular, *all* raw pointers.
491
- MemoryKind :: Stack => ( Tag :: Tagged ( extra. borrow_mut ( ) . new_ptr ( ) ) , Permission :: Unique ) ,
488
+ MemoryKind :: Stack => ( Tag :: Tagged ( extra. new_ptr ( ) ) , Permission :: Unique ) ,
492
489
// `Global` memory can be referenced by global pointers from `tcx`.
493
490
// Thus we call `global_base_ptr` such that the global pointers get the same tag
494
491
// as what we use here.
@@ -500,38 +497,38 @@ impl Stacks {
500
497
| MiriMemoryKind :: ExternStatic
501
498
| MiriMemoryKind :: Tls
502
499
| MiriMemoryKind :: Env ,
503
- ) => ( extra. borrow_mut ( ) . global_base_ptr ( id) , Permission :: SharedReadWrite ) ,
500
+ ) => ( extra. global_base_ptr ( id) , Permission :: SharedReadWrite ) ,
504
501
// Everything else we handle like raw pointers for now.
505
502
_ => {
506
- let mut extra = extra. borrow_mut ( ) ;
507
503
let tag =
508
504
if extra. track_raw { Tag :: Tagged ( extra. new_ptr ( ) ) } else { Tag :: Untagged } ;
509
505
( tag, Permission :: SharedReadWrite )
510
506
}
511
507
} ;
512
- ( Stacks :: new ( size, perm, tag, extra ) , tag)
508
+ ( Stacks :: new ( size, perm, tag) , tag)
513
509
}
514
510
515
511
#[ inline( always) ]
516
- pub fn memory_read < ' tcx > ( & self , ptr : Pointer < Tag > , size : Size ) -> InterpResult < ' tcx > {
512
+ pub fn memory_read < ' tcx > ( & self , ptr : Pointer < Tag > , size : Size , extra : & MemoryExtra ) -> InterpResult < ' tcx > {
517
513
trace ! ( "read access with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
518
- self . for_each ( ptr, size, |ptr, stack, global| stack. access ( AccessKind :: Read , ptr, global) )
514
+ self . for_each ( ptr, size, & * extra . borrow ( ) , |ptr, stack, global| stack. access ( AccessKind :: Read , ptr, global) )
519
515
}
520
516
521
517
#[ inline( always) ]
522
- pub fn memory_written < ' tcx > ( & mut self , ptr : Pointer < Tag > , size : Size ) -> InterpResult < ' tcx > {
518
+ pub fn memory_written < ' tcx > ( & mut self , ptr : Pointer < Tag > , size : Size , extra : & mut MemoryExtra ) -> InterpResult < ' tcx > {
523
519
trace ! ( "write access with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
524
- self . for_each ( ptr, size, |ptr, stack, global| stack. access ( AccessKind :: Write , ptr, global) )
520
+ self . for_each ( ptr, size, extra . get_mut ( ) , |ptr, stack, global| stack. access ( AccessKind :: Write , ptr, global) )
525
521
}
526
522
527
523
#[ inline( always) ]
528
524
pub fn memory_deallocated < ' tcx > (
529
525
& mut self ,
530
526
ptr : Pointer < Tag > ,
531
527
size : Size ,
528
+ extra : & mut MemoryExtra ,
532
529
) -> InterpResult < ' tcx > {
533
530
trace ! ( "deallocation with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
534
- self . for_each ( ptr, size, |ptr, stack, global| stack. dealloc ( ptr, global) )
531
+ self . for_each ( ptr, size, extra . get_mut ( ) , |ptr, stack, global| stack. dealloc ( ptr, global) )
535
532
}
536
533
}
537
534
@@ -560,10 +557,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
560
557
size. bytes( )
561
558
) ;
562
559
563
- // Get the allocation. It might not be mutable, so we cannot use `get_mut`.
560
+ // Get the allocation. We need both the allocation and the MemoryExtra, so we cannot use `&mut`.
561
+ // FIXME: make `get_alloc_extra_mut` also return `&mut MemoryExtra`.
564
562
let extra = this. memory . get_alloc_extra ( ptr. alloc_id ) ?;
565
563
let stacked_borrows =
566
564
extra. stacked_borrows . as_ref ( ) . expect ( "we should have Stacked Borrows data" ) ;
565
+ let global = this. memory . extra . stacked_borrows . as_ref ( ) . unwrap ( ) . borrow ( ) ;
567
566
// Update the stacks.
568
567
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
569
568
// There could be existing unique pointers reborrowed from them that should remain valid!
@@ -583,14 +582,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
583
582
Permission :: SharedReadWrite
584
583
} ;
585
584
let item = Item { perm, tag : new_tag, protector } ;
586
- stacked_borrows. for_each ( cur_ptr, size, |cur_ptr, stack, global| {
585
+ stacked_borrows. for_each ( cur_ptr, size, & * global , |cur_ptr, stack, global| {
587
586
stack. grant ( cur_ptr, item, global)
588
587
} )
589
588
} ) ;
590
589
}
591
590
} ;
592
591
let item = Item { perm, tag : new_tag, protector } ;
593
- stacked_borrows. for_each ( ptr, size, |ptr, stack, global| stack. grant ( ptr, item, global) )
592
+ stacked_borrows. for_each ( ptr, size, & * global , |ptr, stack, global| stack. grant ( ptr, item, global) )
594
593
}
595
594
596
595
/// Retags an indidual pointer, returning the retagged version.
0 commit comments