Skip to content

Commit a73d32f

Browse files
committed
Replace the Untagged index stack with a single index
1 parent 67df005 commit a73d32f

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
@@ -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;
@@ -389,9 +406,12 @@ impl<'tcx> Stack {
389406
}
390407
}
391408

392-
while self.untagged.last() >= Some(&first_incompatible_idx) {
393-
self.untagged.pop();
409+
if let Some(idx) = self.top_untagged {
410+
if idx >= first_incompatible_idx {
411+
self.top_untagged = None;
412+
}
394413
}
414+
395415
if first_incompatible_idx <= self.first_unique {
396416
// We removed all the Unique items
397417
self.first_unique = 0;
@@ -457,7 +477,6 @@ impl<'tcx> Stack {
457477
}
458478

459479
self.cache.clear();
460-
self.untagged.clear();
461480
self.first_unique = 0;
462481
self.last_unique = 0;
463482

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

544+
if new.tag == SbTag::Untagged && new_idx >= self.top_untagged.unwrap_or(0) {
545+
self.top_untagged = Some(new_idx);
546+
}
547+
525548
// Adjust the possibly-unique range if an insert occurs before or within it
526549
if self.first_unique >= new_idx {
527550
self.first_unique += 1;
@@ -541,20 +564,11 @@ impl<'tcx> Stack {
541564
*self.cache.get_mut(&id).unwrap() += 1;
542565
}
543566
}
544-
for idx in self.untagged.iter_mut().rev().take_while(|idx| **idx >= new_idx) {
545-
*idx += 1;
546-
}
547567
}
548568
// We've now made a (conceptual) hole in the tag lookup cache.
549569
// Nothing maps to new_idx, because we've adjusted everything >= it.
550-
match new.tag {
551-
SbTag::Untagged => {
552-
self.untagged.push(new_idx);
553-
self.untagged.sort();
554-
}
555-
SbTag::Tagged(id) => {
556-
self.cache.insert(id, new_idx);
557-
}
570+
if let SbTag::Tagged(id) = new.tag {
571+
self.cache.insert(id, new_idx);
558572
}
559573
}
560574

@@ -569,16 +583,16 @@ impl<'tcx> Stacks {
569583
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
570584
let item = Item { perm, tag, protector: None };
571585
let mut cache = FxHashMap::default();
572-
let mut untagged = Vec::new();
573-
match item.tag {
574-
SbTag::Untagged => {
575-
untagged.push(0);
576-
}
577-
SbTag::Tagged(id) => {
578-
cache.insert(id, 0);
579-
}
586+
if let SbTag::Tagged(id) = item.tag {
587+
cache.insert(id, 0);
580588
}
581-
let stack = Stack { borrows: vec![item], cache, untagged, first_unique: 0, last_unique: 0 };
589+
let stack = Stack {
590+
borrows: vec![item],
591+
cache,
592+
first_unique: 0,
593+
last_unique: 0,
594+
top_untagged: None,
595+
};
582596

583597
Stacks { stacks: RefCell::new(RangeMap::new(size, stack)) }
584598
}

0 commit comments

Comments
 (0)