From 13106e0d2eaa08c4c74f58205f57c4f2d7d4479f Mon Sep 17 00:00:00 2001 From: Austaras Date: Fri, 20 Oct 2023 03:37:37 +0800 Subject: [PATCH] refactor(es/minifier): Decouple `assign_count` from `reassigned` (#8137) --- .../src/compress/optimize/inline.rs | 4 +- .../src/compress/optimize/sequences.rs | 3 +- crates/swc_ecma_minifier/src/program_data.rs | 43 +++++++++---------- .../src/analyzer/ctx.rs | 2 +- .../src/analyzer/mod.rs | 22 +++++----- 5 files changed, 35 insertions(+), 39 deletions(-) diff --git a/crates/swc_ecma_minifier/src/compress/optimize/inline.rs b/crates/swc_ecma_minifier/src/compress/optimize/inline.rs index 3851696b911..980bc444254 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/inline.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/inline.rs @@ -174,7 +174,7 @@ impl Optimizer<'_> { // new variant is added for multi inline, think carefully if is_inline_enabled && usage.declared_count == 1 - && usage.assign_count == 0 + && usage.assign_count == 1 && (!usage.has_property_mutation || !usage.reassigned) && match init { Expr::Ident(Ident { sym, .. }) if &**sym == "eval" => false, @@ -326,7 +326,7 @@ impl Optimizer<'_> { && usage.declared && may_remove && !usage.reassigned - && usage.assign_count == 0 + && usage.assign_count == 1 && ref_count == 1 { match init { diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index 771d4a59c01..5935afbc962 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -2327,8 +2327,7 @@ impl Optimizer<'_> { if let Some(usage) = self.data.vars.get(&left_id.to_id()) { // We are eliminating one usage, so we use 1 instead of // 0 - if !$force_drop && usage.usage_count == 1 && usage.assign_count == 0 - { + if !$force_drop && usage.usage_count == 1 && !usage.reassigned { report_change!("sequences: Dropping inlined variable"); a.name.take(); } diff --git a/crates/swc_ecma_minifier/src/program_data.rs b/crates/swc_ecma_minifier/src/program_data.rs index b43191105a0..141ca4f6bf4 100644 --- a/crates/swc_ecma_minifier/src/program_data.rs +++ b/crates/swc_ecma_minifier/src/program_data.rs @@ -64,6 +64,7 @@ pub(crate) struct VarUsageInfo { pub(crate) declared_as_for_init: bool, + /// The number of assign and initialization to this identifier. pub(crate) assign_count: u32, /// The number of direct and indirect reference to this identifier. @@ -171,7 +172,7 @@ impl VarUsageInfo { /// The variable itself or a property of it is modified. pub(crate) fn mutated(&self) -> bool { - self.assign_count > 0 || self.has_property_mutation + self.assign_count > 1 || self.has_property_mutation } pub(crate) fn can_inline_fn_once(&self) -> bool { @@ -221,11 +222,16 @@ impl Storage for ProgramData { let var_assigned = var_info.assign_count > 0 || (var_info.var_initialized && !e.get().var_initialized); + if var_info.assign_count > 0 { + if e.get().initialized() { + e.get_mut().reassigned = true + } + } + if var_info.var_initialized { // If it is inited in some other child scope and also inited in current // scope if e.get().var_initialized || e.get().ref_count > 0 { - e.get_mut().assign_count += 1; e.get_mut().reassigned = true; } else { // If it is referred outside child scope, it will @@ -237,7 +243,6 @@ impl Storage for ProgramData { // current child scope if !inited && e.get().var_initialized && var_info.ref_count > 0 { e.get_mut().var_initialized = false; - e.get_mut().assign_count += 1; e.get_mut().reassigned = true } } @@ -246,12 +251,6 @@ impl Storage for ProgramData { e.get_mut().reassigned |= var_info.reassigned; - if var_info.assign_count > 0 { - if e.get().initialized() { - e.get_mut().reassigned = true - } - } - e.get_mut().has_property_access |= var_info.has_property_access; e.get_mut().has_property_mutation |= var_info.has_property_mutation; e.get_mut().exported |= var_info.exported; @@ -349,13 +348,16 @@ impl Storage for ProgramData { v.is_top_level |= ctx.is_top_level; // assigned or declared before this declaration - if has_init && (v.declared || v.var_initialized || v.assign_count > 0) { - #[cfg(feature = "debug")] - { - tracing::trace!("declare_decl(`{}`): Already declared", i); + if has_init { + if v.declared || v.var_initialized || v.assign_count > 0 { + #[cfg(feature = "debug")] + { + tracing::trace!("declare_decl(`{}`): Already declared", i); + } + + v.reassigned = true; } - v.reassigned = true; v.assign_count += 1; } @@ -403,7 +405,7 @@ impl Storage for ProgramData { for other in to_mark_mutate { let other = self.vars.entry(other).or_insert_with(|| { - let simple_assign = ctx.is_exact_reassignment && !ctx.is_op_assign; + let simple_assign = ctx.is_exact_assignment && !ctx.is_op_assign; VarUsageInfo { used_above_decl: !simple_assign, @@ -570,7 +572,7 @@ impl ProgramData { let e = self.vars.entry(i.clone()).or_insert_with(|| { // trace!("insert({}{:?})", i.0, i.1); - let simple_assign = ctx.is_exact_reassignment && !ctx.is_op_assign; + let simple_assign = ctx.is_exact_assignment && !ctx.is_op_assign; VarUsageInfo { used_above_decl: !simple_assign, @@ -601,7 +603,7 @@ impl ProgramData { e.executed_multiple_time |= ctx.executed_multiple_time; e.used_in_cond |= ctx.in_cond; - if is_modify && ctx.is_exact_reassignment { + if is_modify && ctx.is_exact_assignment { if is_first { if e.assign_count > 0 || e.initialized() { e.reassigned = true @@ -610,13 +612,8 @@ impl ProgramData { e.assign_count += 1; if !ctx.is_op_assign { - if e.ref_count == 1 - && ctx.in_assign_lhs - && e.var_kind != Some(VarDeclKind::Const) - && !inited - { + if e.ref_count == 1 && e.var_kind != Some(VarDeclKind::Const) && !inited { self.initialized_vars.insert(i.clone()); - e.assign_count -= 1; e.var_initialized = true; } else { e.reassigned = true diff --git a/crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs b/crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs index f53b208365c..1efcf0b2701 100644 --- a/crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs +++ b/crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs @@ -112,7 +112,7 @@ pub struct Ctx { pub in_pat_of_param: bool, pub in_catch_param: bool, /// `true` for `foo.bar` and `false` for `foo` in `foo.bar++` - pub is_exact_reassignment: bool, + pub is_exact_assignment: bool, pub is_callee: bool, diff --git a/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs b/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs index ef74a396a6c..8a95c89c625 100644 --- a/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs +++ b/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs @@ -218,7 +218,7 @@ where fn visit_assign_expr(&mut self, n: &AssignExpr) { let ctx = Ctx { in_assign_lhs: true, - is_exact_reassignment: true, + is_exact_assignment: true, is_op_assign: n.op != op!("="), is_delete_arg: false, ..self.ctx @@ -227,7 +227,7 @@ where let ctx = Ctx { in_assign_lhs: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_delete_arg: false, // We mark bar in // @@ -407,7 +407,7 @@ where }, is_delete_arg: false, is_exact_arg: true, - is_exact_reassignment: false, + is_exact_assignment: false, is_callee: false, is_id_ref: true, ..self.ctx @@ -750,7 +750,7 @@ where self.with_child(n.span.ctxt, ScopeKind::Block, |child| { let ctx = Ctx { - is_exact_reassignment: true, + is_exact_assignment: true, is_delete_arg: false, in_left_of_for_loop: true, ..child.ctx @@ -777,7 +777,7 @@ where self.with_child(n.span.ctxt, ScopeKind::Block, |child| { let ctx = Ctx { in_left_of_for_loop: true, - is_exact_reassignment: true, + is_exact_assignment: true, is_delete_arg: false, ..child.ctx }; @@ -884,7 +884,7 @@ where { let ctx = Ctx { is_exact_arg: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_callee: false, is_id_ref: false, ..self.ctx @@ -895,7 +895,7 @@ where if let MemberProp::Computed(c) = &e.prop { let ctx = Ctx { is_exact_arg: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_callee: false, is_delete_arg: false, ..self.ctx @@ -1067,7 +1067,7 @@ where fn visit_prop(&mut self, n: &Prop) { let ctx = Ctx { is_exact_arg: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_id_ref: true, ..self.ctx }; @@ -1151,7 +1151,7 @@ where if let SuperProp::Computed(c) = &e.prop { let ctx = Ctx { is_exact_arg: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_delete_arg: false, is_id_ref: false, ..self.ctx @@ -1217,7 +1217,7 @@ where fn visit_unary_expr(&mut self, n: &UnaryExpr) { let ctx = Ctx { in_update_arg: false, - is_exact_reassignment: false, + is_exact_assignment: false, is_delete_arg: n.op == op!("delete"), ..self.ctx }; @@ -1228,7 +1228,7 @@ where fn visit_update_expr(&mut self, n: &UpdateExpr) { let ctx = Ctx { in_update_arg: true, - is_exact_reassignment: true, + is_exact_assignment: true, is_delete_arg: false, ..self.ctx };