Skip to content

Commit b152f49

Browse files
committed
Replace the Untagged index stack with a single index
1 parent 0716f4a commit b152f49

File tree

1 file changed

+43
-29
lines changed

1 file changed

+43
-29
lines changed

src/stacked_borrows.rs

+43-29
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ pub struct Stack {
8787
/// search to be efficient, so we use the uniqueness guarantee to keep a map from tag to
8888
/// position in the stack.
8989
cache: FxHashMap<PtrId, usize>,
90-
/// `Untagged` may occur multiple times so we store it outside of the map.
91-
untagged: Vec<usize>,
90+
/// Index of the most recently inserted Untagged
91+
top_untagged: Option<usize>,
9292
/// On a read, we need to disable all `Unique` above the granting item. We can avoid most of
9393
/// this scan by keeping track of the region of the borrow stack that may contain `Unique`s.
9494
first_unique: usize,
@@ -280,15 +280,32 @@ impl Permission {
280280
impl<'tcx> Stack {
281281
/// Find the item granting the given kind of access to the given tag, and return where
282282
/// it is on the stack.
283-
fn find_granting(&self, access: AccessKind, tag: SbTag) -> Option<usize> {
283+
fn find_granting(&mut self, access: AccessKind, tag: SbTag) -> Option<usize> {
284284
match tag {
285285
SbTag::Untagged => {
286+
let end = if let Some(idx) = self.top_untagged {
287+
if self.borrows[idx].perm.grants(access) {
288+
return Some(idx);
289+
} else {
290+
idx
291+
}
292+
} else {
293+
self.borrows.len()
294+
};
286295
// Search top-to-bottom
287-
for idx in self.untagged.iter().rev() {
296+
for (idx, item) in self.borrows[..end]
297+
.iter()
298+
.enumerate()
299+
.rev()
300+
.filter(|(_, item)| item.tag == SbTag::Untagged)
301+
{
302+
if self.top_untagged.is_none() {
303+
self.top_untagged = Some(idx);
304+
}
288305
// Return permission of the first item that grants access.
289306
// We require a permission with the right tag, ensuring U3 and F3.
290-
if self.borrows[*idx].perm.grants(access) {
291-
return Some(*idx);
307+
if item.perm.grants(access) {
308+
return Some(idx);
292309
}
293310
}
294311
return None;
@@ -399,9 +416,12 @@ impl<'tcx> Stack {
399416
}
400417
}
401418

402-
while self.untagged.last() >= Some(&first_incompatible_idx) {
403-
self.untagged.pop();
419+
if let Some(idx) = self.top_untagged {
420+
if idx >= first_incompatible_idx {
421+
self.top_untagged = None;
422+
}
404423
}
424+
405425
if first_incompatible_idx <= self.first_unique {
406426
// We removed all the Unique items
407427
self.first_unique = 0;
@@ -467,7 +487,6 @@ impl<'tcx> Stack {
467487
}
468488

469489
self.cache.clear();
470-
self.untagged.clear();
471490
self.first_unique = 0;
472491
self.last_unique = 0;
473492

@@ -532,6 +551,10 @@ impl<'tcx> Stack {
532551
// The above insert changes the meaning of every index in the cache >= new_idx, so now
533552
// we need to find every one of those indexes and increment it.
534553

554+
if new.tag == SbTag::Untagged && new_idx >= self.top_untagged.unwrap_or(0) {
555+
self.top_untagged = Some(new_idx);
556+
}
557+
535558
// Adjust the possibly-unique range if an insert occurs before or within it
536559
if self.first_unique >= new_idx {
537560
self.first_unique += 1;
@@ -551,20 +574,11 @@ impl<'tcx> Stack {
551574
*self.cache.get_mut(&id).unwrap() += 1;
552575
}
553576
}
554-
for idx in self.untagged.iter_mut().rev().take_while(|idx| **idx >= new_idx) {
555-
*idx += 1;
556-
}
557577
}
558578
// We've now made a (conceptual) hole in the tag lookup cache.
559579
// Nothing maps to new_idx, because we've adjusted everything >= it.
560-
match new.tag {
561-
SbTag::Untagged => {
562-
self.untagged.push(new_idx);
563-
self.untagged.sort();
564-
}
565-
SbTag::Tagged(id) => {
566-
self.cache.insert(id, new_idx);
567-
}
580+
if let SbTag::Tagged(id) = new.tag {
581+
self.cache.insert(id, new_idx);
568582
}
569583
}
570584

@@ -645,16 +659,16 @@ impl<'tcx> Stacks {
645659
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
646660
let item = Item { perm, tag, protector: None };
647661
let mut cache = FxHashMap::default();
648-
let mut untagged = Vec::new();
649-
match item.tag {
650-
SbTag::Untagged => {
651-
untagged.push(0);
652-
}
653-
SbTag::Tagged(id) => {
654-
cache.insert(id, 0);
655-
}
662+
if let SbTag::Tagged(id) = item.tag {
663+
cache.insert(id, 0);
656664
}
657-
let stack = Stack { borrows: vec![item], cache, untagged, first_unique: 0, last_unique: 0 };
665+
let stack = Stack {
666+
borrows: vec![item],
667+
cache,
668+
first_unique: 0,
669+
last_unique: 0,
670+
top_untagged: None,
671+
};
658672

659673
Stacks { stacks: RefCell::new(RangeMap::new(size, stack)) }
660674
}

0 commit comments

Comments
 (0)