Skip to content

Commit 543777a

Browse files
committed
avoid unnecessary RefCell calls in Stacked Borrows
1 parent cf7e4b9 commit 543777a

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

src/stacked_borrows.rs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)