Skip to content

Commit 14cb3c7

Browse files
committed
perf(parser): simplify getting span of identifiers and literals (#11323)
Small optimization. For identifiers and literals, the span of the AST node is the same as the span of the `Token`. So just get the whole span from the `Token` in one access, and avoid the dance of assembling the span by calling `start_span` and then `end_span`.
1 parent 2372f00 commit 14cb3c7

File tree

2 files changed

+20
-34
lines changed

2 files changed

+20
-34
lines changed

crates/oxc_parser/src/js/expression.rs

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ impl<'a> ParserImpl<'a> {
112112

113113
#[inline]
114114
pub(crate) fn parse_identifier_kind(&mut self, kind: Kind) -> (Span, Atom<'a>) {
115-
let span = self.start_span();
115+
let span = self.cur_token().span();
116116
let name = self.cur_string();
117117
self.bump_remap(kind);
118-
(self.end_span(span), Atom::from(name))
118+
(span, Atom::from(name))
119119
}
120120

121121
pub(crate) fn check_identifier(&mut self, kind: Kind, ctx: Context) {
@@ -134,10 +134,10 @@ impl<'a> ParserImpl<'a> {
134134
/// # `IdentifierName`
135135
/// # Panics
136136
pub(crate) fn parse_private_identifier(&mut self) -> PrivateIdentifier<'a> {
137-
let span = self.start_span();
137+
let span = self.cur_token().span();
138138
let name = Atom::from(self.cur_string());
139139
self.bump_any();
140-
self.ast.private_identifier(self.end_span(span), name)
140+
self.ast.private_identifier(span, name)
141141
}
142142

143143
/// Section [Primary Expression](https://tc39.es/ecma262/#sec-primary-expression)
@@ -281,14 +281,14 @@ impl<'a> ParserImpl<'a> {
281281
}
282282

283283
pub(crate) fn parse_literal_null(&mut self) -> NullLiteral {
284-
let span = self.start_span();
284+
let span = self.cur_token().span();
285285
self.bump_any(); // bump `null`
286-
self.ast.null_literal(self.end_span(span))
286+
self.ast.null_literal(span)
287287
}
288288

289289
pub(crate) fn parse_literal_number(&mut self) -> NumericLiteral<'a> {
290-
let span = self.start_span();
291290
let token = self.cur_token();
291+
let span = token.span();
292292
let src = self.cur_src();
293293
let value = match token.kind() {
294294
Kind::Decimal | Kind::Binary | Kind::Octal | Kind::Hex => {
@@ -300,7 +300,7 @@ impl<'a> ParserImpl<'a> {
300300
_ => unreachable!(),
301301
};
302302
let value = value.unwrap_or_else(|err| {
303-
self.set_fatal_error(diagnostics::invalid_number(err, token.span()));
303+
self.set_fatal_error(diagnostics::invalid_number(err, span));
304304
0.0 // Dummy value
305305
});
306306
let base = match token.kind() {
@@ -319,11 +319,10 @@ impl<'a> ParserImpl<'a> {
319319
_ => return self.unexpected(),
320320
};
321321
self.bump_any();
322-
self.ast.numeric_literal(self.end_span(span), value, Some(Atom::from(src)), base)
322+
self.ast.numeric_literal(span, value, Some(Atom::from(src)), base)
323323
}
324324

325325
pub(crate) fn parse_literal_bigint(&mut self) -> BigIntLiteral<'a> {
326-
let span = self.start_span();
327326
let base = match self.cur_kind() {
328327
Kind::Decimal => BigintBase::Decimal,
329328
Kind::Binary => BigintBase::Binary,
@@ -332,24 +331,25 @@ impl<'a> ParserImpl<'a> {
332331
_ => return self.unexpected(),
333332
};
334333
let token = self.cur_token();
334+
let span = token.span();
335335
let raw = self.cur_src();
336336
let src = raw.strip_suffix('n').unwrap();
337337
let _value = parse_big_int(src, token.kind(), token.has_separator())
338-
.map_err(|err| diagnostics::invalid_number(err, token.span()));
338+
.map_err(|err| diagnostics::invalid_number(err, span));
339339
self.bump_any();
340-
self.ast.big_int_literal(self.end_span(span), raw, base)
340+
self.ast.big_int_literal(span, raw, base)
341341
}
342342

343343
pub(crate) fn parse_literal_regexp(&mut self) -> RegExpLiteral<'a> {
344-
let span = self.start_span();
345344
let (pattern_end, flags, flags_error) = self.read_regex();
346345
if !self.lexer.errors.is_empty() {
347346
return self.unexpected();
348347
}
349-
let pattern_start = self.cur_token().start() + 1; // +1 to exclude left `/`
348+
let span = self.cur_token().span();
349+
let pattern_start = span.start + 1; // +1 to exclude left `/`
350350
let pattern_text = &self.source_text[pattern_start as usize..pattern_end as usize];
351351
let flags_start = pattern_end + 1; // +1 to include right `/`
352-
let flags_text = &self.source_text[flags_start as usize..self.cur_token().end() as usize];
352+
let flags_text = &self.source_text[flags_start as usize..span.end as usize];
353353
let raw = self.cur_src();
354354
self.bump_any();
355355

@@ -368,11 +368,7 @@ impl<'a> ParserImpl<'a> {
368368

369369
let pattern = RegExpPattern { text: Atom::from(pattern_text), pattern };
370370

371-
self.ast.reg_exp_literal(
372-
self.end_span(span),
373-
RegExp { pattern, flags },
374-
Some(Atom::from(raw)),
375-
)
371+
self.ast.reg_exp_literal(span, RegExp { pattern, flags }, Some(Atom::from(raw)))
376372
}
377373

378374
#[cfg(feature = "regular_expression")]
@@ -404,16 +400,11 @@ impl<'a> ParserImpl<'a> {
404400
if !self.at(Kind::Str) {
405401
return self.unexpected();
406402
}
403+
let span = self.cur_token().span();
404+
let raw = Atom::from(self.cur_src());
407405
let value = self.cur_string();
408-
let span = self.start_span();
409406
let lone_surrogates = self.cur_token().lone_surrogates();
410407
self.bump_any();
411-
let span = self.end_span(span);
412-
// SAFETY:
413-
// range comes from the lexer, which are ensured to meeting the criteria of `get_unchecked`.
414-
let raw = Atom::from(unsafe {
415-
self.source_text.get_unchecked(span.start as usize..span.end as usize)
416-
});
417408
self.ast.string_literal_with_lone_surrogates(span, value, Some(raw), lone_surrogates)
418409
}
419410

crates/oxc_parser/src/jsx/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,15 +433,10 @@ impl<'a> ParserImpl<'a> {
433433
}
434434

435435
fn parse_jsx_text(&mut self) -> Box<'a, JSXText<'a>> {
436-
let span = self.start_span();
436+
let span = self.cur_token().span();
437+
let raw = Atom::from(self.cur_src());
437438
let value = Atom::from(self.cur_string());
438439
self.bump_any();
439-
let span = self.end_span(span);
440-
// SAFETY:
441-
// range comes from the lexer, which are ensured to meeting the criteria of `get_unchecked`.
442-
let raw = Atom::from(unsafe {
443-
self.source_text.get_unchecked(span.start as usize..span.end as usize)
444-
});
445440
self.ast.alloc_jsx_text(span, value, Some(raw))
446441
}
447442

0 commit comments

Comments
 (0)