@@ -83,8 +83,8 @@ pub struct Stack {
83
83
/// search to be efficient, so we use the uniqueness guarantee to keep a map from tag to
84
84
/// position in the stack.
85
85
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 > ,
88
88
/// On a read, we need to disable all `Unique` above the granting item. We can avoid most of
89
89
/// this scan by keeping track of the region of the borrow stack that may contain `Unique`s.
90
90
first_unique : usize ,
@@ -275,15 +275,32 @@ impl Permission {
275
275
impl < ' tcx > Stack {
276
276
/// Find the item granting the given kind of access to the given tag, and return where
277
277
/// 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 > {
279
279
match tag {
280
280
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
+ } ;
281
290
// 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
+ }
283
300
// Return permission of the first item that grants access.
284
301
// 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) ;
287
304
}
288
305
}
289
306
return None ;
@@ -389,9 +406,12 @@ impl<'tcx> Stack {
389
406
}
390
407
}
391
408
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
+ }
394
413
}
414
+
395
415
if first_incompatible_idx <= self . first_unique {
396
416
// We removed all the Unique items
397
417
self . first_unique = 0 ;
@@ -457,7 +477,6 @@ impl<'tcx> Stack {
457
477
}
458
478
459
479
self . cache . clear ( ) ;
460
- self . untagged . clear ( ) ;
461
480
self . first_unique = 0 ;
462
481
self . last_unique = 0 ;
463
482
@@ -522,6 +541,10 @@ impl<'tcx> Stack {
522
541
// The above insert changes the meaning of every index in the cache >= new_idx, so now
523
542
// we need to find every one of those indexes and increment it.
524
543
544
+ if new. tag == SbTag :: Untagged && new_idx >= self . top_untagged . unwrap_or ( 0 ) {
545
+ self . top_untagged = Some ( new_idx) ;
546
+ }
547
+
525
548
// Adjust the possibly-unique range if an insert occurs before or within it
526
549
if self . first_unique >= new_idx {
527
550
self . first_unique += 1 ;
@@ -541,20 +564,11 @@ impl<'tcx> Stack {
541
564
* self . cache . get_mut ( & id) . unwrap ( ) += 1 ;
542
565
}
543
566
}
544
- for idx in self . untagged . iter_mut ( ) . rev ( ) . take_while ( |idx| * * idx >= new_idx) {
545
- * idx += 1 ;
546
- }
547
567
}
548
568
// We've now made a (conceptual) hole in the tag lookup cache.
549
569
// 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) ;
558
572
}
559
573
}
560
574
@@ -569,16 +583,16 @@ impl<'tcx> Stacks {
569
583
fn new ( size : Size , perm : Permission , tag : SbTag ) -> Self {
570
584
let item = Item { perm, tag, protector : None } ;
571
585
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 ) ;
580
588
}
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
+ } ;
582
596
583
597
Stacks { stacks : RefCell :: new ( RangeMap :: new ( size, stack) ) }
584
598
}
0 commit comments