@@ -11,12 +11,18 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
11
11
use crate :: tokenstream:: { LazyAttrTokenStream , TokenStream } ;
12
12
use crate :: util:: comments;
13
13
14
+ use rustc_data_structures:: sync:: WorkerLocal ;
14
15
use rustc_index:: bit_set:: GrowableBitSet ;
15
16
use rustc_span:: source_map:: BytePos ;
16
17
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
17
18
use rustc_span:: Span ;
18
19
20
+ use std:: cell:: Cell ;
19
21
use std:: iter;
22
+ #[ cfg( debug_assertions) ]
23
+ use std:: ops:: BitXor ;
24
+ #[ cfg( debug_assertions) ]
25
+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
20
26
21
27
pub struct MarkedAttrs ( GrowableBitSet < AttrId > ) ;
22
28
@@ -346,52 +352,86 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
346
352
NestedMetaItem :: MetaItem ( mk_word_item ( ident) )
347
353
}
348
354
349
- pub ( crate ) fn mk_attr_id ( ) -> AttrId {
350
- use std:: sync:: atomic:: AtomicU32 ;
351
- use std:: sync:: atomic:: Ordering ;
355
+ pub struct AttrIdGenerator ( WorkerLocal < Cell < u32 > > ) ;
352
356
353
- static NEXT_ATTR_ID : AtomicU32 = AtomicU32 :: new ( 0 ) ;
357
+ #[ cfg( debug_assertions) ]
358
+ static MAX_ATTR_ID : AtomicU32 = AtomicU32 :: new ( u32:: MAX ) ;
354
359
355
- let id = NEXT_ATTR_ID . fetch_add ( 1 , Ordering :: SeqCst ) ;
356
- assert ! ( id != u32 :: MAX ) ;
357
- AttrId :: from_u32 ( id)
360
+ impl AttrIdGenerator {
361
+ pub fn new ( ) -> Self {
362
+ // We use `(index as u32).reverse_bits()` to initialize the
363
+ // starting value of AttrId in each worker thread.
364
+ // The `index` is the index of the worker thread.
365
+ // This ensures that the AttrId generated in each thread is unique.
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
+ } ) )
377
+ }
378
+
379
+ pub fn mk_attr_id ( & self ) -> AttrId {
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
+
387
+ self . 0 . set ( id + 1 ) ;
388
+ AttrId :: from_u32 ( id)
389
+ }
358
390
}
359
391
360
- pub fn mk_attr ( style : AttrStyle , path : Path , args : MacArgs , span : Span ) -> Attribute {
361
- mk_attr_from_item ( AttrItem { path, args, tokens : None } , None , style, span)
392
+ pub fn mk_attr (
393
+ g : & AttrIdGenerator ,
394
+ style : AttrStyle ,
395
+ path : Path ,
396
+ args : MacArgs ,
397
+ span : Span ,
398
+ ) -> Attribute {
399
+ mk_attr_from_item ( g, AttrItem { path, args, tokens : None } , None , style, span)
362
400
}
363
401
364
402
pub fn mk_attr_from_item (
403
+ g : & AttrIdGenerator ,
365
404
item : AttrItem ,
366
405
tokens : Option < LazyAttrTokenStream > ,
367
406
style : AttrStyle ,
368
407
span : Span ,
369
408
) -> Attribute {
370
409
Attribute {
371
410
kind : AttrKind :: Normal ( P ( ast:: NormalAttr { item, tokens } ) ) ,
372
- id : mk_attr_id ( ) ,
411
+ id : g . mk_attr_id ( ) ,
373
412
style,
374
413
span,
375
414
}
376
415
}
377
416
378
417
/// Returns an inner attribute with the given value and span.
379
- pub fn mk_attr_inner ( item : MetaItem ) -> Attribute {
380
- mk_attr ( AttrStyle :: Inner , item. path , item. kind . mac_args ( item. span ) , item. span )
418
+ pub fn mk_attr_inner ( g : & AttrIdGenerator , item : MetaItem ) -> Attribute {
419
+ mk_attr ( g , AttrStyle :: Inner , item. path , item. kind . mac_args ( item. span ) , item. span )
381
420
}
382
421
383
422
/// Returns an outer attribute with the given value and span.
384
- pub fn mk_attr_outer ( item : MetaItem ) -> Attribute {
385
- mk_attr ( AttrStyle :: Outer , item. path , item. kind . mac_args ( item. span ) , item. span )
423
+ pub fn mk_attr_outer ( g : & AttrIdGenerator , item : MetaItem ) -> Attribute {
424
+ mk_attr ( g , AttrStyle :: Outer , item. path , item. kind . mac_args ( item. span ) , item. span )
386
425
}
387
426
388
427
pub fn mk_doc_comment (
428
+ g : & AttrIdGenerator ,
389
429
comment_kind : CommentKind ,
390
430
style : AttrStyle ,
391
431
data : Symbol ,
392
432
span : Span ,
393
433
) -> Attribute {
394
- Attribute { kind : AttrKind :: DocComment ( comment_kind, data) , id : mk_attr_id ( ) , style, span }
434
+ Attribute { kind : AttrKind :: DocComment ( comment_kind, data) , id : g . mk_attr_id ( ) , style, span }
395
435
}
396
436
397
437
pub fn list_contains_name ( items : & [ NestedMetaItem ] , name : Symbol ) -> bool {
0 commit comments