Skip to content

Commit 99495bd

Browse files
authored
perf(es/minifier): Use bitflags to reduce compress context size (#10381)
Related #10379 context 48 bytes -> 24 bytes
1 parent 126d432 commit 99495bd

File tree

13 files changed

+338
-348
lines changed

13 files changed

+338
-348
lines changed

Diff for: Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: crates/swc_ecma_minifier/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ trace-ast = []
3333
[dependencies]
3434
arrayvec = { workspace = true }
3535
backtrace = { workspace = true, optional = true }
36+
bitflags = { workspace = true }
3637
indexmap = { workspace = true }
3738
num-bigint = { workspace = true }
3839
num_cpus = { workspace = true }

Diff for: crates/swc_ecma_minifier/src/compress/optimize/conditionals.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use swc_ecma_utils::{ExprExt, ExprFactory, IdentUsageFinder, StmtExt, StmtLike};
99
use super::Optimizer;
1010
use crate::{
1111
compress::{
12-
optimize::Ctx,
12+
optimize::BitCtx,
1313
util::{negate, negate_cost},
1414
},
1515
DISABLE_BUGGY_PASSES,
@@ -32,10 +32,7 @@ impl Optimizer<'_> {
3232

3333
if negate_cost(self.ctx.expr_ctx, &stmt.test, true, false) < 0 {
3434
report_change!("if_return: Negating `cond` of an if statement which has cons and alt");
35-
let ctx = Ctx {
36-
in_bool_ctx: true,
37-
..self.ctx.clone()
38-
};
35+
let ctx = self.ctx.clone().with(BitCtx::InBoolCtx, true);
3936
self.with_ctx(ctx).negate(&mut stmt.test, false);
4037
swap(alt, &mut *stmt.cons);
4138
return;

Diff for: crates/swc_ecma_minifier/src/compress/optimize/dead_code.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use swc_common::util::take::Take;
22
use swc_ecma_ast::*;
33

4-
use super::Optimizer;
4+
use super::{BitCtx, Optimizer};
55

66
/// Methods related to option `dead_code`.
77
impl Optimizer<'_> {
@@ -38,7 +38,7 @@ impl Optimizer<'_> {
3838
}
3939

4040
// A return statement in a try block may not terminate function.
41-
if self.ctx.in_try_block {
41+
if self.ctx.bit_ctx.contains(BitCtx::InTryBlock) {
4242
return false;
4343
}
4444

Diff for: crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use swc_common::{util::take::Take, Spanned, SyntaxContext, DUMMY_SP};
55
use swc_ecma_ast::*;
66
use swc_ecma_utils::{ExprExt, Value::Known};
77

8-
use super::Optimizer;
8+
use super::{BitCtx, Optimizer};
99
use crate::{compress::util::eval_as_number, maybe_par, DISABLE_BUGGY_PASSES};
1010

1111
/// Methods related to the option `evaluate`.
@@ -24,7 +24,11 @@ impl Optimizer<'_> {
2424
}
2525

2626
fn eval_fn_props(&mut self, e: &mut Expr) -> Option<()> {
27-
if self.ctx.is_delete_arg || self.ctx.is_update_arg || self.ctx.is_lhs_of_assign {
27+
if self
28+
.ctx
29+
.bit_ctx
30+
.intersects(BitCtx::IsDeleteArg | BitCtx::IsUpdateArg | BitCtx::IsLhsOfAssign)
31+
{
2832
return None;
2933
}
3034

@@ -84,11 +88,9 @@ impl Optimizer<'_> {
8488
return;
8589
}
8690

87-
if self.ctx.is_delete_arg
88-
|| self.ctx.is_update_arg
89-
|| self.ctx.is_lhs_of_assign
90-
|| self.ctx.in_with_stmt
91-
{
91+
if self.ctx.bit_ctx.intersects(
92+
BitCtx::IsDeleteArg | BitCtx::IsUpdateArg | BitCtx::IsLhsOfAssign | BitCtx::InWithStmt,
93+
) {
9294
return;
9395
}
9496

@@ -145,7 +147,11 @@ impl Optimizer<'_> {
145147
return;
146148
}
147149

148-
if self.ctx.is_delete_arg || self.ctx.is_update_arg || self.ctx.is_lhs_of_assign {
150+
if self
151+
.ctx
152+
.bit_ctx
153+
.intersects(BitCtx::IsDeleteArg | BitCtx::IsUpdateArg | BitCtx::IsLhsOfAssign)
154+
{
149155
return;
150156
}
151157

@@ -336,7 +342,11 @@ impl Optimizer<'_> {
336342
return;
337343
}
338344

339-
if self.ctx.is_delete_arg || self.ctx.is_update_arg || self.ctx.is_lhs_of_assign {
345+
if self
346+
.ctx
347+
.bit_ctx
348+
.intersects(BitCtx::IsDeleteArg | BitCtx::IsUpdateArg | BitCtx::IsLhsOfAssign)
349+
{
340350
return;
341351
}
342352

Diff for: crates/swc_ecma_minifier/src/compress/optimize/if_return.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
77
use super::Optimizer;
88
#[cfg(feature = "debug")]
99
use crate::debug::dump;
10-
use crate::{compress::util::is_pure_undefined, util::ExprOptExt};
10+
use crate::{
11+
compress::{optimize::BitCtx, util::is_pure_undefined},
12+
util::ExprOptExt,
13+
};
1114

1215
/// Methods related to the option `if_return`. All methods are noop if
1316
/// `if_return` is false.
@@ -220,7 +223,7 @@ impl Optimizer<'_> {
220223
.last()
221224
.map(|stmt| match stmt.as_stmt() {
222225
Some(Stmt::If(IfStmt { alt: None, .. }))
223-
if self.ctx.is_nested_if_return_merging =>
226+
if self.ctx.bit_ctx.contains(BitCtx::IsNestedIfReturnMerging) =>
224227
{
225228
false
226229
}

Diff for: crates/swc_ecma_minifier/src/compress/optimize/iife.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ use swc_ecma_ast::*;
66
use swc_ecma_utils::{contains_arguments, contains_this_expr, find_pat_ids, ExprFactory};
77
use swc_ecma_visit::{noop_visit_type, Visit, VisitMutWith, VisitWith};
88

9-
use super::{util::NormalMultiReplacer, Optimizer};
9+
use super::{util::NormalMultiReplacer, BitCtx, Optimizer};
1010
#[cfg(feature = "debug")]
1111
use crate::debug::dump;
1212
use crate::{
13-
compress::optimize::Ctx,
1413
program_data::{ProgramData, ScopeData},
1514
util::{idents_captured_by, make_number},
1615
};
@@ -19,7 +18,12 @@ use crate::{
1918
impl Optimizer<'_> {
2019
/// Negates iife, while ignore return value.
2120
pub(super) fn negate_iife_ignoring_ret(&mut self, e: &mut Expr) {
22-
if !self.options.negate_iife || self.ctx.in_bang_arg || self.ctx.dont_use_negated_iife {
21+
if !self.options.negate_iife
22+
|| self
23+
.ctx
24+
.bit_ctx
25+
.intersects(BitCtx::InBangArg | BitCtx::DontUseNegatedIife)
26+
{
2327
return;
2428
}
2529

@@ -81,7 +85,7 @@ impl Optimizer<'_> {
8185
}
8286

8387
pub(super) fn restore_negated_iife(&mut self, cond: &mut CondExpr) {
84-
if !self.ctx.dont_use_negated_iife {
88+
if !self.ctx.bit_ctx.contains(BitCtx::DontUseNegatedIife) {
8589
return;
8690
}
8791

@@ -290,11 +294,11 @@ impl Optimizer<'_> {
290294
return;
291295
}
292296

293-
let ctx = Ctx {
294-
in_fn_like: true,
295-
top_level: false,
296-
..self.ctx.clone()
297-
};
297+
let ctx = self
298+
.ctx
299+
.clone()
300+
.with(BitCtx::InFnLike, true)
301+
.with(BitCtx::TopLevel, false);
298302
let mut optimizer = self.with_ctx(ctx);
299303
match find_body(callee) {
300304
Some(Either::Left(body)) => {
@@ -439,7 +443,7 @@ impl Optimizer<'_> {
439443
Callee::Expr(e) => &**e,
440444
};
441445

442-
if self.ctx.dont_invoke_iife {
446+
if self.ctx.bit_ctx.contains(BitCtx::DontInvokeIife) {
443447
log_abort!("iife: Inline is prevented");
444448
return false;
445449
}
@@ -465,7 +469,7 @@ impl Optimizer<'_> {
465469
return false;
466470
}
467471

468-
if self.ctx.in_param && !f.params.is_empty() {
472+
if self.ctx.bit_ctx.contains(BitCtx::InParam) && !f.params.is_empty() {
469473
log_abort!("iife: We don't invoke IIFE with params in function params");
470474
return false;
471475
}
@@ -486,7 +490,7 @@ impl Optimizer<'_> {
486490
return false;
487491
}
488492

489-
if self.ctx.in_param && !f.function.params.is_empty() {
493+
if self.ctx.bit_ctx.contains(BitCtx::InParam) && !f.function.params.is_empty() {
490494
log_abort!("iife: We don't invoke IIFE with params in function params");
491495
return false;
492496
}
@@ -582,7 +586,7 @@ impl Optimizer<'_> {
582586
}
583587

584588
if let Expr::Lit(Lit::Num(..)) = &**body {
585-
if self.ctx.in_obj_of_non_computed_member {
589+
if self.ctx.bit_ctx.contains(BitCtx::InObjOfNonComputedMember) {
586590
return;
587591
}
588592
}
@@ -803,7 +807,7 @@ impl Optimizer<'_> {
803807
}
804808
}
805809

806-
if self.ctx.executed_multiple_time {
810+
if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) {
807811
if !param_ids.is_empty() {
808812
let captured = idents_captured_by(body);
809813

@@ -858,7 +862,7 @@ impl Optimizer<'_> {
858862
}
859863
}
860864

861-
if self.ctx.executed_multiple_time {
865+
if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) {
862866
return false;
863867
}
864868

@@ -875,7 +879,7 @@ impl Optimizer<'_> {
875879
Some(Expr::Await(..)) => false,
876880

877881
Some(Expr::Lit(Lit::Num(..))) => {
878-
for_stmt || !self.ctx.in_obj_of_non_computed_member
882+
for_stmt || !self.ctx.bit_ctx.contains(BitCtx::InObjOfNonComputedMember)
879883
}
880884
_ => true,
881885
},
@@ -935,7 +939,7 @@ impl Optimizer<'_> {
935939
vars.push(VarDeclarator {
936940
span: DUMMY_SP,
937941
name: param.clone().into(),
938-
init: if self.ctx.executed_multiple_time && no_arg {
942+
init: if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) && no_arg {
939943
Some(Expr::undefined(DUMMY_SP))
940944
} else {
941945
None
@@ -983,7 +987,7 @@ impl Optimizer<'_> {
983987
vars.push(VarDeclarator {
984988
span: DUMMY_SP,
985989
name: param.clone().into(),
986-
init: if self.ctx.executed_multiple_time && arg.is_none() {
990+
init: if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) && arg.is_none() {
987991
Some(Expr::undefined(DUMMY_SP))
988992
} else {
989993
arg

Diff for: crates/swc_ecma_minifier/src/compress/optimize/inline.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use swc_ecma_visit::VisitMutWith;
77

88
use super::Optimizer;
99
use crate::{
10-
compress::optimize::util::is_valid_for_lhs,
10+
compress::optimize::{util::is_valid_for_lhs, BitCtx},
1111
program_data::VarUsageInfo,
1212
util::{
1313
idents_captured_by, idents_used_by, idents_used_by_ignoring_nested, size::SizeWithCtxt,
@@ -339,7 +339,7 @@ impl Optimizer<'_> {
339339
let usage = self.data.vars.get(&id).unwrap();
340340

341341
// Single use => inlined
342-
if !self.ctx.is_exported
342+
if !self.ctx.bit_ctx.contains(BitCtx::IsExported)
343343
&& is_inline_enabled
344344
&& usage.declared
345345
&& may_remove
@@ -623,7 +623,7 @@ impl Optimizer<'_> {
623623
}
624624
}
625625

626-
if self.ctx.is_exported {
626+
if self.ctx.bit_ctx.contains(BitCtx::IsExported) {
627627
log_abort!("inline: [x] exported");
628628
return;
629629
}
@@ -797,7 +797,7 @@ impl Optimizer<'_> {
797797

798798
/// Actually inlines variables.
799799
pub(super) fn inline(&mut self, e: &mut Expr) {
800-
if self.ctx.is_exact_lhs_of_assign {
800+
if self.ctx.bit_ctx.contains(BitCtx::IsExactLhsOfAssign) {
801801
return;
802802
}
803803

@@ -825,7 +825,7 @@ impl Optimizer<'_> {
825825
.lits
826826
.get(&id)
827827
.or_else(|| {
828-
if self.ctx.is_callee {
828+
if self.ctx.bit_ctx.contains(BitCtx::IsCallee) {
829829
self.vars.simple_functions.get(&i.to_id())
830830
} else {
831831
None
@@ -834,7 +834,7 @@ impl Optimizer<'_> {
834834
.cloned()
835835
{
836836
if !matches!(&*value, Expr::Ident(..) | Expr::Member(..))
837-
&& self.ctx.is_update_arg
837+
&& self.ctx.bit_ctx.contains(BitCtx::IsUpdateArg)
838838
{
839839
return;
840840
}
@@ -875,12 +875,14 @@ impl Optimizer<'_> {
875875

876876
// Check without cloning
877877
if let Some(value) = self.vars.vars_for_inlining.get(&i.to_id()) {
878-
if self.ctx.is_exact_lhs_of_assign && !is_valid_for_lhs(value) {
878+
if self.ctx.bit_ctx.contains(BitCtx::IsExactLhsOfAssign)
879+
&& !is_valid_for_lhs(value)
880+
{
879881
return;
880882
}
881883

882884
if let Expr::Member(..) = &**value {
883-
if self.ctx.executed_multiple_time {
885+
if self.ctx.bit_ctx.contains(BitCtx::ExecutedMultipleTime) {
884886
return;
885887
}
886888
}

0 commit comments

Comments
 (0)