Skip to content

Commit 64137f0

Browse files
committed
Auto merge of rust-lang#94693 - nnethercote:parser-inlining, r=petrochenkov
Inline some parser functions Some crates that do a lot of complex declarative macro expansion spend a lot of time parsing (and reparsing) tokens. These commits inline some functions for some minor speed wins. r? `@ghost`
2 parents 3ea4493 + f8f1d3f commit 64137f0

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

compiler/rustc_parse/src/parser/attr_wrapper.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ rustc_data_structures::static_assert_size!(LazyTokenStreamImpl, 144);
100100

101101
impl CreateTokenStream for LazyTokenStreamImpl {
102102
fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
103-
// The token produced by the final call to `next` or `next_desugared`
104-
// was not actually consumed by the callback. The combination
105-
// of chaining the initial token and using `take` produces the desired
106-
// result - we produce an empty `TokenStream` if no calls were made,
107-
// and omit the final token otherwise.
103+
// The token produced by the final call to `{,inlined_}next` or
104+
// `{,inlined_}next_desugared` was not actually consumed by the
105+
// callback. The combination of chaining the initial token and using
106+
// `take` produces the desired result - we produce an empty
107+
// `TokenStream` if no calls were made, and omit the final token
108+
// otherwise.
108109
let mut cursor_snapshot = self.cursor_snapshot.clone();
109110
let tokens =
110111
std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1))

compiler/rustc_parse/src/parser/mod.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,9 @@ struct TokenCursor {
206206
frame: TokenCursorFrame,
207207
stack: Vec<TokenCursorFrame>,
208208
desugar_doc_comments: bool,
209-
// Counts the number of calls to `next` or `next_desugared`,
210-
// depending on whether `desugar_doc_comments` is set.
209+
// Counts the number of calls to `{,inlined_}next` or
210+
// `{,inlined_}next_desugared`, depending on whether
211+
// `desugar_doc_comments` is set.
211212
num_next_calls: usize,
212213
// During parsing, we may sometimes need to 'unglue' a
213214
// glued token into two component tokens
@@ -256,6 +257,12 @@ impl TokenCursorFrame {
256257

257258
impl TokenCursor {
258259
fn next(&mut self) -> (Token, Spacing) {
260+
self.inlined_next()
261+
}
262+
263+
/// This always-inlined version should only be used on hot code paths.
264+
#[inline(always)]
265+
fn inlined_next(&mut self) -> (Token, Spacing) {
259266
loop {
260267
let (tree, spacing) = if !self.frame.open_delim {
261268
self.frame.open_delim = true;
@@ -285,7 +292,13 @@ impl TokenCursor {
285292
}
286293

287294
fn next_desugared(&mut self) -> (Token, Spacing) {
288-
let (data, attr_style, sp) = match self.next() {
295+
self.inlined_next_desugared()
296+
}
297+
298+
/// This always-inlined version should only be used on hot code paths.
299+
#[inline(always)]
300+
fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
301+
let (data, attr_style, sp) = match self.inlined_next() {
289302
(Token { kind: token::DocComment(_, attr_style, data), span }, _) => {
290303
(data, attr_style, span)
291304
}
@@ -463,12 +476,13 @@ impl<'a> Parser<'a> {
463476
parser
464477
}
465478

479+
#[inline]
466480
fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) {
467481
loop {
468482
let (mut next, spacing) = if self.desugar_doc_comments {
469-
self.token_cursor.next_desugared()
483+
self.token_cursor.inlined_next_desugared()
470484
} else {
471-
self.token_cursor.next()
485+
self.token_cursor.inlined_next()
472486
};
473487
self.token_cursor.num_next_calls += 1;
474488
// We've retrieved an token from the underlying
@@ -998,7 +1012,13 @@ impl<'a> Parser<'a> {
9981012
}
9991013

10001014
/// Advance the parser by one token using provided token as the next one.
1001-
fn bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
1015+
fn bump_with(&mut self, next: (Token, Spacing)) {
1016+
self.inlined_bump_with(next)
1017+
}
1018+
1019+
/// This always-inlined version should only be used on hot code paths.
1020+
#[inline(always)]
1021+
fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
10021022
// Bumping after EOF is a bad sign, usually an infinite loop.
10031023
if self.prev_token.kind == TokenKind::Eof {
10041024
let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
@@ -1016,7 +1036,7 @@ impl<'a> Parser<'a> {
10161036
/// Advance the parser by one token.
10171037
pub fn bump(&mut self) {
10181038
let next_token = self.next_tok(self.token.span);
1019-
self.bump_with(next_token);
1039+
self.inlined_bump_with(next_token);
10201040
}
10211041

10221042
/// Look-ahead `dist` tokens of `self.token` and get access to that token there.

0 commit comments

Comments
 (0)