@@ -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