Shrink Nonterminal.

By heap allocating the argument within `NtPath`, `NtVis`, and `NtStmt`.
This slightly reduces cumulative and peak allocation amounts, most
notably on `deep-vector`.
This commit is contained in:
Nicholas Nethercote 2022-04-06 12:08:39 +10:00
parent c2afaba465
commit d9592c2d9f
10 changed files with 18 additions and 16 deletions

View File

@ -439,7 +439,7 @@ impl MetaItem {
} }
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
token::Nonterminal::NtPath(ref path) => path.clone(), token::Nonterminal::NtPath(ref path) => (**path).clone(),
_ => return None, _ => return None,
}, },
_ => return None, _ => return None,

View File

@ -772,7 +772,9 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
token::NtBlock(block) => vis.visit_block(block), token::NtBlock(block) => vis.visit_block(block),
token::NtStmt(stmt) => visit_clobber(stmt, |stmt| { token::NtStmt(stmt) => visit_clobber(stmt, |stmt| {
// See reasoning above. // See reasoning above.
stmt.map(|stmt| {
vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item")
})
}), }),
token::NtPat(pat) => vis.visit_pat(pat), token::NtPat(pat) => vis.visit_pat(pat),
token::NtExpr(expr) => vis.visit_expr(expr), token::NtExpr(expr) => vis.visit_expr(expr),

View File

@ -668,7 +668,7 @@ impl PartialEq<TokenKind> for Token {
pub enum Nonterminal { pub enum Nonterminal {
NtItem(P<ast::Item>), NtItem(P<ast::Item>),
NtBlock(P<ast::Block>), NtBlock(P<ast::Block>),
NtStmt(ast::Stmt), NtStmt(P<ast::Stmt>),
NtPat(P<ast::Pat>), NtPat(P<ast::Pat>),
NtExpr(P<ast::Expr>), NtExpr(P<ast::Expr>),
NtTy(P<ast::Ty>), NtTy(P<ast::Ty>),
@ -677,13 +677,13 @@ pub enum Nonterminal {
NtLiteral(P<ast::Expr>), NtLiteral(P<ast::Expr>),
/// Stuff inside brackets for attributes /// Stuff inside brackets for attributes
NtMeta(P<ast::AttrItem>), NtMeta(P<ast::AttrItem>),
NtPath(ast::Path), NtPath(P<ast::Path>),
NtVis(ast::Visibility), NtVis(P<ast::Visibility>),
} }
// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Nonterminal, 48); rustc_data_structures::static_assert_size!(Nonterminal, 16);
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind { pub enum NonterminalKind {

View File

@ -118,7 +118,7 @@ impl Annotatable {
Annotatable::ForeignItem(item) => { Annotatable::ForeignItem(item) => {
token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
} }
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), Annotatable::Stmt(stmt) => token::NtStmt(stmt),
Annotatable::Expr(expr) => token::NtExpr(expr), Annotatable::Expr(expr) => token::NtExpr(expr),
Annotatable::Arm(..) Annotatable::Arm(..)
| Annotatable::ExprField(..) | Annotatable::ExprField(..)

View File

@ -90,7 +90,7 @@ impl MultiItemModifier for ProcMacroDerive {
// A proc macro can't observe the fact that we're passing // A proc macro can't observe the fact that we're passing
// them an `NtStmt` - it can only see the underlying tokens // them an `NtStmt` - it can only see the underlying tokens
// of the wrapped item // of the wrapped item
token::NtStmt(stmt.into_inner()) token::NtStmt(stmt)
} }
_ => unreachable!(), _ => unreachable!(),
}; };

View File

@ -41,7 +41,7 @@ macro_rules! maybe_whole_expr {
return Ok(e); return Ok(e);
} }
token::NtPath(path) => { token::NtPath(path) => {
let path = path.clone(); let path = (**path).clone();
$p.bump(); $p.bump();
return Ok($p.mk_expr( return Ok($p.mk_expr(
$p.prev_token.span, $p.prev_token.span,

View File

@ -1289,7 +1289,7 @@ impl<'a> Parser<'a> {
/// so emit a proper diagnostic. /// so emit a proper diagnostic.
// Public for rustfmt usage. // Public for rustfmt usage.
pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
maybe_whole!(self, NtVis, |x| x); maybe_whole!(self, NtVis, |x| x.into_inner());
self.expected_tokens.push(TokenType::Keyword(kw::Crate)); self.expected_tokens.push(TokenType::Keyword(kw::Crate));
if self.is_crate_vis() { if self.is_crate_vis() {

View File

@ -118,7 +118,7 @@ impl<'a> Parser<'a> {
token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
} }
NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
Some(s) => token::NtStmt(s), Some(s) => token::NtStmt(P(s)),
None => { None => {
return Err(self.struct_span_err(self.token.span, "expected a statement")); return Err(self.struct_span_err(self.token.span, "expected a statement"));
} }
@ -161,11 +161,11 @@ impl<'a> Parser<'a> {
return Err(self.struct_span_err(self.token.span, msg)); return Err(self.struct_span_err(self.token.span, msg));
} }
NonterminalKind::Path => token::NtPath( NonterminalKind::Path => token::NtPath(
self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
), ),
NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
NonterminalKind::Vis => token::NtVis( NonterminalKind::Vis => token::NtVis(
self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?),
), ),
NonterminalKind::Lifetime => { NonterminalKind::Lifetime => {
if self.check_lifetime() { if self.check_lifetime() {

View File

@ -165,7 +165,7 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtPath, |path| { maybe_whole!(self, NtPath, |path| {
reject_generics_if_mod_style(self, &path); reject_generics_if_mod_style(self, &path);
path path.into_inner()
}); });
if let token::Interpolated(nt) = &self.token.kind { if let token::Interpolated(nt) = &self.token.kind {

View File

@ -54,7 +54,7 @@ impl<'a> Parser<'a> {
stmt.visit_attrs(|stmt_attrs| { stmt.visit_attrs(|stmt_attrs| {
attrs.prepend_to_nt_inner(stmt_attrs); attrs.prepend_to_nt_inner(stmt_attrs);
}); });
return Ok(Some(stmt)); return Ok(Some(stmt.into_inner()));
} }
Ok(Some(if self.token.is_keyword(kw::Let) { Ok(Some(if self.token.is_keyword(kw::Let) {
@ -535,7 +535,7 @@ impl<'a> Parser<'a> {
recover: AttemptLocalParseRecovery, recover: AttemptLocalParseRecovery,
) -> PResult<'a, Option<Stmt>> { ) -> PResult<'a, Option<Stmt>> {
// Skip looking for a trailing semicolon when we have an interpolated statement. // Skip looking for a trailing semicolon when we have an interpolated statement.
maybe_whole!(self, NtStmt, |x| Some(x)); maybe_whole!(self, NtStmt, |x| Some(x.into_inner()));
let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else {
return Ok(None); return Ok(None);