diff --git a/.changeset/cold-pillows-walk.md b/.changeset/cold-pillows-walk.md new file mode 100644 index 000000000000..4dfd392a0bb2 --- /dev/null +++ b/.changeset/cold-pillows-walk.md @@ -0,0 +1,6 @@ +--- +swc_bundler: patch +swc_ecma_transforms_base: patch +--- + +perf(es/helpers): Use `bool` instead of `AtomicBool` diff --git a/crates/swc_bundler/src/bundler/chunk/merge.rs b/crates/swc_bundler/src/bundler/chunk/merge.rs index ff0d193533c4..6c0ef0a2a81b 100644 --- a/crates/swc_bundler/src/bundler/chunk/merge.rs +++ b/crates/swc_bundler/src/bundler/chunk/merge.rs @@ -9,6 +9,7 @@ use swc_common::{ FileName, SyntaxContext, DUMMY_SP, }; use swc_ecma_ast::*; +use swc_ecma_transforms_base::helpers::Helpers; use swc_ecma_utils::{find_pat_ids, prepend_stmt, private_ident, quote_ident, ExprFactory}; use swc_ecma_visit::{VisitMut, VisitMutWith}; use EdgeDirection::Outgoing; @@ -104,7 +105,18 @@ where let deps = all_deps_of_entry.iter().map(|id| { let dep_info = self.scope.get_module(*id).unwrap(); entry_info.helpers.extend(&dep_info.helpers); - entry_info.swc_helpers.extend_from(&dep_info.swc_helpers); + + { + let helpers = *entry_info.swc_helpers.lock(); + let dep_helpers = *dep_info.swc_helpers.lock(); + + let helpers = Helpers::from_data(helpers); + let dep_helpers = Helpers::from_data(dep_helpers); + + helpers.extend_from(&dep_helpers); + + *entry_info.swc_helpers.lock() = helpers.data(); + } if *id == entry_id { return Modules::empty(injected_ctxt); diff --git a/crates/swc_bundler/src/bundler/finalize.rs b/crates/swc_bundler/src/bundler/finalize.rs index 18eb71581703..58208ccd0117 100644 --- a/crates/swc_bundler/src/bundler/finalize.rs +++ b/crates/swc_bundler/src/bundler/finalize.rs @@ -6,7 +6,7 @@ use swc_common::{collections::AHashMap, util::move_map::MoveMap, FileName, Mark, use swc_ecma_ast::*; use swc_ecma_transforms_base::{ fixer::fixer, - helpers::{inject_helpers, HELPERS}, + helpers::{inject_helpers, Helpers, HELPERS}, hygiene::hygiene, }; use swc_ecma_utils::{contains_top_level_await, find_pat_ids, private_ident, ExprFactory}; @@ -48,15 +48,16 @@ where { // Inject swc helpers - let swc_helpers = self + let swc_helpers = *self .scope .get_module(bundle.id) .expect("module should exist at this point") - .swc_helpers; + .swc_helpers + .lock(); let module = bundle.module; - bundle.module = HELPERS.set(&swc_helpers, || { + bundle.module = HELPERS.set(&Helpers::from_data(swc_helpers), || { module.fold_with(&mut inject_helpers(unresolved_mark)) }); } diff --git a/crates/swc_bundler/src/bundler/load.rs b/crates/swc_bundler/src/bundler/load.rs index 374e7ecf0a23..0c543c2e1a4d 100644 --- a/crates/swc_bundler/src/bundler/load.rs +++ b/crates/swc_bundler/src/bundler/load.rs @@ -4,7 +4,10 @@ use anyhow::{Context, Error}; use is_macro::Is; #[cfg(feature = "rayon")] use rayon::iter::ParallelIterator; -use swc_common::{sync::Lrc, FileName, SourceFile, SyntaxContext}; +use swc_common::{ + sync::{Lock, Lrc}, + FileName, SourceFile, SyntaxContext, +}; use swc_ecma_ast::{ CallExpr, Callee, Expr, Ident, ImportDecl, ImportSpecifier, MemberExpr, MemberProp, Module, ModuleDecl, ModuleExportName, Str, SuperProp, SuperPropExpr, @@ -38,7 +41,7 @@ pub(crate) struct TransformedModule { /// Used helpers pub helpers: Lrc, - pub swc_helpers: Lrc, + pub swc_helpers: Lrc>, local_ctxt: SyntaxContext, export_ctxt: SyntaxContext, @@ -208,7 +211,7 @@ where exports: Lrc::new(exports), is_es6, helpers: Default::default(), - swc_helpers: Lrc::new(data.helpers), + swc_helpers: Lrc::new(Lock::new(data.helpers.data())), local_ctxt: SyntaxContext::empty().apply_mark(local_mark), export_ctxt: SyntaxContext::empty().apply_mark(export_mark), }, diff --git a/crates/swc_ecma_transforms_base/src/helpers/mod.rs b/crates/swc_ecma_transforms_base/src/helpers/mod.rs index 412b6a8fe23b..7720369d2ea7 100644 --- a/crates/swc_ecma_transforms_base/src/helpers/mod.rs +++ b/crates/swc_ecma_transforms_base/src/helpers/mod.rs @@ -1,7 +1,4 @@ -use std::{ - mem::replace, - sync::atomic::{AtomicBool, Ordering}, -}; +use std::{cell::RefCell, mem::replace}; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; @@ -52,7 +49,7 @@ macro_rules! add_to { parse(&code) }); - let enable = $b.load(Ordering::Relaxed); + let enable = $b; if enable { $buf.extend(STMTS.iter().cloned().map(|mut stmt| { stmt.visit_mut_with(&mut Marker { @@ -69,7 +66,7 @@ macro_rules! add_to { macro_rules! add_import_to { ($buf:expr, $name:ident, $b:expr, $mark:expr) => {{ - let enable = $b.load(Ordering::Relaxed); + let enable = $b; if enable { let ctxt = SyntaxContext::empty().apply_mark($mark); let s = ImportSpecifier::Named(ImportNamedSpecifier { @@ -103,6 +100,13 @@ better_scoped_tls::scoped_tls!( /// Tracks used helper methods. (e.g. __extends) #[derive(Debug, Default)] pub struct Helpers { + external: bool, + mark: HelperMark, + inner: RefCell, +} + +#[derive(Debug, Clone, Copy)] +pub struct HelperData { external: bool, mark: HelperMark, inner: Inner, @@ -124,6 +128,22 @@ impl Helpers { pub const fn external(&self) -> bool { self.external } + + pub fn data(&self) -> HelperData { + HelperData { + inner: *self.inner.borrow(), + external: self.external, + mark: self.mark, + } + } + + pub fn from_data(data: HelperData) -> Self { + Helpers { + external: data.external, + mark: data.mark, + inner: RefCell::new(data.inner), + } + } } #[derive(Debug, Clone, Copy)] @@ -140,15 +160,15 @@ macro_rules! define_helpers { $( $name:ident : ( $( $dep:ident ),* ), )* } ) => { - #[derive(Debug,Default)] + #[derive(Debug,Default, Clone, Copy)] struct Inner { - $( $name: AtomicBool, )* + $( $name: bool, )* } impl Helpers { $( pub fn $name(&self) { - self.inner.$name.store(true, Ordering::Relaxed); + self.inner.borrow_mut().$name = true; if !self.external { $( @@ -159,11 +179,14 @@ macro_rules! define_helpers { )* } + impl Helpers { pub fn extend_from(&self, other: &Self) { + let other = other.inner.borrow(); + let mut me = self.inner.borrow_mut(); $( - if other.inner.$name.load(Ordering::SeqCst) { - self.inner.$name.store(true, Ordering::Relaxed); + if other.$name { + me.$name = true; } )* } @@ -173,8 +196,9 @@ macro_rules! define_helpers { fn is_helper_used(&self) -> bool{ HELPERS.with(|helpers|{ + let inner = helpers.inner.borrow(); false $( - || helpers.inner.$name.load(Ordering::Relaxed) + || inner.$name )* }) } @@ -184,8 +208,9 @@ macro_rules! define_helpers { HELPERS.with(|helpers|{ debug_assert!(!helpers.external); + let inner = helpers.inner.borrow(); $( - add_to!(buf, $name, helpers.inner.$name, helpers.mark.0); + add_to!(buf, $name, inner.$name, helpers.mark.0); )* }); @@ -196,9 +221,10 @@ macro_rules! define_helpers { let mut buf = Vec::new(); HELPERS.with(|helpers|{ + let inner = helpers.inner.borrow(); debug_assert!(helpers.external); $( - add_import_to!(buf, $name, helpers.inner.$name, helpers.mark.0); + add_import_to!(buf, $name, inner.$name, helpers.mark.0); )* }); @@ -209,8 +235,9 @@ macro_rules! define_helpers { let mut buf = Vec::new(); HELPERS.with(|helpers|{ debug_assert!(helpers.external); + let inner = helpers.inner.borrow(); $( - let enable = helpers.inner.$name.load(Ordering::Relaxed); + let enable = inner.$name; if enable { buf.push(self.build_reqire(stringify!($name), helpers.mark.0)) } diff --git a/crates/swc_ecma_transforms_base/src/perf.rs b/crates/swc_ecma_transforms_base/src/perf.rs index 30d6e68bc910..28079a55ea60 100644 --- a/crates/swc_ecma_transforms_base/src/perf.rs +++ b/crates/swc_ecma_transforms_base/src/perf.rs @@ -5,6 +5,7 @@ use swc_ecma_ast::*; pub use swc_ecma_utils::parallel::*; use swc_ecma_visit::{Fold, FoldWith, Visit, VisitMut, VisitMutWith, VisitWith}; +use crate::helpers::Helpers; #[cfg(feature = "concurrent")] use crate::helpers::HELPERS; @@ -52,14 +53,18 @@ where if nodes.len() >= threshold { GLOBALS.with(|globals| { HELPERS.with(|helpers| { + let helpers = helpers.data(); + HANDLER.with(|handler| { use rayon::prelude::*; let visitor = nodes .into_par_iter() .map(|node| { + let helpers = Helpers::from_data(helpers); + GLOBALS.set(globals, || { - HELPERS.set(helpers, || { + HELPERS.set(&helpers, || { HANDLER.set(handler, || { let mut visitor = Parallel::create(&*self); node.visit_with(&mut visitor); @@ -110,14 +115,16 @@ where if nodes.len() >= threshold { GLOBALS.with(|globals| { HELPERS.with(|helpers| { + let helpers = helpers.data(); HANDLER.with(|handler| { use rayon::prelude::*; let visitor = nodes .into_par_iter() .map(|node| { + let helpers = Helpers::from_data(helpers); GLOBALS.set(globals, || { - HELPERS.set(helpers, || { + HELPERS.set(&helpers, || { HANDLER.set(handler, || { let mut visitor = Parallel::create(&*self); node.visit_mut_with(&mut visitor); @@ -170,12 +177,14 @@ where let (visitor, nodes) = GLOBALS.with(|globals| { HELPERS.with(|helpers| { + let helpers = helpers.data(); HANDLER.with(|handler| { nodes .into_par_iter() .map(|node| { + let helpers = Helpers::from_data(helpers); GLOBALS.set(globals, || { - HELPERS.set(helpers, || { + HELPERS.set(&helpers, || { HANDLER.set(handler, || { let mut visitor = Parallel::create(&*self); let node = node.fold_with(&mut visitor);