Skip to content

Commit a36fe44

Browse files
committed
Steal another bit in PackedItem to indicate if it is protected
1 parent 85d3a5d commit a36fe44

File tree

2 files changed

+43
-36
lines changed

2 files changed

+43
-36
lines changed

src/stacked_borrows.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ pub struct Item {
9999
perm: Permission,
100100
/// The pointers the permission is granted to.
101101
tag: SbTag,
102+
/// Whether or not there is a protector for this tag
103+
protected: bool,
102104
}
103105

104106
impl fmt::Debug for Item {
@@ -325,7 +327,7 @@ impl<'tcx> Stack {
325327
));
326328
}
327329

328-
if global.protected_tags.contains(&item.tag) {
330+
if item.protected && global.protected_tags.contains(&item.tag) {
329331
if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
330332
Err(err_sb_ub(
331333
format!(
@@ -568,7 +570,7 @@ impl<'tcx> Stack {
568570
impl<'tcx> Stacks {
569571
/// Creates new stack with initial tag.
570572
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
571-
let item = Item { perm, tag };
573+
let item = Item { perm, tag, protected: false };
572574
let stack = Stack::new(item);
573575

574576
Stacks {
@@ -853,7 +855,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
853855
} else {
854856
Permission::SharedReadWrite
855857
};
856-
let item = Item { perm, tag: new_tag };
858+
let protected = if frozen {
859+
protect
860+
} else {
861+
// We do not protect inside UnsafeCell.
862+
// This fixes https://github.com/rust-lang/rust/issues/55005.
863+
false
864+
};
865+
let item = Item { perm, tag: new_tag, protected };
857866
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
858867
stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| {
859868
stack.grant(
@@ -879,7 +888,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
879888
.as_mut()
880889
.expect("we should have Stacked Borrows data")
881890
.borrow_mut();
882-
let item = Item { perm, tag: new_tag };
891+
let item = Item { perm, tag: new_tag, protected: protect };
883892
let range = alloc_range(base_offset, size);
884893
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
885894
let current_span = &mut machine.current_span(); // `get_alloc_extra_mut` invalidated our old `current_span`

src/stacked_borrows/stack.rs

+30-32
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,16 @@ const CACHE_LEN: usize = 32;
1717
struct PackedItem(u64);
1818

1919
impl PackedItem {
20-
const TAG_MASK: u64 = u64::MAX << 2;
21-
const PERM_MASK: u64 = !Self::TAG_MASK;
22-
23-
fn new(tag: SbTag, perm: Permission) -> Self {
24-
let packed_perm = match perm {
25-
Permission::Unique => 0,
26-
Permission::SharedReadWrite => 1,
27-
Permission::SharedReadOnly => 2,
28-
Permission::Disabled => 3,
29-
};
30-
debug_assert!(packed_perm & Self::TAG_MASK == 0);
31-
32-
let packed_tag = tag.0.get() << 2;
33-
debug_assert!(packed_tag & Self::PERM_MASK == 0);
34-
35-
let new = Self(packed_tag + packed_perm);
36-
37-
debug_assert!(new.tag() == tag);
38-
debug_assert!(new.perm() == perm);
39-
40-
new
41-
}
20+
const TAG_MASK: u64 = u64::MAX >> 3;
21+
const PERM_MASK: u64 = 0x3 << 61;
22+
const PROTECTED_MASK: u64 = 0x1 << 63;
4223

4324
fn tag(self) -> SbTag {
44-
unsafe { SbTag(std::num::NonZeroU64::new_unchecked((self.0 & Self::TAG_MASK) >> 2)) }
25+
unsafe { SbTag(std::num::NonZeroU64::new_unchecked(self.0 & Self::TAG_MASK)) }
4526
}
4627

4728
fn perm(self) -> Permission {
48-
match self.0 & Self::PERM_MASK {
29+
match (self.0 & Self::PERM_MASK) >> 61 {
4930
0 => Permission::Unique,
5031
1 => Permission::SharedReadWrite,
5132
2 => Permission::SharedReadOnly,
@@ -54,20 +35,40 @@ impl PackedItem {
5435
}
5536
}
5637

38+
fn protected(self) -> bool {
39+
self.0 & Self::PROTECTED_MASK > 0
40+
}
41+
5742
fn set_disabled(&mut self) {
58-
self.0 |= 0x3;
43+
self.0 |= Self::PERM_MASK;
5944
}
6045
}
6146

6247
impl From<Item> for PackedItem {
6348
fn from(item: Item) -> Self {
64-
Self::new(item.tag, item.perm)
49+
assert!(item.tag.0.get() <= Self::TAG_MASK);
50+
let perm = match item.perm {
51+
Permission::Unique => 0,
52+
Permission::SharedReadWrite => 1,
53+
Permission::SharedReadOnly => 2,
54+
Permission::Disabled => 3,
55+
} << 61;
56+
let tag = item.tag.0.get();
57+
let protected = (item.protected as u64) << 63;
58+
59+
let new = Self(tag + perm + protected);
60+
61+
debug_assert!(new.tag() == item.tag);
62+
debug_assert!(new.perm() == item.perm);
63+
debug_assert!(new.protected() == item.protected);
64+
65+
new
6566
}
6667
}
6768

6869
impl From<PackedItem> for Item {
6970
fn from(item: PackedItem) -> Item {
70-
let new = Item { tag: item.tag(), perm: item.perm() };
71+
let new = Item { tag: item.tag(), perm: item.perm(), protected: item.protected() };
7172

7273
debug_assert!(new.tag == item.tag());
7374
debug_assert!(new.perm == item.perm());
@@ -310,7 +311,7 @@ impl<'tcx> Stack {
310311
}
311312

312313
// This primes the cache for the next access, which is almost always the just-added tag.
313-
self.cache.add(new_idx, PackedItem::new(new.tag, new.perm));
314+
self.cache.add(new_idx, PackedItem::from(new));
314315

315316
#[cfg(feature = "expensive-debug-assertions")]
316317
self.verify_cache_consistency();
@@ -322,10 +323,7 @@ impl<'tcx> Stack {
322323
borrows: vec![item.into()],
323324
unknown_bottom: None,
324325
#[cfg(feature = "stack-cache")]
325-
cache: StackCache {
326-
idx: [0; CACHE_LEN],
327-
tags: [PackedItem::new(item.tag, item.perm); CACHE_LEN],
328-
},
326+
cache: StackCache { idx: [0; CACHE_LEN], tags: [PackedItem::from(item); CACHE_LEN] },
329327
#[cfg(feature = "stack-cache")]
330328
unique_range: if item.perm == Permission::Unique { 0..1 } else { 0..0 },
331329
}

0 commit comments

Comments
 (0)