@@ -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 {
275275impl < ' 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