Skip to content

Commit

Permalink
perf(rolldown): build oxc semantic data only once (rolldown#1506)
Browse files Browse the repository at this point in the history
It was accidental that oxc semantic data is built twice during the whole
process. This PR passes the built semantic into the transformer so it is
not built twice.
  • Loading branch information
Boshen authored Jul 1, 2024
1 parent 88cfe8c commit fa347b3
Showing 4 changed files with 42 additions and 24 deletions.
14 changes: 10 additions & 4 deletions crates/rolldown/src/module_loader/normal_module_task.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,10 @@ use std::{path::Path, sync::Arc};

use anyhow::Result;
use futures::future::join_all;
use oxc::index::IndexVec;
use oxc::{
index::IndexVec,
semantic::{ScopeTree, SymbolTable},
};
use rolldown_common::{
side_effects::{DeterminedSideEffects, HookSideEffects},
AstScopes, ImportRecordId, ModuleDefFormat, ModuleType, NormalModule, NormalModuleId,
@@ -112,14 +115,15 @@ impl NormalModuleTask {
.await?
.into();

let mut ast = parse_to_ast(
let (mut ast, symbols, scopes) = parse_to_ast(
Path::new(&self.resolved_path.path.as_ref()),
&self.ctx.input_options,
module_type,
Arc::clone(&source),
)?;

let (scope, scan_result, ast_symbol, namespace_object_ref) = self.scan(&mut ast, &source);
let (scope, scan_result, ast_symbol, namespace_object_ref) =
self.scan(&mut ast, &source, symbols, scopes);

let resolved_deps =
self.resolve_dependencies(&scan_result.import_records, &mut warnings).await?;
@@ -242,8 +246,10 @@ impl NormalModuleTask {
&self,
ast: &mut OxcAst,
source: &Arc<str>,
symbols: SymbolTable,
scopes: ScopeTree,
) -> (AstScopes, ScanResult, AstSymbols, SymbolRef) {
let (ast_scopes, mut ast_symbols) = make_ast_scopes_and_symbols(ast);
let (mut ast_symbols, ast_scopes) = make_ast_scopes_and_symbols(symbols, scopes);
let file_path: ResourceId = Arc::<str>::clone(&self.resolved_path.path).into();
let repr_name = file_path.as_path().representative_file_name();
let repr_name = legitimize_identifier_name(&repr_name);
19 changes: 11 additions & 8 deletions crates/rolldown/src/utils/make_ast_symbol_and_scope.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use oxc::semantic::{ScopeTree, SymbolTable};
use rolldown_common::AstScopes;
use rolldown_oxc_utils::OxcAst;

use crate::types::ast_symbols::AstSymbols;

pub fn make_ast_scopes_and_symbols(ast: &OxcAst) -> (AstScopes, AstSymbols) {
let (mut symbol_table, scope) = ast.make_symbol_table_and_scope_tree();
pub fn make_ast_scopes_and_symbols(
symbols: SymbolTable,
scopes: ScopeTree,
) -> (AstSymbols, AstScopes) {
let mut symbols = symbols;
let ast_scope = AstScopes::new(
scope,
std::mem::take(&mut symbol_table.references),
std::mem::take(&mut symbol_table.resolved_references),
scopes,
std::mem::take(&mut symbols.references),
std::mem::take(&mut symbols.resolved_references),
);
let ast_symbols = AstSymbols::from_symbol_table(symbol_table);
(ast_scope, ast_symbols)
let ast_symbols = AstSymbols::from_symbol_table(symbols);
(ast_symbols, ast_scope)
}
11 changes: 6 additions & 5 deletions crates/rolldown/src/utils/parse_to_ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::{path::Path, sync::Arc};

use oxc::span::SourceType as OxcSourceType;
use oxc::{
semantic::{ScopeTree, SymbolTable},
span::SourceType as OxcSourceType,
};
use rolldown_common::{ModuleType, NormalizedBundlerOptions};
use rolldown_loader_utils::{base64_to_esm, binary_to_esm, json_to_esm, text_to_esm};
use rolldown_oxc_utils::{OxcAst, OxcCompiler};
@@ -24,7 +27,7 @@ pub fn parse_to_ast(
options: &NormalizedBundlerOptions,
module_type: ModuleType,
source: impl Into<Arc<str>>,
) -> anyhow::Result<OxcAst> {
) -> anyhow::Result<(OxcAst, SymbolTable, ScopeTree)> {
let source: Arc<str> = source.into();

// 1. Transform the source to the type that rolldown supported.
@@ -55,7 +58,5 @@ pub fn parse_to_ast(

let oxc_ast = OxcCompiler::parse(Arc::clone(&source), oxc_source_type)?;

let valid_js_ast = pre_process_ast(oxc_ast, &parsed_type, path, oxc_source_type)?;

Ok(valid_js_ast)
pre_process_ast(oxc_ast, &parsed_type, path, oxc_source_type)
}
22 changes: 15 additions & 7 deletions crates/rolldown/src/utils/pre_process_ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::path::Path;

use oxc::minifier::RemoveDeadCode;
use oxc::semantic::{ScopeTree, SymbolTable};
use oxc::span::SourceType;
use oxc::transformer::{TransformOptions, Transformer};
use rolldown_oxc_utils::OxcAst;
@@ -17,9 +18,12 @@ pub fn pre_process_ast(
parse_type: &OxcParseType,
path: &Path,
source_type: SourceType,
) -> anyhow::Result<OxcAst> {
) -> anyhow::Result<(OxcAst, SymbolTable, ScopeTree)> {
let (mut symbols, mut scopes) = ast.make_symbol_table_and_scope_tree();

if !matches!(parse_type, OxcParseType::Js) {
let result = ast.program.with_mut(|fields| {
let trivias = ast.trivias.clone();
let ret = ast.program.with_mut(move |fields| {
let mut transformer_options = TransformOptions::default();
match parse_type {
OxcParseType::Js => unreachable!("Should not reach here"),
@@ -37,14 +41,18 @@ pub fn pre_process_ast(
path,
source_type,
fields.source,
ast.trivias.clone(),
trivias,
transformer_options,
)
.build(fields.program)
.build_with_symbols_and_scopes(symbols, scopes, fields.program)
});
if !result.errors.is_empty() {
return Err(anyhow::anyhow!("Transform failed, got {:#?}", result.errors));

if !ret.errors.is_empty() {
return Err(anyhow::anyhow!("Transform failed, got {:#?}", ret.errors));
}

symbols = ret.symbols;
scopes = ret.scopes;
}

ast.program.with_mut(|fields| {
@@ -55,5 +63,5 @@ pub fn pre_process_ast(

tweak_ast_for_scanning(&mut ast);

Ok(ast)
Ok((ast, symbols, scopes))
}

0 comments on commit fa347b3

Please sign in to comment.