Skip to content

Commit 6a3f79a

Browse files
committed
refact(es/minifier): Inline into shorthand prop early
1 parent cd3dc01 commit 6a3f79a

File tree

3 files changed

+85
-63
lines changed

3 files changed

+85
-63
lines changed

crates/swc_ecma_minifier/src/compress/optimize/inline.rs

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,6 @@ impl Optimizer<'_> {
912912
}
913913
}
914914

915-
/// Actually inlines variables.
916915
pub(super) fn inline(&mut self, e: &mut Expr) {
917916
if self.ctx.bit_ctx.contains(BitCtx::IsExactLhsOfAssign) {
918917
return;
@@ -936,81 +935,89 @@ impl Optimizer<'_> {
936935
}
937936
}
938937
Expr::Ident(i) => {
939-
let id = i.to_id();
940-
if let Some(value) = self.vars.lits.get(&id).or_else(|| {
941-
if self.ctx.bit_ctx.contains(BitCtx::IsCallee) {
942-
self.vars.simple_functions.get(&id)
943-
} else {
944-
None
945-
}
946-
}) {
947-
if !matches!(**value, Expr::Ident(..) | Expr::Member(..))
948-
&& self.ctx.bit_ctx.contains(BitCtx::IsUpdateArg)
949-
{
950-
return;
951-
}
952-
953-
// currently renamer relies on the fact no distinct var has same ctxt, we need
954-
// to remap all new bindings.
955-
let bindings: FxHashSet<Id> = collect_decls(value);
956-
let new_mark = Mark::new();
957-
let mut cache = FxHashMap::default();
958-
let mut remap = FxHashMap::default();
959-
960-
for id in bindings {
961-
let new_ctxt = cache
962-
.entry(id.1)
963-
.or_insert_with(|| id.1.apply_mark(new_mark));
938+
if let Some(value) = self.inline_ident(i) {
939+
*e = *value
940+
}
941+
}
942+
_ => (),
943+
}
944+
}
964945

965-
let new_ctxt = *new_ctxt;
946+
/// Actually inlines variables.
947+
pub(super) fn inline_ident(&mut self, ident: &Ident) -> Option<Box<Expr>> {
948+
let id = ident.to_id();
966949

967-
if let Some(usage) = self.data.vars.get(&id).cloned() {
968-
let new_id = (id.0.clone(), new_ctxt);
969-
self.data.vars.insert(new_id, usage);
970-
}
950+
if let Some(value) = self.vars.lits.get(&id).or_else(|| {
951+
if self.ctx.bit_ctx.contains(BitCtx::IsCallee) {
952+
self.vars.simple_functions.get(&id)
953+
} else {
954+
None
955+
}
956+
}) {
957+
if !matches!(**value, Expr::Ident(..) | Expr::Member(..))
958+
&& self.ctx.bit_ctx.contains(BitCtx::IsUpdateArg)
959+
{
960+
return None;
961+
}
971962

972-
remap.insert(id, new_ctxt);
973-
}
963+
// currently renamer relies on the fact no distinct var has same ctxt, we need
964+
// to remap all new bindings.
965+
let bindings: FxHashSet<Id> = collect_decls(value);
966+
let new_mark = Mark::new();
967+
let mut cache = FxHashMap::default();
968+
let mut remap = FxHashMap::default();
974969

975-
let mut value = value.clone();
976-
if !remap.is_empty() {
977-
let mut remapper = Remapper::new(&remap);
978-
value.visit_mut_with(&mut remapper);
979-
}
970+
for id in bindings {
971+
let new_ctxt = cache
972+
.entry(id.1)
973+
.or_insert_with(|| id.1.apply_mark(new_mark));
980974

981-
self.changed = true;
982-
report_change!("inline: Replacing a variable `{}` with cheap expression", i);
975+
let new_ctxt = *new_ctxt;
983976

984-
*e = *value;
985-
return;
977+
if let Some(usage) = self.data.vars.get(&id).cloned() {
978+
let new_id = (id.0.clone(), new_ctxt);
979+
self.data.vars.insert(new_id, usage);
986980
}
987981

988-
// Check without cloning
989-
if let Some(value) = self.vars.vars_for_inlining.get(&id) {
990-
if self.ctx.bit_ctx.contains(BitCtx::IsExactLhsOfAssign)
991-
&& !is_valid_for_lhs(value)
992-
{
993-
return;
994-
}
982+
remap.insert(id, new_ctxt);
983+
}
995984

996-
if let Expr::Member(..) = &**value {
997-
if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) {
998-
return;
999-
}
1000-
}
1001-
}
985+
let mut value = value.clone();
986+
if !remap.is_empty() {
987+
let mut remapper = Remapper::new(&remap);
988+
value.visit_mut_with(&mut remapper);
989+
}
1002990

