mirror of
https://github.com/rust-lang/rust.git
synced 2026-06-01 22:18:23 +03:00
avoid unnecessary RefCell calls in Stacked Borrows
This commit is contained in:
+39
-21
@@ -457,14 +457,29 @@ fn for_each(
|
||||
&self,
|
||||
ptr: Pointer<Tag>,
|
||||
size: Size,
|
||||
global: &GlobalState,
|
||||
f: impl Fn(Pointer<Tag>, &mut Stack, &GlobalState) -> InterpResult<'tcx>,
|
||||
f: impl Fn(Pointer<Tag>, &mut Stack) -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let mut stacks = self.stacks.borrow_mut();
|
||||
for (offset, stack) in stacks.iter_mut(ptr.offset, size) {
|
||||
let mut cur_ptr = ptr;
|
||||
cur_ptr.offset = offset;
|
||||
f(cur_ptr, stack, &*global)?;
|
||||
f(cur_ptr, stack)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Call `f` on every stack in the range.
|
||||
fn for_each_mut(
|
||||
&mut self,
|
||||
ptr: Pointer<Tag>,
|
||||
size: Size,
|
||||
f: impl Fn(Pointer<Tag>, &mut Stack) -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let stacks = self.stacks.get_mut();
|
||||
for (offset, stack) in stacks.iter_mut(ptr.offset, size) {
|
||||
let mut cur_ptr = ptr;
|
||||
cur_ptr.offset = offset;
|
||||
f(cur_ptr, stack)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -516,9 +531,8 @@ pub fn memory_read<'tcx>(
|
||||
extra: &MemoryExtra,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("read access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
|
||||
self.for_each(ptr, size, &*extra.borrow(), |ptr, stack, global| {
|
||||
stack.access(AccessKind::Read, ptr, global)
|
||||
})
|
||||
let global = &*extra.borrow();
|
||||
self.for_each(ptr, size, move |ptr, stack| stack.access(AccessKind::Read, ptr, global))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -529,9 +543,8 @@ pub fn memory_written<'tcx>(
|
||||
extra: &mut MemoryExtra,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("write access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
|
||||
self.for_each(ptr, size, extra.get_mut(), |ptr, stack, global| {
|
||||
stack.access(AccessKind::Write, ptr, global)
|
||||
})
|
||||
let global = extra.get_mut();
|
||||
self.for_each_mut(ptr, size, move |ptr, stack| stack.access(AccessKind::Write, ptr, global))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -542,7 +555,8 @@ pub fn memory_deallocated<'tcx>(
|
||||
extra: &mut MemoryExtra,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("deallocation with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
|
||||
self.for_each(ptr, size, extra.get_mut(), |ptr, stack, global| stack.dealloc(ptr, global))
|
||||
let global = extra.get_mut();
|
||||
self.for_each_mut(ptr, size, move |ptr, stack| stack.dealloc(ptr, global))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,12 +585,6 @@ fn reborrow(
|
||||
size.bytes()
|
||||
);
|
||||
|
||||
// Get the allocation. We need both the allocation and the MemoryExtra, so we cannot use `&mut`.
|
||||
// FIXME: make `get_alloc_extra_mut` also return `&mut MemoryExtra`.
|
||||
let extra = this.memory.get_alloc_extra(ptr.alloc_id)?;
|
||||
let stacked_borrows =
|
||||
extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
|
||||
let global = this.memory.extra.stacked_borrows.as_ref().unwrap().borrow();
|
||||
// Update the stacks.
|
||||
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
|
||||
// There could be existing unique pointers reborrowed from them that should remain valid!
|
||||
@@ -588,6 +596,12 @@ fn reborrow(
|
||||
// Shared references and *const are a whole different kind of game, the
|
||||
// permission is not uniform across the entire range!
|
||||
// We need a frozen-sensitive reborrow.
|
||||
// We have to use shared references to alloc/memory_extra here since
|
||||
// `visit_freeze_sensitive` needs to access the global state.
|
||||
let extra = this.memory.get_alloc_extra(ptr.alloc_id)?;
|
||||
let stacked_borrows =
|
||||
extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
|
||||
let global = this.memory.extra.stacked_borrows.as_ref().unwrap().borrow();
|
||||
return this.visit_freeze_sensitive(place, size, |cur_ptr, size, frozen| {
|
||||
// We are only ever `SharedReadOnly` inside the frozen bits.
|
||||
let perm = if frozen {
|
||||
@@ -596,15 +610,19 @@ fn reborrow(
|
||||
Permission::SharedReadWrite
|
||||
};
|
||||
let item = Item { perm, tag: new_tag, protector };
|
||||
stacked_borrows.for_each(cur_ptr, size, &*global, |cur_ptr, stack, global| {
|
||||
stack.grant(cur_ptr, item, global)
|
||||
stacked_borrows.for_each(cur_ptr, size, |cur_ptr, stack| {
|
||||
stack.grant(cur_ptr, item, &*global)
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
// Here we can avoid `borrow()` calls because we have mutable references.
|
||||
let (alloc_extra, memory_extra) = this.memory.get_alloc_extra_mut(ptr.alloc_id)?;
|
||||
let stacked_borrows =
|
||||
alloc_extra.stacked_borrows.as_mut().expect("we should have Stacked Borrows data");
|
||||
let global = memory_extra.stacked_borrows.as_mut().unwrap().get_mut();
|
||||
let item = Item { perm, tag: new_tag, protector };
|
||||
stacked_borrows
|
||||
.for_each(ptr, size, &*global, |ptr, stack, global| stack.grant(ptr, item, global))
|
||||
stacked_borrows.for_each_mut(ptr, size, |ptr, stack| stack.grant(ptr, item, global))
|
||||
}
|
||||
|
||||
/// Retags an indidual pointer, returning the retagged version.
|
||||
@@ -640,7 +658,7 @@ fn retag_reference(
|
||||
|
||||
// Compute new borrow.
|
||||
let new_tag = {
|
||||
let mut mem_extra = this.memory.extra.stacked_borrows.as_ref().unwrap().borrow_mut();
|
||||
let mem_extra = this.memory.extra.stacked_borrows.as_mut().unwrap().get_mut();
|
||||
match kind {
|
||||
// Give up tracking for raw pointers.
|
||||
RefKind::Raw { .. } if !mem_extra.track_raw => Tag::Untagged,
|
||||
|
||||
Reference in New Issue
Block a user