perf(ast): box ImportDeclarationSpecifier enum variants (#3061)

Part of #3047.

As with #3058, it's hard to interpret the benchmark results here. But in
this case I think it's easier to see from "first principles" that this
should be an improvement - `ImportSpecifier` is pretty massive (80
bytes) vs `ImportDefaultSpecifier` (40 bytes), and the latter (e.g.
`import React from 'react'`) is common in JS code.
This commit is contained in:
overlookmotel 2024-04-22 02:06:39 +01:00 committed by GitHub
parent 2804e7dbf6
commit 383b449d4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 15 deletions

View file

@ -2373,11 +2373,11 @@ pub struct ImportDeclaration<'a> {
pub enum ImportDeclarationSpecifier<'a> { pub enum ImportDeclarationSpecifier<'a> {
/// import {imported} from "source" /// import {imported} from "source"
/// import {imported as local} from "source" /// import {imported as local} from "source"
ImportSpecifier(ImportSpecifier<'a>), ImportSpecifier(Box<'a, ImportSpecifier<'a>>),
/// import local from "source" /// import local from "source"
ImportDefaultSpecifier(ImportDefaultSpecifier<'a>), ImportDefaultSpecifier(Box<'a, ImportDefaultSpecifier<'a>>),
/// import * as local from "source" /// import * as local from "source"
ImportNamespaceSpecifier(ImportNamespaceSpecifier<'a>), ImportNamespaceSpecifier(Box<'a, ImportNamespaceSpecifier<'a>>),
} }
// import {imported} from "source" // import {imported} from "source"

View file

@ -107,10 +107,9 @@ impl<'a> ParserImpl<'a> {
fn parse_import_default_specifier(&mut self) -> Result<ImportDeclarationSpecifier<'a>> { fn parse_import_default_specifier(&mut self) -> Result<ImportDeclarationSpecifier<'a>> {
let span = self.start_span(); let span = self.start_span();
let local = self.parse_binding_identifier()?; let local = self.parse_binding_identifier()?;
Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier(ImportDefaultSpecifier { Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier(
span: self.end_span(span), self.ast.alloc(ImportDefaultSpecifier { span: self.end_span(span), local }),
local, ))
}))
} }
// import * as name from "module-name" // import * as name from "module-name"
@ -119,10 +118,9 @@ impl<'a> ParserImpl<'a> {
self.bump_any(); // advance `*` self.bump_any(); // advance `*`
self.expect(Kind::As)?; self.expect(Kind::As)?;
let local = self.parse_binding_identifier()?; let local = self.parse_binding_identifier()?;
Ok(ImportDeclarationSpecifier::ImportNamespaceSpecifier(ImportNamespaceSpecifier { Ok(ImportDeclarationSpecifier::ImportNamespaceSpecifier(
span: self.end_span(span), self.ast.alloc(ImportNamespaceSpecifier { span: self.end_span(span), local }),
local, ))
}))
} }
// import { export1 , export2 as alias2 , [...] } from "module-name"; // import { export1 , export2 as alias2 , [...] } from "module-name";
@ -384,7 +382,7 @@ impl<'a> ParserImpl<'a> {
// ImportSpecifier : // ImportSpecifier :
// ImportedBinding // ImportedBinding
// ModuleExportName as ImportedBinding // ModuleExportName as ImportedBinding
pub(crate) fn parse_import_specifier(&mut self) -> Result<ImportSpecifier<'a>> { pub(crate) fn parse_import_specifier(&mut self) -> Result<Box<'a, ImportSpecifier<'a>>> {
let specifier_span = self.start_span(); let specifier_span = self.start_span();
let peek_kind = self.peek_kind(); let peek_kind = self.peek_kind();
let mut import_kind = ImportOrExportKind::Value; let mut import_kind = ImportOrExportKind::Value;
@ -415,7 +413,12 @@ impl<'a> ParserImpl<'a> {
let imported = IdentifierName { span: local.span, name: local.name.clone() }; let imported = IdentifierName { span: local.span, name: local.name.clone() };
(ModuleExportName::Identifier(imported), local) (ModuleExportName::Identifier(imported), local)
}; };
Ok(ImportSpecifier { span: self.end_span(specifier_span), imported, local, import_kind }) Ok(self.ast.alloc(ImportSpecifier {
span: self.end_span(specifier_span),
imported,
local,
import_kind,
}))
} }
// ModuleExportName : // ModuleExportName :

View file

@ -85,7 +85,7 @@ impl<'a> ModuleImports<'a> {
names: std::vec::Vec<NamedImport>, names: std::vec::Vec<NamedImport>,
) -> Statement<'a> { ) -> Statement<'a> {
let specifiers = self.ast.new_vec_from_iter(names.into_iter().map(|name| { let specifiers = self.ast.new_vec_from_iter(names.into_iter().map(|name| {
ImportDeclarationSpecifier::ImportSpecifier(ImportSpecifier { ImportDeclarationSpecifier::ImportSpecifier(self.ast.alloc(ImportSpecifier {
span: SPAN, span: SPAN,
imported: ModuleExportName::Identifier(IdentifierName::new( imported: ModuleExportName::Identifier(IdentifierName::new(
SPAN, SPAN,
@ -96,7 +96,7 @@ impl<'a> ModuleImports<'a> {
self.ast.new_atom(name.local.unwrap_or(name.imported).as_str()), self.ast.new_atom(name.local.unwrap_or(name.imported).as_str()),
), ),
import_kind: ImportOrExportKind::Value, import_kind: ImportOrExportKind::Value,
}) }))
})); }));
let import_stmt = self.ast.import_declaration( let import_stmt = self.ast.import_declaration(
SPAN, SPAN,