1003-
if let Some(value) = self.vars.vars_for_inlining.remove(&id) {
1004-
self.changed = true;
1005-
report_change!("inline: Replacing '{}' with an expression", i);
991+
self.changed = true;
992+
report_change!(
993+
"inline: Replacing a variable `{}` with cheap expression",
994+
ident
995+
);
1006996

1007-
*e = *value;
997+
return Some(value);
998+
}
999+
1000+
// Check without cloning
1001+
if let Some(value) = self.vars.vars_for_inlining.get(&id) {
1002+
if self.ctx.bit_ctx.contains(BitCtx::IsExactLhsOfAssign) && !is_valid_for_lhs(value) {
1003+
return None;
1004+
}
10081005

1009-
log_abort!("inline: [Change] {}", crate::debug::dump(&*e, false))
1006+
if let Expr::Member(..) = &**value {
1007+
if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) {
1008+
return None;
10101009
}
10111010
}
1012-
_ => (),
10131011
}
1012+
1013+
if let Some(value) = self.vars.vars_for_inlining.remove(&id) {
1014+
self.changed = true;
1015+
report_change!("inline: Replacing '{}' with an expression", ident);
1016+
1017+
return Some(value);
1018+
}
1019+
1020+
None
10141021
}
10151022
}
10161023

crates/swc_ecma_minifier/src/compress/optimize/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use super::util::{drop_invalid_stmts, is_fine_for_if_cons};
2626
#[cfg(feature = "debug")]
2727
use crate::debug::dump;
2828
use crate::{
29-
compress::{optimize::util::get_ids_of_pat, util::is_pure_undefined},
29+
compress::{
30+
optimize::util::{get_ids_of_pat, prop_name_from_ident},
31+
util::is_pure_undefined,
32+
},
3033
debug::AssertValid,
3134
maybe_par,
3235
mode::Mode,
@@ -2489,6 +2492,18 @@ impl VisitMut for Optimizer<'_> {
24892492
n.retain(|p| !p.pat.is_invalid());
24902493
}
24912494

2495+
fn visit_mut_prop(&mut self, n: &mut Prop) {
2496+
n.visit_mut_children_with(self);
2497+
2498+
if let Prop::Shorthand(i) = n {
2499+
if let Some(expr) = self.inline_ident(i) {
2500+
let key = prop_name_from_ident(i.take());
2501+
*n = Prop::KeyValue(KeyValueProp { key, value: expr });
2502+
self.changed = true;
2503+
}
2504+
}
2505+
}
2506+
24922507
#[cfg_attr(feature = "debug", tracing::instrument(level = "debug", skip_all))]
24932508
fn visit_mut_return_stmt(&mut self, n: &mut ReturnStmt) {
24942509
n.visit_mut_children_with(self);

crates/swc_ecma_minifier/src/compress/optimize/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ pub fn get_ids_of_pat(pat: &Pat) -> Vec<Id> {
826826
/// Creates a PropName for a shorthand property, handling the special case of
827827
/// `__proto__`. When the property name is `__proto__`, it must be converted to
828828
/// a computed property to preserve JavaScript semantics.
829-
fn prop_name_from_ident(ident: Ident) -> PropName {
829+
pub(crate) fn prop_name_from_ident(ident: Ident) -> PropName {
830830
if ident.sym == "__proto__" {
831831
PropName::Computed(ComputedPropName {
832832
span: ident.span,

0 commit comments

Comments
 (0)