@@ -19,6 +19,10 @@ use rustc_span::Span;
19
19
20
20
use std:: cell:: Cell ;
21
21
use std:: iter;
22
+ #[ cfg( debug_assertions) ]
23
+ use std:: ops:: BitXor ;
24
+ #[ cfg( debug_assertions) ]
25
+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
22
26
23
27
pub struct MarkedAttrs ( GrowableBitSet < AttrId > ) ;
24
28
@@ -350,17 +354,36 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
350
354
351
355
pub struct AttrIdGenerator ( WorkerLocal < Cell < u32 > > ) ;
352
356
357
+ #[ cfg( debug_assertions) ]
358
+ static MAX_ATTR_ID : AtomicU32 = AtomicU32 :: new ( u32:: MAX ) ;
359
+
353
360
impl AttrIdGenerator {
354
361
pub fn new ( ) -> Self {
355
362
// We use `(index as u32).reverse_bits()` to initialize the
356
363
// starting value of AttrId in each worker thread.
357
364
// The `index` is the index of the worker thread.
358
365
// This ensures that the AttrId generated in each thread is unique.
359
- AttrIdGenerator ( WorkerLocal :: new ( |index| Cell :: new ( ( index as u32 ) . reverse_bits ( ) ) ) )
366
+ AttrIdGenerator ( WorkerLocal :: new ( |index| {
367
+ let index: u32 = index. try_into ( ) . unwrap ( ) ;
368
+
369
+ #[ cfg( debug_assertions) ]
370
+ {
371
+ let max_id = ( ( index + 1 ) . next_power_of_two ( ) - 1 ) . bitxor ( u32:: MAX ) . reverse_bits ( ) ;
372
+ MAX_ATTR_ID . fetch_min ( max_id, Ordering :: Release ) ;
373
+ }
374
+
375
+ Cell :: new ( index. reverse_bits ( ) )
376
+ } ) )
360
377
}
361
378
362
379
pub fn mk_attr_id ( & self ) -> AttrId {
363
380
let id = self . 0 . get ( ) ;
381
+
382
+ // Ensure the assigned attr_id does not overlap the bits
383
+ // representing the number of threads.
384
+ #[ cfg( debug_assertions) ]
385
+ assert ! ( id <= MAX_ATTR_ID . load( Ordering :: Acquire ) ) ;
386
+
364
387
self . 0 . set ( id + 1 ) ;
365
388
AttrId :: from_u32 ( id)
366
389
}
0 commit comments