From 383b449d4ed1dc3e536b516e4188ad8c7d0047b0 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Mon, 22 Apr 2024 02:06:39 +0100 Subject: [PATCH] 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. --- crates/oxc_ast/src/ast/js.rs | 6 ++--- crates/oxc_parser/src/js/module.rs | 23 +++++++++++-------- .../src/helpers/module_imports.rs | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index bc03af823..ca1d24ce9 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -2373,11 +2373,11 @@ pub struct ImportDeclaration<'a> { pub enum ImportDeclarationSpecifier<'a> { /// import {imported} from "source" /// import {imported as local} from "source" - ImportSpecifier(ImportSpecifier<'a>), + ImportSpecifier(Box<'a, ImportSpecifier<'a>>), /// import local from "source" - ImportDefaultSpecifier(ImportDefaultSpecifier<'a>), + ImportDefaultSpecifier(Box<'a, ImportDefaultSpecifier<'a>>), /// import * as local from "source" - ImportNamespaceSpecifier(ImportNamespaceSpecifier<'a>), + ImportNamespaceSpecifier(Box<'a, ImportNamespaceSpecifier<'a>>), } // import {imported} from "source" diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index 8ddc492a3..62164605a 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -107,10 +107,9 @@ impl<'a> ParserImpl<'a> { fn parse_import_default_specifier(&mut self) -> Result> { let span = self.start_span(); let local = self.parse_binding_identifier()?; - Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier(ImportDefaultSpecifier { - span: self.end_span(span), - local, - })) + Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier( + self.ast.alloc(ImportDefaultSpecifier { span: self.end_span(span), local }), + )) } // import * as name from "module-name" @@ -119,10 +118,9 @@ impl<'a> ParserImpl<'a> { self.bump_any(); // advance `*` self.expect(Kind::As)?; let local = self.parse_binding_identifier()?; - Ok(ImportDeclarationSpecifier::ImportNamespaceSpecifier(ImportNamespaceSpecifier { - span: self.end_span(span), - local, - })) + Ok(ImportDeclarationSpecifier::ImportNamespaceSpecifier( + self.ast.alloc(ImportNamespaceSpecifier { span: self.end_span(span), local }), + )) } // import { export1 , export2 as alias2 , [...] } from "module-name"; @@ -384,7 +382,7 @@ impl<'a> ParserImpl<'a> { // ImportSpecifier : // ImportedBinding // ModuleExportName as ImportedBinding - pub(crate) fn parse_import_specifier(&mut self) -> Result> { + pub(crate) fn parse_import_specifier(&mut self) -> Result>> { let specifier_span = self.start_span(); let peek_kind = self.peek_kind(); let mut import_kind = ImportOrExportKind::Value; @@ -415,7 +413,12 @@ impl<'a> ParserImpl<'a> { let imported = IdentifierName { span: local.span, name: local.name.clone() }; (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 : diff --git a/crates/oxc_transformer/src/helpers/module_imports.rs b/crates/oxc_transformer/src/helpers/module_imports.rs index 4fc8b4e09..199c66f1a 100644 --- a/crates/oxc_transformer/src/helpers/module_imports.rs +++ b/crates/oxc_transformer/src/helpers/module_imports.rs @@ -85,7 +85,7 @@ impl<'a> ModuleImports<'a> { names: std::vec::Vec, ) -> Statement<'a> { let specifiers = self.ast.new_vec_from_iter(names.into_iter().map(|name| { - ImportDeclarationSpecifier::ImportSpecifier(ImportSpecifier { + ImportDeclarationSpecifier::ImportSpecifier(self.ast.alloc(ImportSpecifier { span: SPAN, imported: ModuleExportName::Identifier(IdentifierName::new( SPAN, @@ -96,7 +96,7 @@ impl<'a> ModuleImports<'a> { self.ast.new_atom(name.local.unwrap_or(name.imported).as_str()), ), import_kind: ImportOrExportKind::Value, - }) + })) })); let import_stmt = self.ast.import_declaration( SPAN,