@@ -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 ;
@@ -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