Skip to content

Commit 750bd1a

Browse files
committed
Auto merge of rust-lang#101313 - SparrowLii:mk_attr_id, r=cjgillot
make `mk_attr_id` part of `ParseSess` Updates rust-lang#48685 The current `mk_attr_id` uses the `AtomicU32` type, which is not very efficient and adds a lot of lock contention in a parallel environment. This PR refers to the task list in rust-lang#48685, uses `mk_attr_id` as a method of the `AttrIdGenerator` struct, and adds a new field `attr_id_generator` to `ParseSess`. `AttrIdGenerator` uses the `WorkerLocal`, which has two advantages: 1. `Cell` is more efficient than `AtomicU32`, and does not increase any lock contention. 2. We put the index of the work thread in the first few bits of the generated `AttrId`, so that the `AttrId` generated in different threads can be easily guaranteed to be unique. cc `@cjgillot`
2 parents 6153d3c + bfc4f2e commit 750bd1a

File tree

13 files changed

+111
-27
lines changed

13 files changed

+111
-27
lines changed

compiler/rustc_ast/src/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2524,8 +2524,8 @@ impl<S: Encoder> Encodable<S> for AttrId {
25242524
}
25252525

25262526
impl<D: Decoder> Decodable<D> for AttrId {
2527-
fn decode(_: &mut D) -> AttrId {
2528-
crate::attr::mk_attr_id()
2527+
default fn decode(_: &mut D) -> AttrId {
2528+
panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
25292529
}
25302530
}
25312531

compiler/rustc_ast/src/attr/mod.rs

+55-15
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
1111
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
1212
use crate::util::comments;
1313

14+
use rustc_data_structures::sync::WorkerLocal;
1415
use rustc_index::bit_set::GrowableBitSet;
1516
use rustc_span::source_map::BytePos;
1617
use rustc_span::symbol::{sym, Ident, Symbol};
1718
use rustc_span::Span;
1819

20+
use std::cell::Cell;
1921
use std::iter;
22+
#[cfg(debug_assertions)]
23+
use std::ops::BitXor;
24+
#[cfg(debug_assertions)]
25+
use std::sync::atomic::{AtomicU32, Ordering};
2026

2127
pub 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

364402
pub 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

388427
pub 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

397437
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {

compiler/rustc_ast_lowering/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1552,7 +1552,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15521552
let uc_nested = attr::mk_nested_word_item(uc_ident);
15531553
attr::mk_list_item(allow_ident, vec![uc_nested])
15541554
};
1555-
attr::mk_attr_outer(allow)
1555+
attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
15561556
};
15571557
let attrs: AttrVec = thin_vec![attr];
15581558

compiler/rustc_ast_pretty/src/pprust/state.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_span::source_map::{SourceMap, Spanned};
2222
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
2323
use rustc_span::{BytePos, FileName, Span};
2424

25+
use rustc_ast::attr::AttrIdGenerator;
2526
use std::borrow::Cow;
2627

2728
pub use self::delimited::IterDelimited;
@@ -107,6 +108,7 @@ pub fn print_crate<'a>(
107108
ann: &'a dyn PpAnn,
108109
is_expanded: bool,
109110
edition: Edition,
111+
g: &AttrIdGenerator,
110112
) -> String {
111113
let mut s =
112114
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
@@ -120,15 +122,15 @@ pub fn print_crate<'a>(
120122
// `#![feature(prelude_import)]`
121123
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
122124
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
123-
let fake_attr = attr::mk_attr_inner(list);
125+
let fake_attr = attr::mk_attr_inner(g, list);
124126
s.print_attribute(&fake_attr);
125127

126128
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
127129
// root, so this is not needed, and actually breaks things.
128130
if edition == Edition::Edition2015 {
129131
// `#![no_std]`
130132
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
131-
let fake_attr = attr::mk_attr_inner(no_std_meta);
133+
let fake_attr = attr::mk_attr_inner(g, no_std_meta);
132134
s.print_attribute(&fake_attr);
133135
}
134136
}

compiler/rustc_builtin_macros/src/cmdline_attrs.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
2828
continue;
2929
}
3030

31-
krate.attrs.push(mk_attr(AttrStyle::Inner, path, args, start_span.to(end_span)));
31+
krate.attrs.push(mk_attr(
32+
&parse_sess.attr_id_generator,
33+
AttrStyle::Inner,
34+
path,
35+
args,
36+
start_span.to(end_span),
37+
));
3238
}
3339

3440
krate

