@@ -11,12 +11,18 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
1111use crate :: tokenstream:: { LazyAttrTokenStream , TokenStream } ;
1212use crate :: util:: comments;
1313
14+ use rustc_data_structures:: sync:: WorkerLocal ;
1415use rustc_index:: bit_set:: GrowableBitSet ;
1516use rustc_span:: source_map:: BytePos ;
1617use rustc_span:: symbol:: { sym, Ident , Symbol } ;
1718use rustc_span:: Span ;
1819
20+ use std:: cell:: Cell ;
1921use std:: iter;
22+ #[ cfg( debug_assertions) ]
23+ use std:: ops:: BitXor ;
24+ #[ cfg( debug_assertions) ]
25+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
2026
2127pub struct MarkedAttrs ( GrowableBitSet < AttrId > ) ;
2228
@@ -346,52 +352,86 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
346352 NestedMetaItem :: MetaItem ( mk_word_item ( ident) )
347353}
348354
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 > > ) ;
352356
353- static NEXT_ATTR_ID : AtomicU32 = AtomicU32 :: new ( 0 ) ;
357+ #[ cfg( debug_assertions) ]
358+ static MAX_ATTR_ID : AtomicU32 = AtomicU32 :: new ( u32:: MAX ) ;
354359
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+ }
358390}
359391
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)
362400}
363401
364402pub fn mk_attr_from_item (
403+ g : & AttrIdGenerator ,
365404 item : AttrItem ,
366405 tokens : Option < LazyAttrTokenStream > ,
367406 style : AttrStyle ,
368407 span : Span ,
369408) -> Attribute {
370409 Attribute {
371410 kind : AttrKind :: Normal ( P ( ast:: NormalAttr { item, tokens } ) ) ,
372- id : mk_attr_id ( ) ,
411+ id : g . mk_attr_id ( ) ,
373412 style,
374413 span,
375414 }
376415}
377416
378417/// 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 )
381420}
382421
383422/// 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 )
386425}
387426
388427pub fn mk_doc_comment (
428+ g : & AttrIdGenerator ,
389429 comment_kind : CommentKind ,
390430 style : AttrStyle ,
391431 data : Symbol ,
392432 span : Span ,
393433) -> 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 }
395435}
396436
397437pub fn list_contains_name ( items : & [ NestedMetaItem ] , name : Symbol ) -> bool {
0 commit comments