Skip to content

Commit 17acc3f

Browse files
committed
Document implementation a bit, add some fast paths
1 parent 3bbcafe commit 17acc3f

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/stacked_borrows/stack.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ struct StackCache {
5151

5252
#[cfg(feature = "stack-cache")]
5353
impl StackCache {
54+
/// When a tag is used, we call this function to add or refresh it in the cache.
55+
///
56+
/// We use position in the cache to represent how recently a tag was used; the first position
57+
/// is the most recently used tag. So an add shifts every element towards the end, and inserts
58+
/// the new element at the start. We lose the last element.
59+
/// This strategy is effective at keeping the most-accessed tags in the cache, but it costs a
60+
/// linear shift across the entire cache when we add a new tag.
5461
fn add(&mut self, idx: usize, tag: SbTag) {
5562
self.tags.copy_within(0..CACHE_LEN - 1, 1);
5663
self.tags[0] = tag;
@@ -172,9 +179,12 @@ impl<'tcx> Stack {
172179
// If we found the tag, look up its position in the stack to see if it grants
173180
// the required permission
174181
if self.borrows[stack_idx].perm.grants(access) {
175-
// If it does, and it's already in the most-recently-used position, move it
176-
// there.
177-
if cache_idx != 0 {
182+
// If it does, and it's not already in the most-recently-used position, move it there.
183+
// Except if the tag is in position 1, this is equivalent to just a swap, so do that.
184+
if cache_idx == 1 {
185+
self.cache.tags.swap(0, 1);
186+
self.cache.idx.swap(0, 1);
187+
} else if cache_idx > 1 {
178188
self.cache.add(stack_idx, tag);
179189
}
180190
Some(stack_idx)
@@ -208,9 +218,13 @@ impl<'tcx> Stack {
208218

209219
// The above insert changes the meaning of every index in the cache >= new_idx, so now
210220
// we need to find every one of those indexes and increment it.
211-
for idx in &mut self.cache.idx {
212-
if *idx >= new_idx {
213-
*idx += 1;
221+
// But if the insert is at the end (equivalent to a push), we can skip this step because
222+
// it didn't change the position of any other tags.
223+
if new_idx != self.borrows.len() - 1 {
224+
for idx in &mut self.cache.idx {
225+
if *idx >= new_idx {
226+
*idx += 1;
227+
}
214228
}
215229
}
216230

0 commit comments

Comments
 (0)