@@ -87,8 +87,8 @@ pub struct Stack {
87
87
/// search to be efficient, so we use the uniqueness guarantee to keep a map from tag to
88
88
/// position in the stack.
89
89
cache : FxHashMap < PtrId , usize > ,
90
- /// `Untagged` may occur multiple times so we store it outside of the map.
91
- untagged : Vec < usize > ,
90
+ /// Index of the most recently inserted Untagged
91
+ top_untagged : Option < usize > ,
92
92
/// On a read, we need to disable all `Unique` above the granting item. We can avoid most of
93
93
/// this scan by keeping track of the region of the borrow stack that may contain `Unique`s.
94
94
first_unique : usize ,
@@ -280,15 +280,32 @@ impl Permission {
280
280
impl < ' tcx > Stack {
281
281
/// Find the item granting the given kind of access to the given tag, and return where
282
282
/// it is on the stack.
283
- fn find_granting ( & self , access : AccessKind , tag : SbTag ) -> Option < usize > {
283
+ fn find_granting ( & mut self , access : AccessKind , tag : SbTag ) -> Option < usize > {
284
284
match tag {
285
285
SbTag :: Untagged => {
286
+ let end = if let Some ( idx) = self . top_untagged {
287
+ if self . borrows [ idx] . perm . grants ( access) {
288
+ return Some ( idx) ;
289
+ } else {
290
+ idx
291
+ }
292
+ } else {
293
+ self . borrows . len ( )
294
+ } ;
286
295
// Search top-to-bottom
287
- for idx in self . untagged . iter ( ) . rev ( ) {
296
+ for ( idx, item) in self . borrows [ ..end]
297
+ . iter ( )
298
+ . enumerate ( )
299
+ . rev ( )
300
+ . filter ( |( _, item) | item. tag == SbTag :: Untagged )
301
+ {
302
+ if self . top_untagged . is_none ( ) {
303
+ self . top_untagged = Some ( idx) ;
304
+ }
288
305
// Return permission of the first item that grants access.
289
306
// We require a permission with the right tag, ensuring U3 and F3.
290
- if self . borrows [ * idx ] . perm . grants ( access) {
291
- return Some ( * idx) ;
307
+ if item . perm . grants ( access) {
308
+ return Some ( idx) ;
292
309
}
293
310
}
294
311
return None ;
@@ -399,9 +416,12 @@ impl<'tcx> Stack {
399
416
}
400
417
}
401
418
402
- while self . untagged . last ( ) >= Some ( & first_incompatible_idx) {
403
- self . untagged . pop ( ) ;
419
+ if let Some ( idx) = self . top_untagged {
420
+ if idx >= first_incompatible_idx {
421
+ self . top_untagged = None ;
422
+ }
404
423
}
424
+
405
425
if first_incompatible_idx <= self . first_unique {
406
426
// We removed all the Unique items
407
427
self . first_unique = 0 ;
@@ -467,7 +487,6 @@ impl<'tcx> Stack {
467
487
}
468
488
469
489
self . cache . clear ( ) ;
470
- self . untagged . clear ( ) ;
471
490
self . first_unique = 0 ;
472
491
self . last_unique = 0 ;
473
492
@@ -532,6 +551,10 @@ impl<'tcx> Stack {
532
551
// The above insert changes the meaning of every index in the cache >= new_idx, so now
533
552
// we need to find every one of those indexes and increment it.
534
553
554
+ if new. tag == SbTag :: Untagged && new_idx >= self . top_untagged . unwrap_or ( 0 ) {
555
+ self . top_untagged = Some ( new_idx) ;
556
+ }
557
+
535
558
// Adjust the possibly-unique range if an insert occurs before or within it
536
559
if self . first_unique >= new_idx {
537
560
self . first_unique += 1 ;
@@ -551,20 +574,11 @@ impl<'tcx> Stack {
551
574
* self . cache . get_mut ( & id) . unwrap ( ) += 1 ;
552
575
}
553
576
}
554
- for idx in self . untagged . iter_mut ( ) . rev ( ) . take_while ( |idx| * * idx >= new_idx) {
555
- * idx += 1 ;
556
- }
557
577
}
558
578
// We've now made a (conceptual) hole in the tag lookup cache.
559
579
// Nothing maps to new_idx, because we've adjusted everything >= it.
560
- match new. tag {
561
- SbTag :: Untagged => {
562
- self . untagged . push ( new_idx) ;
563
- self . untagged . sort ( ) ;
564
- }
565
- SbTag :: Tagged ( id) => {
566
- self . cache . insert ( id, new_idx) ;
567
- }
580
+ if let SbTag :: Tagged ( id) = new. tag {
581
+ self . cache . insert ( id, new_idx) ;
568
582
}
569
583
}
570
584
@@ -645,16 +659,16 @@ impl<'tcx> Stacks {
645
659
fn new ( size : Size , perm : Permission , tag : SbTag ) -> Self {
646
660
let item = Item { perm, tag, protector : None } ;
647
661
let mut cache = FxHashMap :: default ( ) ;
648
- let mut untagged = Vec :: new ( ) ;
649
- match item. tag {
650
- SbTag :: Untagged => {
651
- untagged. push ( 0 ) ;
652
- }
653
- SbTag :: Tagged ( id) => {
654
- cache. insert ( id, 0 ) ;
655
- }
662
+ if let SbTag :: Tagged ( id) = item. tag {
663
+ cache. insert ( id, 0 ) ;
656
664
}
657
- let stack = Stack { borrows : vec ! [ item] , cache, untagged, first_unique : 0 , last_unique : 0 } ;
665
+ let stack = Stack {
666
+ borrows : vec ! [ item] ,
667
+ cache,
668
+ first_unique : 0 ,
669
+ last_unique : 0 ,
670
+ top_untagged : None ,
671
+ } ;
658
672
659
673
Stacks { stacks : RefCell :: new ( RangeMap :: new ( size, stack) ) }
660
674
}
0 commit comments