perf(parser): allocate AST nodes in arena directly#23712
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
Pull request overview
This PR applies small performance-focused refactors in oxc_parser to allocate AST nodes directly in the arena (and/or return already-boxed nodes) to reduce intermediate stack allocations and copies during parsing.
Changes:
- Return
Box<'a, T>from several parsing helpers when the produced AST node is always boxed in the AST (e.g. literals,usingdeclarations, TS import attributes object). - Replace “build then
alloc” patterns withAstBuilder::alloc_*constructors (e.g.alloc_identifier_name,alloc_object_expression,alloc_*_literal). - Thread boxed nodes through call sites to avoid extra
self.alloc(...)steps.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| crates/oxc_parser/src/ts/types.rs | Allocate TS import type option/attribute AST nodes directly in the arena; return boxed object expressions where required. |
| crates/oxc_parser/src/js/statement.rs | Pass already-boxed using declarations into parse_any_for_loop without re-boxing. |
| crates/oxc_parser/src/js/expression.rs | Return boxed literal nodes and construct Expression::*Literal variants without intermediate allocations. |
| crates/oxc_parser/src/js/declaration.rs | Make parse_using_declaration return a boxed VariableDeclaration and propagate that to statement construction. |
| crates/oxc_parser/src/js/binding.rs | Make rest-element parsing return boxed rest elements and pass them through binding-pattern builders directly. |
| crates/oxc_parser/src/cursor.rs | Update parse_delimited_list_with_rest to return an optional boxed rest element to match binding parser changes. |
c94b543 to
ca1a2ae
Compare
6853db4 to
35f8681
Compare
ca1a2ae to
644b3d0
Compare
35f8681 to
4149490
Compare
4149490 to
b57ac10
Compare
) Optimization to parsing JSX. When parsing JSX element names `parse_jsx_element_name` has to determine if the identifier: 1. starts with a lowercase letter, and 2. contains a `-`. The 2nd check is relatively expensive - string search. Avoid the search by making the lexer feed this information (which it already has) to the parser. This reduces the check in the parser to just `!contains_dash`. (came across this while working #23712)

Same as #23709.
Small perf optimizations around AST builder calls.
Boxes, allocate into theBoxas early as possible, to increase chance compiler sees the type can be built directly in arena, rather than built on the stack, and then copied from stack into arena.Box<T>rather thanTwhere the value needs to be boxed anyway. If function is not inlined, this avoids stack allocation + copy.Also, shorten code where possible by using more specific
AstBuildermethods.