mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #101313 - SparrowLii:mk_attr_id, r=cjgillot
make `mk_attr_id` part of `ParseSess` Updates #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 #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`
This commit is contained in:
commit
750bd1a7ff
@ -2524,8 +2524,8 @@ impl<S: Encoder> Encodable<S> for AttrId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Decoder> Decodable<D> for AttrId {
|
impl<D: Decoder> Decodable<D> for AttrId {
|
||||||
fn decode(_: &mut D) -> AttrId {
|
default fn decode(_: &mut D) -> AttrId {
|
||||||
crate::attr::mk_attr_id()
|
panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,12 +11,18 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
|||||||
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
||||||
use crate::util::comments;
|
use crate::util::comments;
|
||||||
|
|
||||||
|
use rustc_data_structures::sync::WorkerLocal;
|
||||||
use rustc_index::bit_set::GrowableBitSet;
|
use rustc_index::bit_set::GrowableBitSet;
|
||||||
use rustc_span::source_map::BytePos;
|
use rustc_span::source_map::BytePos;
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
use std::ops::BitXor;
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
|
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
|
||||||
|
|
||||||
@ -346,22 +352,55 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
|
|||||||
NestedMetaItem::MetaItem(mk_word_item(ident))
|
NestedMetaItem::MetaItem(mk_word_item(ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mk_attr_id() -> AttrId {
|
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||||
use std::sync::atomic::AtomicU32;
|
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
|
|
||||||
static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
|
#[cfg(debug_assertions)]
|
||||||
|
static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
|
||||||
|
|
||||||
let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
|
impl AttrIdGenerator {
|
||||||
assert!(id != u32::MAX);
|
pub fn new() -> Self {
|
||||||
AttrId::from_u32(id)
|
// We use `(index as u32).reverse_bits()` to initialize the
|
||||||
|
// starting value of AttrId in each worker thread.
|
||||||
|
// The `index` is the index of the worker thread.
|
||||||
|
// This ensures that the AttrId generated in each thread is unique.
|
||||||
|
AttrIdGenerator(WorkerLocal::new(|index| {
|
||||||
|
let index: u32 = index.try_into().unwrap();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
|
||||||
|
MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell::new(index.reverse_bits())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mk_attr_id(&self) -> AttrId {
|
||||||
|
let id = self.0.get();
|
||||||
|
|
||||||
|
// Ensure the assigned attr_id does not overlap the bits
|
||||||
|
// representing the number of threads.
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
|
||||||
|
|
||||||
|
self.0.set(id + 1);
|
||||||
|
AttrId::from_u32(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
|
pub fn mk_attr(
|
||||||
mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
|
g: &AttrIdGenerator,
|
||||||
|
style: AttrStyle,
|
||||||
|
path: Path,
|
||||||
|
args: MacArgs,
|
||||||
|
span: Span,
|
||||||
|
) -> Attribute {
|
||||||
|
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_attr_from_item(
|
pub fn mk_attr_from_item(
|
||||||
|
g: &AttrIdGenerator,
|
||||||
item: AttrItem,
|
item: AttrItem,
|
||||||
tokens: Option<LazyAttrTokenStream>,
|
tokens: Option<LazyAttrTokenStream>,
|
||||||
style: AttrStyle,
|
style: AttrStyle,
|
||||||
@ -369,29 +408,30 @@ pub fn mk_attr_from_item(
|
|||||||
) -> Attribute {
|
) -> Attribute {
|
||||||
Attribute {
|
Attribute {
|
||||||
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
|
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
|
||||||
id: mk_attr_id(),
|
id: g.mk_attr_id(),
|
||||||
style,
|
style,
|
||||||
span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an inner attribute with the given value and span.
|
/// Returns an inner attribute with the given value and span.
|
||||||
pub fn mk_attr_inner(item: MetaItem) -> Attribute {
|
pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||||
mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
|
mk_attr(g, AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an outer attribute with the given value and span.
|
/// Returns an outer attribute with the given value and span.
|
||||||
pub fn mk_attr_outer(item: MetaItem) -> Attribute {
|
pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||||
mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
|
mk_attr(g, AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_doc_comment(
|
pub fn mk_doc_comment(
|
||||||
|
g: &AttrIdGenerator,
|
||||||
comment_kind: CommentKind,
|
comment_kind: CommentKind,
|
||||||
style: AttrStyle,
|
style: AttrStyle,
|
||||||
data: Symbol,
|
data: Symbol,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Attribute {
|
) -> Attribute {
|
||||||
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span }
|
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
||||||
|
@ -1552,7 +1552,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let uc_nested = attr::mk_nested_word_item(uc_ident);
|
let uc_nested = attr::mk_nested_word_item(uc_ident);
|
||||||
attr::mk_list_item(allow_ident, vec![uc_nested])
|
attr::mk_list_item(allow_ident, vec![uc_nested])
|
||||||
};
|
};
|
||||||
attr::mk_attr_outer(allow)
|
attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
|
||||||
};
|
};
|
||||||
let attrs: AttrVec = thin_vec![attr];
|
let attrs: AttrVec = thin_vec![attr];
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ use rustc_span::source_map::{SourceMap, Spanned};
|
|||||||
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
||||||
use rustc_span::{BytePos, FileName, Span};
|
use rustc_span::{BytePos, FileName, Span};
|
||||||
|
|
||||||
|
use rustc_ast::attr::AttrIdGenerator;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub use self::delimited::IterDelimited;
|
pub use self::delimited::IterDelimited;
|
||||||
@ -107,6 +108,7 @@ pub fn print_crate<'a>(
|
|||||||
ann: &'a dyn PpAnn,
|
ann: &'a dyn PpAnn,
|
||||||
is_expanded: bool,
|
is_expanded: bool,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
|
g: &AttrIdGenerator,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut s =
|
let mut s =
|
||||||
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
|
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
|
||||||
@ -120,7 +122,7 @@ pub fn print_crate<'a>(
|
|||||||
// `#![feature(prelude_import)]`
|
// `#![feature(prelude_import)]`
|
||||||
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
|
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
|
||||||
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
||||||
let fake_attr = attr::mk_attr_inner(list);
|
let fake_attr = attr::mk_attr_inner(g, list);
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
|
|
||||||
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
||||||
@ -128,7 +130,7 @@ pub fn print_crate<'a>(
|
|||||||
if edition == Edition::Edition2015 {
|
if edition == Edition::Edition2015 {
|
||||||
// `#![no_std]`
|
// `#![no_std]`
|
||||||
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
|
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
|
||||||
let fake_attr = attr::mk_attr_inner(no_std_meta);
|
let fake_attr = attr::mk_attr_inner(g, no_std_meta);
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
krate.attrs.push(mk_attr(AttrStyle::Inner, path, args, start_span.to(end_span)));
|
krate.attrs.push(mk_attr(
|
||||||
|
&parse_sess.attr_id_generator,
|
||||||
|
AttrStyle::Inner,
|
||||||
|
path,
|
||||||
|
args,
|
||||||
|
start_span.to(end_span),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
krate
|
krate
|
||||||
|
@ -32,7 +32,8 @@ impl MultiItemModifier for Expander {
|
|||||||
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
||||||
let template =
|
let template =
|
||||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||||
let attr = attr::mk_attr_outer(meta_item.clone());
|
let attr =
|
||||||
|
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
|
||||||
validate_attr::check_builtin_attribute(
|
validate_attr::check_builtin_attribute(
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
&attr,
|
&attr,
|
||||||
|
@ -187,7 +187,10 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
|||||||
let dc_nested =
|
let dc_nested =
|
||||||
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
|
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
|
||||||
let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
|
let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
|
||||||
let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
|
let allow_dead_code = attr::mk_attr_outer(
|
||||||
|
&self.sess.parse_sess.attr_id_generator,
|
||||||
|
allow_dead_code_item,
|
||||||
|
);
|
||||||
let attrs = attrs
|
let attrs = attrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|attr| {
|
.filter(|attr| {
|
||||||
|
@ -396,6 +396,7 @@ pub fn print_after_parsing(
|
|||||||
annotation.pp_ann(),
|
annotation.pp_ann(),
|
||||||
false,
|
false,
|
||||||
parse.edition,
|
parse.edition,
|
||||||
|
&sess.parse_sess.attr_id_generator,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -438,6 +439,7 @@ pub fn print_after_hir_lowering<'tcx>(
|
|||||||
annotation.pp_ann(),
|
annotation.pp_ann(),
|
||||||
true,
|
true,
|
||||||
parse.edition,
|
parse.edition,
|
||||||
|
&sess.parse_sess.attr_id_generator,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -616,7 +616,7 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
|
pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
|
||||||
attr::mk_attr_outer(mi)
|
attr::mk_attr_outer(&self.sess.parse_sess.attr_id_generator, mi)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem {
|
pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem {
|
||||||
|
@ -424,7 +424,13 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
);
|
);
|
||||||
trees.push(bracket_group);
|
trees.push(bracket_group);
|
||||||
let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));
|
let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));
|
||||||
let attr = attr::mk_attr_from_item(item, tokens, attr.style, item_span);
|
let attr = attr::mk_attr_from_item(
|
||||||
|
&self.sess.parse_sess.attr_id_generator,
|
||||||
|
item,
|
||||||
|
tokens,
|
||||||
|
attr.style,
|
||||||
|
item_span,
|
||||||
|
);
|
||||||
if attr.has_name(sym::crate_type) {
|
if attr.has_name(sym::crate_type) {
|
||||||
self.sess.parse_sess.buffer_lint(
|
self.sess.parse_sess.buffer_lint(
|
||||||
rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
||||||
|
@ -450,6 +450,13 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId {
|
||||||
|
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ast::AttrId {
|
||||||
|
let sess = d.sess.expect("can't decode AttrId without Session");
|
||||||
|
sess.parse_sess.attr_id_generator.mk_attr_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
|
||||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext {
|
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext {
|
||||||
let cdata = decoder.cdata();
|
let cdata = decoder.cdata();
|
||||||
|
@ -87,6 +87,7 @@ impl<'a> Parser<'a> {
|
|||||||
// Always make an outer attribute - this allows us to recover from a misplaced
|
// Always make an outer attribute - this allows us to recover from a misplaced
|
||||||
// inner attribute.
|
// inner attribute.
|
||||||
Some(attr::mk_doc_comment(
|
Some(attr::mk_doc_comment(
|
||||||
|
&self.sess.attr_id_generator,
|
||||||
comment_kind,
|
comment_kind,
|
||||||
ast::AttrStyle::Outer,
|
ast::AttrStyle::Outer,
|
||||||
data,
|
data,
|
||||||
@ -138,7 +139,13 @@ impl<'a> Parser<'a> {
|
|||||||
this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
|
this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(attr::mk_attr_from_item(item, None, style, attr_sp))
|
Ok(attr::mk_attr_from_item(
|
||||||
|
&self.sess.attr_id_generator,
|
||||||
|
item,
|
||||||
|
None,
|
||||||
|
style,
|
||||||
|
attr_sp,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
let token_str = pprust::token_to_string(&this.token);
|
let token_str = pprust::token_to_string(&this.token);
|
||||||
let msg = &format!("expected `#`, found `{token_str}`");
|
let msg = &format!("expected `#`, found `{token_str}`");
|
||||||
@ -291,7 +298,13 @@ impl<'a> Parser<'a> {
|
|||||||
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
|
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
|
||||||
if attr_style == ast::AttrStyle::Inner {
|
if attr_style == ast::AttrStyle::Inner {
|
||||||
self.bump();
|
self.bump();
|
||||||
Some(attr::mk_doc_comment(comment_kind, attr_style, data, self.prev_token.span))
|
Some(attr::mk_doc_comment(
|
||||||
|
&self.sess.attr_id_generator,
|
||||||
|
comment_kind,
|
||||||
|
attr_style,
|
||||||
|
data,
|
||||||
|
self.prev_token.span,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ use rustc_span::hygiene::ExpnId;
|
|||||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
|
use rustc_ast::attr::AttrIdGenerator;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// The set of keys (and, optionally, values) that define the compilation
|
/// The set of keys (and, optionally, values) that define the compilation
|
||||||
@ -219,6 +220,8 @@ pub struct ParseSess {
|
|||||||
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
|
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
|
||||||
/// identifier represented by its position in the vector.
|
/// identifier represented by its position in the vector.
|
||||||
pub proc_macro_quoted_spans: Lock<Vec<Span>>,
|
pub proc_macro_quoted_spans: Lock<Vec<Span>>,
|
||||||
|
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
|
||||||
|
pub attr_id_generator: AttrIdGenerator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
@ -257,6 +260,7 @@ impl ParseSess {
|
|||||||
type_ascription_path_suggestions: Default::default(),
|
type_ascription_path_suggestions: Default::default(),
|
||||||
assume_incomplete_release: false,
|
assume_incomplete_release: false,
|
||||||
proc_macro_quoted_spans: Default::default(),
|
proc_macro_quoted_spans: Default::default(),
|
||||||
|
attr_id_generator: AttrIdGenerator::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user