Skip to content

Commit 9606bce

Browse files
committed
Replace the Untagged index stack with a single index
1 parent fe4bb5c commit 9606bce

File tree

1 file changed

+43
-29
lines changed

1 file changed

+43
-29
lines changed

src/stacked_borrows.rs

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ pub struct Stack {
8383
/// search to be efficient, so we use the uniqueness guarantee to keep a map from tag to
8484
/// position in the stack.
8585
cache: FxHashMap<PtrId, usize>,
86-
/// `Untagged` may occur multiple times so we store it outside of the map.
87-
untagged: Vec<usize>,
86+
/// Index of the most recently inserted Untagged
87+
top_untagged: Option<usize>,
8888
/// On a read, we need to disable all `Unique` above the granting item. We can avoid most of
8989
/// this scan by keeping track of the region of the borrow stack that may contain `Unique`s.
9090
first_unique: usize,
@@ -275,15 +275,32 @@ impl Permission {
275275
impl<'tcx> Stack {
276276
/// Find the item granting the given kind of access to the given tag, and return where
277277
/// it is on the stack.
278-
fn find_granting(&self, access: AccessKind, tag: SbTag) -> Option<usize> {
278+
fn find_granting(&mut self, access: AccessKind, tag: SbTag) -> Option<usize> {
279279
match tag {
280280
SbTag::Untagged => {
281+
let end = if let Some(idx) = self.top_untagged {
282+
if self.borrows[idx].perm.grants(access) {
283+
return Some(idx);
284+
} else {
285+
idx
286+
}
287+
} else {
288+
self.borrows.len()
289+
};
281290
// Search top-to-bottom
282-
for idx in self.untagged.iter().rev() {
291+
for (idx, item) in self.borrows[..end]
292+
.iter()
293+
.enumerate()
294+
.rev()
295+
.filter(|(_, item)| item.tag == SbTag::Untagged)
296+
{
297+
if self.top_untagged.is_none() {
298+
self.top_untagged = Some(idx);
299+
}
283300
// Return permission of the first item that grants access.
284301
// We require a permission with the right tag, ensuring U3 and F3.
285-
if self.borrows[*idx].perm.grants(access) {
286-
return Some(*idx);
302+
if item.perm.grants(access) {
303+
return Some(idx);
287304
}
288305
}
289306
return None;
@@ -382,9 +399,12 @@ impl<'tcx> Stack {
382399
}
383400
}
384401

385-
while self.untagged.last() >= Some(&first_incompatible_idx) {
386-
self.untagged.pop();
402+
if let Some(idx) = self.top_untagged {
403+
if idx >= first_incompatible_idx {
404+
self.top_untagged = None;
405+
}
387406
}
407+
388408
if first_incompatible_idx <= self.first_unique {
389409
// We removed all the Unique items
390410
self.first_unique = 0;
@@ -450,7 +470,6 @@ impl<'tcx> Stack {
450470
}
451471

452472
self.cache.clear();
453-
self.untagged.clear();
454473
self.first_unique = 0;
455474
self.last_unique = 0;
456475

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

537+
if new.tag == SbTag::Untagged && new_idx >= self.top_untagged.unwrap_or(0) {
538+
self.top_untagged = Some(new_idx);
539+
}
540+
518541
// Adjust the possibly-unique range if an insert occurs before or within it
519542
if self.first_unique >= new_idx {
520543
self.first_unique += 1;
@@ -534,20 +557,11 @@ impl<'tcx> Stack {
534557
*self.cache.get_mut(&id).unwrap() += 1;
535558
}
536559
}
537-
for idx in self.untagged.iter_mut().rev().take_while(|idx| **idx >= new_idx) {
538-
*idx += 1;
539-
}
540560
}
541561
// We've now made a (conceptual) hole in the tag lookup cache.
542562
// Nothing maps to new_idx, because we've adjusted everything >= it.
543-
match new.tag {
544-
SbTag::Untagged => {
545-
self.untagged.push(new_idx);
546-
self.untagged.sort();
547-
}
548-
SbTag::Tagged(id) => {
549-
self.cache.insert(id, new_idx);
550-
}
563+
if let SbTag::Tagged(id) = new.tag {
564+
self.cache.insert(id, new_idx);
551565
}
552566
}
553567

@@ -562,16 +576,16 @@ impl<'tcx> Stacks {
562576
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
563577
let item = Item { perm, tag, protector: None };
564578
let mut cache = FxHashMap::default();
565-
let mut untagged = Vec::new();
566-
match item.tag {
567-
SbTag::Untagged => {
568-
untagged.push(0);
569-
}
570-
SbTag::Tagged(id) => {
571-
cache.insert(id, 0);
572-
}
579+
if let SbTag::Tagged(id) = item.tag {
580+
cache.insert(id, 0);
573581
}
574-
let stack = Stack { borrows: vec![item], cache, untagged, first_unique: 0, last_unique: 0 };
582+
let stack = Stack {
583+
borrows: vec![item],
584+
cache,
585+
first_unique: 0,
586+
last_unique: 0,
587+
top_untagged: None,
588+
};
575589

576590
Stacks { stacks: RefCell::new(RangeMap::new(size, stack)) }
577591
}

0 commit comments

Comments
 (0)