mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 04:39:06 +03:00
refactor(es/minifier): Pre-calculate reassigned
(#7832)
This commit is contained in:
parent
662f236aa5
commit
65db1badff
@ -40,7 +40,7 @@ impl Optimizer<'_> {
|
|||||||
|
|
||||||
let usage = self.data.vars.get(&obj.to_id())?;
|
let usage = self.data.vars.get(&obj.to_id())?;
|
||||||
|
|
||||||
if usage.reassigned() {
|
if usage.reassigned {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ impl Optimizer<'_> {
|
|||||||
match &mut **param {
|
match &mut **param {
|
||||||
Pat::Ident(param) => {
|
Pat::Ident(param) => {
|
||||||
if let Some(usage) = self.data.vars.get(¶m.to_id()) {
|
if let Some(usage) = self.data.vars.get(¶m.to_id()) {
|
||||||
if usage.reassigned() {
|
if usage.reassigned {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if usage.ref_count != 1 {
|
if usage.ref_count != 1 {
|
||||||
@ -222,7 +222,7 @@ impl Optimizer<'_> {
|
|||||||
Pat::Rest(rest_pat) => {
|
Pat::Rest(rest_pat) => {
|
||||||
if let Pat::Ident(param_id) = &*rest_pat.arg {
|
if let Pat::Ident(param_id) = &*rest_pat.arg {
|
||||||
if let Some(usage) = self.data.vars.get(¶m_id.to_id()) {
|
if let Some(usage) = self.data.vars.get(¶m_id.to_id()) {
|
||||||
if usage.reassigned()
|
if usage.reassigned
|
||||||
|| usage.ref_count != 1
|
|| usage.ref_count != 1
|
||||||
|| !usage.has_property_access
|
|| !usage.has_property_access
|
||||||
{
|
{
|
||||||
@ -906,7 +906,7 @@ impl Optimizer<'_> {
|
|||||||
if let Some(arg) = arg {
|
if let Some(arg) = arg {
|
||||||
if let Some(usage) = self.data.vars.get(&orig_params[idx].to_id()) {
|
if let Some(usage) = self.data.vars.get(&orig_params[idx].to_id()) {
|
||||||
if usage.ref_count == 1
|
if usage.ref_count == 1
|
||||||
&& !usage.reassigned()
|
&& !usage.reassigned
|
||||||
&& !usage.has_property_mutation
|
&& !usage.has_property_mutation
|
||||||
&& matches!(
|
&& matches!(
|
||||||
&*arg,
|
&*arg,
|
||||||
|
@ -98,7 +98,7 @@ impl Optimizer<'_> {
|
|||||||
//
|
//
|
||||||
// TODO: Allow `length` in usage.accessed_props
|
// TODO: Allow `length` in usage.accessed_props
|
||||||
if usage.declared
|
if usage.declared
|
||||||
&& !usage.reassigned()
|
&& !usage.reassigned
|
||||||
&& !usage.mutated
|
&& !usage.mutated
|
||||||
&& !usage.has_property_mutation
|
&& !usage.has_property_mutation
|
||||||
&& usage.accessed_props.is_empty()
|
&& usage.accessed_props.is_empty()
|
||||||
@ -153,7 +153,7 @@ impl Optimizer<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !usage.reassigned() {
|
if !usage.reassigned {
|
||||||
match init {
|
match init {
|
||||||
Expr::Fn(..) | Expr::Arrow(..) => {
|
Expr::Fn(..) | Expr::Arrow(..) => {
|
||||||
self.typeofs.insert(ident.to_id(), js_word!("function"));
|
self.typeofs.insert(ident.to_id(), js_word!("function"));
|
||||||
@ -188,7 +188,7 @@ impl Optimizer<'_> {
|
|||||||
if !usage.assigned_fn_local {
|
if !usage.assigned_fn_local {
|
||||||
false
|
false
|
||||||
} else if let Some(u) = self.data.vars.get(&id.to_id()) {
|
} else if let Some(u) = self.data.vars.get(&id.to_id()) {
|
||||||
let mut should_inline = !u.reassigned() && u.declared;
|
let mut should_inline = !u.reassigned && u.declared;
|
||||||
|
|
||||||
should_inline &=
|
should_inline &=
|
||||||
// Function declarations are hoisted
|
// Function declarations are hoisted
|
||||||
@ -322,7 +322,7 @@ impl Optimizer<'_> {
|
|||||||
&& is_inline_enabled
|
&& is_inline_enabled
|
||||||
&& usage.declared
|
&& usage.declared
|
||||||
&& may_remove
|
&& may_remove
|
||||||
&& !usage.reassigned()
|
&& !usage.reassigned
|
||||||
&& (usage.can_inline_var() || usage.is_mutated_only_by_one_call())
|
&& (usage.can_inline_var() || usage.is_mutated_only_by_one_call())
|
||||||
&& ref_count == 1
|
&& ref_count == 1
|
||||||
{
|
{
|
||||||
@ -371,7 +371,7 @@ impl Optimizer<'_> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(v_usage) = self.data.vars.get(&id) {
|
if let Some(v_usage) = self.data.vars.get(&id) {
|
||||||
if v_usage.reassigned() {
|
if v_usage.reassigned {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -388,7 +388,7 @@ impl Optimizer<'_> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(v_usage) = self.data.vars.get(&id) {
|
if let Some(v_usage) = self.data.vars.get(&id) {
|
||||||
if v_usage.reassigned() {
|
if v_usage.reassigned {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -400,7 +400,7 @@ impl Optimizer<'_> {
|
|||||||
Expr::Object(..) if self.options.pristine_globals => {
|
Expr::Object(..) if self.options.pristine_globals => {
|
||||||
for id in idents_used_by_ignoring_nested(init) {
|
for id in idents_used_by_ignoring_nested(init) {
|
||||||
if let Some(v_usage) = self.data.vars.get(&id) {
|
if let Some(v_usage) = self.data.vars.get(&id) {
|
||||||
if v_usage.reassigned() {
|
if v_usage.reassigned {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +413,7 @@ impl Optimizer<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(init_usage) = self.data.vars.get(&id.to_id()) {
|
if let Some(init_usage) = self.data.vars.get(&id.to_id()) {
|
||||||
if init_usage.reassigned() || !init_usage.declared {
|
if init_usage.reassigned || !init_usage.declared {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,7 +422,7 @@ impl Optimizer<'_> {
|
|||||||
_ => {
|
_ => {
|
||||||
for id in idents_used_by(init) {
|
for id in idents_used_by(init) {
|
||||||
if let Some(v_usage) = self.data.vars.get(&id) {
|
if let Some(v_usage) = self.data.vars.get(&id) {
|
||||||
if v_usage.reassigned() || v_usage.has_property_mutation {
|
if v_usage.reassigned || v_usage.has_property_mutation {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -534,7 +534,7 @@ impl Optimizer<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(usage) = self.data.vars.get(&i.to_id()) {
|
if let Some(usage) = self.data.vars.get(&i.to_id()) {
|
||||||
if !usage.reassigned() {
|
if !usage.reassigned {
|
||||||
trace_op!("typeofs: Storing typeof `{}{:?}`", i.sym, i.span.ctxt);
|
trace_op!("typeofs: Storing typeof `{}{:?}`", i.sym, i.span.ctxt);
|
||||||
match &*decl {
|
match &*decl {
|
||||||
Decl::Fn(..) => {
|
Decl::Fn(..) => {
|
||||||
@ -601,10 +601,10 @@ impl Optimizer<'_> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if usage.reassigned() || usage.inline_prevented {
|
if usage.reassigned || usage.inline_prevented {
|
||||||
log_abort!(
|
log_abort!(
|
||||||
"inline: [x] reassigned = {}, inline_prevented = {}",
|
"inline: [x] reassigned = {}, inline_prevented = {}",
|
||||||
usage.reassigned(),
|
usage.reassigned,
|
||||||
usage.inline_prevented
|
usage.inline_prevented
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -842,7 +842,7 @@ impl Optimizer<'_> {
|
|||||||
if let Expr::Ident(callee) = &**callee {
|
if let Expr::Ident(callee) = &**callee {
|
||||||
if self.options.reduce_vars && self.options.side_effects {
|
if self.options.reduce_vars && self.options.side_effects {
|
||||||
if let Some(usage) = self.data.vars.get(&callee.to_id()) {
|
if let Some(usage) = self.data.vars.get(&callee.to_id()) {
|
||||||
if !usage.reassigned() && usage.pure_fn {
|
if !usage.reassigned && usage.pure_fn {
|
||||||
self.changed = true;
|
self.changed = true;
|
||||||
report_change!("Reducing function call to a variable");
|
report_change!("Reducing function call to a variable");
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ impl Optimizer<'_> {
|
|||||||
&& !v.used_as_arg
|
&& !v.used_as_arg
|
||||||
&& !v.used_in_cond
|
&& !v.used_in_cond
|
||||||
&& (!v.is_fn_local || !self.mode.should_be_very_correct())
|
&& (!v.is_fn_local || !self.mode.should_be_very_correct())
|
||||||
&& !v.reassigned()
|
&& !v.reassigned
|
||||||
&& !v.is_infected()
|
&& !v.is_infected()
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
@ -1469,7 +1469,7 @@ impl Optimizer<'_> {
|
|||||||
}
|
}
|
||||||
_ => a.may_have_side_effects(&self.expr_ctx),
|
_ => a.may_have_side_effects(&self.expr_ctx),
|
||||||
};
|
};
|
||||||
if has_side_effect && !usgae.is_fn_local && (usgae.exported || usgae.reassigned()) {
|
if has_side_effect && !usgae.is_fn_local && (usgae.exported || usgae.reassigned) {
|
||||||
log_abort!("a (expr) has side effect");
|
log_abort!("a (expr) has side effect");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1478,7 +1478,7 @@ impl Optimizer<'_> {
|
|||||||
if let Some(init) = &a.init {
|
if let Some(init) = &a.init {
|
||||||
if init.may_have_side_effects(&self.expr_ctx)
|
if init.may_have_side_effects(&self.expr_ctx)
|
||||||
&& !usgae.is_fn_local
|
&& !usgae.is_fn_local
|
||||||
&& (usgae.exported || usgae.reassigned())
|
&& (usgae.exported || usgae.reassigned)
|
||||||
{
|
{
|
||||||
log_abort!("a (var) init has side effect");
|
log_abort!("a (var) init has side effect");
|
||||||
return false;
|
return false;
|
||||||
@ -2210,7 +2210,7 @@ impl Optimizer<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We can remove this variable same as unused pass
|
// We can remove this variable same as unused pass
|
||||||
if !usage.reassigned()
|
if !usage.reassigned
|
||||||
&& usage.usage_count == 1
|
&& usage.usage_count == 1
|
||||||
&& usage.declared
|
&& usage.declared
|
||||||
&& !usage.used_recursively
|
&& !usage.used_recursively
|
||||||
@ -2239,7 +2239,7 @@ impl Optimizer<'_> {
|
|||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if usage.ref_count != 1 || usage.reassigned() || !usage.is_fn_local {
|
if usage.ref_count != 1 || usage.reassigned || !usage.is_fn_local {
|
||||||
if is_lit {
|
if is_lit {
|
||||||
can_take_init = false
|
can_take_init = false
|
||||||
} else {
|
} else {
|
||||||
@ -2271,7 +2271,7 @@ impl Optimizer<'_> {
|
|||||||
|
|
||||||
Mergable::FnDecl(a) => {
|
Mergable::FnDecl(a) => {
|
||||||
if let Some(usage) = self.data.vars.get(&a.ident.to_id()) {
|
if let Some(usage) = self.data.vars.get(&a.ident.to_id()) {
|
||||||
if usage.ref_count != 1 || usage.reassigned() || !usage.is_fn_local {
|
if usage.ref_count != 1 || usage.reassigned || !usage.is_fn_local {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ impl Optimizer<'_> {
|
|||||||
if let Some(v) = self.data.vars.get(&i.to_id()).cloned() {
|
if let Some(v) = self.data.vars.get(&i.to_id()).cloned() {
|
||||||
if v.ref_count == 0
|
if v.ref_count == 0
|
||||||
&& v.usage_count == 0
|
&& v.usage_count == 0
|
||||||
&& !v.reassigned()
|
&& !v.reassigned
|
||||||
&& !v.has_property_mutation
|
&& !v.has_property_mutation
|
||||||
&& !v.declared_as_catch_param
|
&& !v.declared_as_catch_param
|
||||||
{
|
{
|
||||||
@ -215,9 +215,7 @@ impl Optimizer<'_> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !usage.mutated
|
if !usage.mutated && !usage.reassigned && usage.no_side_effect_for_member_access
|
||||||
&& !usage.reassigned()
|
|
||||||
&& usage.no_side_effect_for_member_access
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ pub(crate) struct VarUsageInfo {
|
|||||||
pub(crate) usage_count: u32,
|
pub(crate) usage_count: u32,
|
||||||
|
|
||||||
/// The variable itself is assigned after reference.
|
/// The variable itself is assigned after reference.
|
||||||
reassigned: bool,
|
pub(crate) reassigned: bool,
|
||||||
/// The variable itself or a property of it is modified.
|
/// The variable itself or a property of it is modified.
|
||||||
pub(crate) mutated: bool,
|
pub(crate) mutated: bool,
|
||||||
|
|
||||||
@ -178,23 +178,18 @@ impl VarUsageInfo {
|
|||||||
!self.infects_to.is_empty()
|
!self.infects_to.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn reassigned(&self) -> bool {
|
|
||||||
self.reassigned
|
|
||||||
|| (u32::from(self.var_initialized)
|
|
||||||
+ u32::from(self.declared_as_catch_param)
|
|
||||||
+ u32::from(self.declared_as_fn_param)
|
|
||||||
+ self.assign_count)
|
|
||||||
> 1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn can_inline_var(&self) -> bool {
|
pub(crate) fn can_inline_var(&self) -> bool {
|
||||||
!self.mutated || (self.assign_count == 0 && !self.reassigned())
|
!self.mutated || (self.assign_count == 0 && !self.reassigned)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn can_inline_fn_once(&self) -> bool {
|
pub(crate) fn can_inline_fn_once(&self) -> bool {
|
||||||
self.callee_count > 0
|
self.callee_count > 0
|
||||||
|| !self.executed_multiple_time && (self.is_fn_local || !self.used_in_non_child_fn)
|
|| !self.executed_multiple_time && (self.is_fn_local || !self.used_in_non_child_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initialized(&self) -> bool {
|
||||||
|
self.var_initialized || self.declared_as_fn_param || self.declared_as_catch_param
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Storage for ProgramData {
|
impl Storage for ProgramData {
|
||||||
@ -255,6 +250,12 @@ impl Storage for ProgramData {
|
|||||||
|
|
||||||
e.get_mut().reassigned |= var_info.reassigned;
|
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().mutated |= var_info.mutated;
|
e.get_mut().mutated |= var_info.mutated;
|
||||||
|
|
||||||
e.get_mut().has_property_access |= var_info.has_property_access;
|
e.get_mut().has_property_access |= var_info.has_property_access;
|
||||||
@ -354,7 +355,8 @@ impl Storage for ProgramData {
|
|||||||
let v = self.vars.entry(i.to_id()).or_default();
|
let v = self.vars.entry(i.to_id()).or_default();
|
||||||
v.is_top_level |= ctx.is_top_level;
|
v.is_top_level |= ctx.is_top_level;
|
||||||
|
|
||||||
if has_init && (v.declared || v.var_initialized) {
|
// assigned or declared before this declaration
|
||||||
|
if has_init && (v.declared || v.var_initialized || v.assign_count > 0) {
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
{
|
{
|
||||||
tracing::trace!("declare_decl(`{}`): Already declared", i);
|
tracing::trace!("declare_decl(`{}`): Already declared", i);
|
||||||
@ -486,10 +488,6 @@ impl VarDataLike for VarUsageInfo {
|
|||||||
self.mutated = true;
|
self.mutated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_reassigned(&mut self) {
|
|
||||||
self.reassigned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mark_used_as_ref(&mut self) {
|
fn mark_used_as_ref(&mut self) {
|
||||||
self.used_as_ref = true;
|
self.used_as_ref = true;
|
||||||
}
|
}
|
||||||
@ -620,23 +618,29 @@ impl ProgramData {
|
|||||||
|
|
||||||
if is_modify && ctx.is_exact_reassignment {
|
if is_modify && ctx.is_exact_reassignment {
|
||||||
if is_first {
|
if is_first {
|
||||||
|
if e.assign_count > 0 || e.initialized() {
|
||||||
|
e.reassigned = true
|
||||||
|
}
|
||||||
|
|
||||||
e.assign_count += 1;
|
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
|
||||||
|
{
|
||||||
|
self.initialized_vars.insert(i.clone());
|
||||||
|
e.assign_count -= 1;
|
||||||
|
e.var_initialized = true;
|
||||||
|
} else {
|
||||||
|
e.reassigned = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.is_op_assign {
|
if ctx.is_op_assign {
|
||||||
e.usage_count += 1;
|
e.usage_count += 1;
|
||||||
} else if is_first {
|
|
||||||
if e.ref_count == 1
|
|
||||||
&& ctx.in_assign_lhs
|
|
||||||
&& 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for other in e.infects_to.clone() {
|
for other in e.infects_to.clone() {
|
||||||
|
File diff suppressed because one or more lines are too long
@ -67,8 +67,6 @@ pub trait VarDataLike: Sized {
|
|||||||
|
|
||||||
fn mark_mutated(&mut self);
|
fn mark_mutated(&mut self);
|
||||||
|
|
||||||
fn mark_reassigned(&mut self);
|
|
||||||
|
|
||||||
fn mark_used_as_ref(&mut self);
|
fn mark_used_as_ref(&mut self);
|
||||||
|
|
||||||
fn add_infects_to(&mut self, other: Access);
|
fn add_infects_to(&mut self, other: Access);
|
||||||
|
Loading…
Reference in New Issue
Block a user