compiler/rustc_builtin_macros/src/derive.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ impl MultiItemModifier for Expander {
3232
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
3333
let template =
3434
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
35-
let attr = attr::mk_attr_outer(meta_item.clone());
35+
let attr =
36+
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
3637
validate_attr::check_builtin_attribute(
3738
&sess.parse_sess,
3839
&attr,

compiler/rustc_builtin_macros/src/test_harness.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
187187
let dc_nested =
188188
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
189189
let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
190-
let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
190+
let allow_dead_code = attr::mk_attr_outer(
191+
&self.sess.parse_sess.attr_id_generator,
192+
allow_dead_code_item,
193+
);
191194
let attrs = attrs
192195
.into_iter()
193196
.filter(|attr| {

compiler/rustc_driver/src/pretty.rs

+2
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ pub fn print_after_parsing(
396396
annotation.pp_ann(),
397397
false,
398398
parse.edition,
399+
&sess.parse_sess.attr_id_generator,
399400
)
400401
})
401402
}
@@ -438,6 +439,7 @@ pub fn print_after_hir_lowering<'tcx>(
438439
annotation.pp_ann(),
439440
true,
440441
parse.edition,
442+
&sess.parse_sess.attr_id_generator,
441443
)
442444
})
443445
}

compiler/rustc_expand/src/build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ impl<'a> ExtCtxt<'a> {
616616
}
617617

618618
pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
619-
attr::mk_attr_outer(mi)
619+
attr::mk_attr_outer(&self.sess.parse_sess.attr_id_generator, mi)
620620
}
621621

622622
pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem {

compiler/rustc_expand/src/config.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,13 @@ impl<'a> StripUnconfigured<'a> {
424424
);
425425
trees.push(bracket_group);
426426
let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));
427-
let attr = attr::mk_attr_from_item(item, tokens, attr.style, item_span);
427+
let attr = attr::mk_attr_from_item(
428+
&self.sess.parse_sess.attr_id_generator,
429+
item,
430+
tokens,
431+
attr.style,
432+
item_span,
433+
);
428434
if attr.has_name(sym::crate_type) {
429435
self.sess.parse_sess.buffer_lint(
430436
rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,

compiler/rustc_metadata/src/rmeta/decoder.rs

+7
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,13 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
450450
}
451451
}
452452

453+
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId {
454+
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ast::AttrId {
455+
let sess = d.sess.expect("can't decode AttrId without Session");
456+
sess.parse_sess.attr_id_generator.mk_attr_id()
457+
}
458+
}
459+
453460
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
454461
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext {
455462
let cdata = decoder.cdata();

compiler/rustc_parse/src/parser/attr.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ impl<'a> Parser<'a> {
8787
// Always make an outer attribute - this allows us to recover from a misplaced
8888
// inner attribute.
8989
Some(attr::mk_doc_comment(
90+
&self.sess.attr_id_generator,
9091
comment_kind,
9192
ast::AttrStyle::Outer,
9293
data,
@@ -138,7 +139,13 @@ impl<'a> Parser<'a> {
138139
this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
139140
}
140141

141-
Ok(attr::mk_attr_from_item(item, None, style, attr_sp))
142+
Ok(attr::mk_attr_from_item(
143+
&self.sess.attr_id_generator,
144+
item,
145+
None,
146+
style,
147+
attr_sp,
148+
))
142149
} else {
143150
let token_str = pprust::token_to_string(&this.token);
144151
let msg = &format!("expected `#`, found `{token_str}`");
@@ -291,7 +298,13 @@ impl<'a> Parser<'a> {
291298
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
292299
if attr_style == ast::AttrStyle::Inner {
293300
self.bump();
294-
Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span))
301+
Some(attr::mk_doc_comment(
302+
&self.sess.attr_id_generator,
303+
comment_kind,
304+
attr_style,
305+
data,
306+
self.prev_token.span,
307+
))
295308
} else {
296309
None
297310
}

compiler/rustc_session/src/parse.rs

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_span::hygiene::ExpnId;
2121
use rustc_span::source_map::{FilePathMapping, SourceMap};
2222
use rustc_span::{Span, Symbol};
2323

24+
use rustc_ast::attr::AttrIdGenerator;
2425
use std::str;
2526

2627
/// The set of keys (and, optionally, values) that define the compilation
@@ -219,6 +220,8 @@ pub struct ParseSess {
219220
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
220221
/// identifier represented by its position in the vector.
221222
pub proc_macro_quoted_spans: Lock<Vec<Span>>,
223+
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
224+
pub attr_id_generator: AttrIdGenerator,
222225
}
223226

224227
impl ParseSess {
@@ -257,6 +260,7 @@ impl ParseSess {
257260
type_ascription_path_suggestions: Default::default(),
258261
assume_incomplete_release: false,
259262
proc_macro_quoted_spans: Default::default(),
263+
attr_id_generator: AttrIdGenerator::new(),
260264
}
261265
}
262266

0 commit comments

Comments
 (0)