@@ -457,14 +457,29 @@ impl<'tcx> Stacks {
457457 & self ,
458458 ptr : Pointer < Tag > ,
459459 size : Size ,
460- global : & GlobalState ,
461- f : impl Fn ( Pointer < Tag > , & mut Stack , & GlobalState ) -> InterpResult < ' tcx > ,
460+ f : impl Fn ( Pointer < Tag > , & mut Stack ) -> InterpResult < ' tcx > ,
462461 ) -> InterpResult < ' tcx > {
463462 let mut stacks = self . stacks . borrow_mut ( ) ;
464463 for ( offset, stack) in stacks. iter_mut ( ptr. offset , size) {
465464 let mut cur_ptr = ptr;
466465 cur_ptr. offset = offset;
467- f ( cur_ptr, stack, & * global) ?;
466+ f ( cur_ptr, stack) ?;
467+ }
468+ Ok ( ( ) )
469+ }
470+
471+ /// Call `f` on every stack in the range.
472+ fn for_each_mut (
473+ & mut self ,
474+ ptr : Pointer < Tag > ,
475+ size : Size ,
476+ f : impl Fn ( Pointer < Tag > , & mut Stack ) -> InterpResult < ' tcx > ,
477+ ) -> InterpResult < ' tcx > {
478+ let stacks = self . stacks . get_mut ( ) ;
479+ for ( offset, stack) in stacks. iter_mut ( ptr. offset , size) {
480+ let mut cur_ptr = ptr;
481+ cur_ptr. offset = offset;
482+ f ( cur_ptr, stack) ?;
468483 }
469484 Ok ( ( ) )
470485 }
@@ -516,9 +531,8 @@ impl Stacks {
516531 extra : & MemoryExtra ,
517532 ) -> InterpResult < ' tcx > {
518533 trace ! ( "read access with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
519- self . for_each ( ptr, size, & * extra. borrow ( ) , |ptr, stack, global| {
520- stack. access ( AccessKind :: Read , ptr, global)
521- } )
534+ let global = & * extra. borrow ( ) ;
535+ self . for_each ( ptr, size, move |ptr, stack| stack. access ( AccessKind :: Read , ptr, global) )
522536 }
523537
524538 #[ inline( always) ]
@@ -529,9 +543,8 @@ impl Stacks {
529543 extra : & mut MemoryExtra ,
530544 ) -> InterpResult < ' tcx > {
531545 trace ! ( "write access with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
532- self . for_each ( ptr, size, extra. get_mut ( ) , |ptr, stack, global| {
533- stack. access ( AccessKind :: Write , ptr, global)
534- } )
546+ let global = extra. get_mut ( ) ;
547+ self . for_each_mut ( ptr, size, move |ptr, stack| stack. access ( AccessKind :: Write , ptr, global) )
535548 }
536549
537550 #[ inline( always) ]
@@ -542,7 +555,8 @@ impl Stacks {
542555 extra : & mut MemoryExtra ,
543556 ) -> InterpResult < ' tcx > {
544557 trace ! ( "deallocation with tag {:?}: {:?}, size {}" , ptr. tag, ptr. erase_tag( ) , size. bytes( ) ) ;
545- self . for_each ( ptr, size, extra. get_mut ( ) , |ptr, stack, global| stack. dealloc ( ptr, global) )
558+ let global = extra. get_mut ( ) ;
559+ self . for_each_mut ( ptr, size, move |ptr, stack| stack. dealloc ( ptr, global) )
546560 }
547561}
548562
@@ -571,12 +585,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
571585 size. bytes( )
572586 ) ;
573587
574- // Get the allocation. We need both the allocation and the MemoryExtra, so we cannot use `&mut`.
575- // FIXME: make `get_alloc_extra_mut` also return `&mut MemoryExtra`.
576- let extra = this. memory . get_alloc_extra ( ptr. alloc_id ) ?;
577- let stacked_borrows =
578- extra. stacked_borrows . as_ref ( ) . expect ( "we should have Stacked Borrows data" ) ;
579- let global = this. memory . extra . stacked_borrows . as_ref ( ) . unwrap ( ) . borrow ( ) ;
580588 // Update the stacks.
581589 // Make sure that raw pointers and mutable shared references are reborrowed "weak":
582590 // There could be existing unique pointers reborrowed from them that should remain valid!
@@ -588,6 +596,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
588596 // Shared references and *const are a whole different kind of game, the
589597 // permission is not uniform across the entire range!
590598 // We need a frozen-sensitive reborrow.
599+ // We have to use shared references to alloc/memory_extra here since
600+ // `visit_freeze_sensitive` needs to access the global state.
601+ let extra = this. memory . get_alloc_extra ( ptr. alloc_id ) ?;
602+ let stacked_borrows =
603+ extra. stacked_borrows . as_ref ( ) . expect ( "we should have Stacked Borrows data" ) ;
604+ let global = this. memory . extra . stacked_borrows . as_ref ( ) . unwrap ( ) . borrow ( ) ;
591605 return this. visit_freeze_sensitive ( place, size, |cur_ptr, size, frozen| {
592606 // We are only ever `SharedReadOnly` inside the frozen bits.
593607 let perm = if frozen {
@@ -596,15 +610,19 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
596610 Permission :: SharedReadWrite
597611 } ;
598612 let item = Item { perm, tag : new_tag, protector } ;
599- stacked_borrows. for_each ( cur_ptr, size, & * global , |cur_ptr, stack, global | {
600- stack. grant ( cur_ptr, item, global)
613+ stacked_borrows. for_each ( cur_ptr, size, |cur_ptr, stack| {
614+ stack. grant ( cur_ptr, item, & * global)
601615 } )
602616 } ) ;
603617 }
604618 } ;
619+ // Here we can avoid `borrow()` calls because we have mutable references.
620+ let ( alloc_extra, memory_extra) = this. memory . get_alloc_extra_mut ( ptr. alloc_id ) ?;
621+ let stacked_borrows =
622+ alloc_extra. stacked_borrows . as_mut ( ) . expect ( "we should have Stacked Borrows data" ) ;
623+ let global = memory_extra. stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) ;
605624 let item = Item { perm, tag : new_tag, protector } ;
606- stacked_borrows
607- . for_each ( ptr, size, & * global, |ptr, stack, global| stack. grant ( ptr, item, global) )
625+ stacked_borrows. for_each_mut ( ptr, size, |ptr, stack| stack. grant ( ptr, item, global) )
608626 }
609627
610628 /// Retags an indidual pointer, returning the retagged version.
@@ -640,7 +658,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
640658
641659 // Compute new borrow.
642660 let new_tag = {
643- let mut mem_extra = this. memory . extra . stacked_borrows . as_ref ( ) . unwrap ( ) . borrow_mut ( ) ;
661+ let mem_extra = this. memory . extra . stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) ;
644662 match kind {
645663 // Give up tracking for raw pointers.
646664 RefKind :: Raw { .. } if !mem_extra. track_raw => Tag :: Untagged ,
0 commit comments