@@ -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 ;
@@ -382,9 +399,12 @@ impl<'tcx> Stack {
382
399
}
383
400
}
384
401
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
+ }
387
406
}
407
+
388
408
if first_incompatible_idx <= self . first_unique {
389
409
// We removed all the Unique items
390
410
self . first_unique = 0 ;
@@ -450,7 +470,6 @@ impl<'tcx> Stack {
450
470
}
451
471
452
472
self . cache . clear ( ) ;
453
- self . untagged . clear ( ) ;
454
473
self . first_unique = 0 ;
455
474
self . last_unique = 0 ;
456
475
@@ -515,6 +534,10 @@ impl<'tcx> Stack {
515
534
// The above insert changes the meaning of every index in the cache >= new_idx, so now
516
535
// we need to find every one of those indexes and increment it.
517
536
537
+ if new. tag == SbTag :: Untagged && new_idx >= self . top_untagged . unwrap_or ( 0 ) {
538
+ self . top_untagged = Some ( new_idx) ;
539
+ }
540
+
518
541
// Adjust the possibly-unique range if an insert occurs before or within it
519
542
if self . first_unique >= new_idx {
520
543
self . first_unique += 1 ;
@@ -534,20 +557,11 @@ impl<'tcx> Stack {
534
557
* self . cache . get_mut ( & id) . unwrap ( ) += 1 ;
535
558
}
536
559
}
537
- for idx in self . untagged . iter_mut ( ) . rev ( ) . take_while ( |idx| * * idx >= new_idx) {
538
- * idx += 1 ;
539
- }
540
560
}
541
561
// We've now made a (conceptual) hole in the tag lookup cache.
542
562
// 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) ;
551
565
}
552
566
}
553
567
@@ -562,16 +576,16 @@ impl<'tcx> Stacks {
562
576
fn new ( size : Size , perm : Permission , tag : SbTag ) -> Self {
563
577
let item = Item { perm, tag, protector : None } ;
564
578
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 ) ;
573
581
}
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
+ } ;
575
589
576
590
Stacks { stacks : RefCell :: new ( RangeMap :: new ( size, stack) ) }
577
591
}
0 commit comments