Skip to content

Commit 773d19c

Browse files
authored
perf(es/minifier): Use bigflags to reduce context size of analyzer (#10380)
Related #10379 Context: 16 bytes -> 8 bytes
1 parent b4b3aff commit 773d19c

File tree

6 files changed

+248
-284
lines changed

6 files changed

+248
-284
lines changed

.changeset/five-jobs-teach.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
swc_ecma_minifier: minor
3+
swc_ecma_usage_analyzer: minor
4+
swc_core: minor
5+
---
6+
7+
perf(es/usage_analyzer): Use bigflags to reduce context size

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/swc_ecma_minifier/src/program_data.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ impl Storage for ProgramData {
345345
})
346346
});
347347

348-
e.used_as_ref |= ctx.is_id_ref;
348+
e.used_as_ref |= ctx.is_id_ref();
349349
e.ref_count += 1;
350350
e.usage_count += 1;
351351
// If it is inited in some child scope, but referenced in current scope
@@ -354,9 +354,9 @@ impl Storage for ProgramData {
354354
e.var_initialized = false;
355355
}
356356

357-
e.inline_prevented |= ctx.inline_prevented;
358-
e.executed_multiple_time |= ctx.executed_multiple_time;
359-
e.used_in_cond |= ctx.in_cond;
357+
e.inline_prevented |= ctx.inline_prevented();
358+
e.executed_multiple_time |= ctx.executed_multiple_time();
359+
e.used_in_cond |= ctx.in_cond();
360360
}
361361

362362
fn report_assign(&mut self, ctx: Ctx, i: Id, is_op: bool, ty: Value<Type>) {
@@ -395,9 +395,9 @@ impl Storage for ProgramData {
395395
let curr = &to_visit[idx];
396396

397397
if let Some(usage) = self.vars.get_mut(curr) {
398-
usage.inline_prevented |= ctx.inline_prevented;
399-
usage.executed_multiple_time |= ctx.executed_multiple_time;
400-
usage.used_in_cond |= ctx.in_cond;
398+
usage.inline_prevented |= ctx.inline_prevented();
399+
usage.executed_multiple_time |= ctx.executed_multiple_time();
400+
usage.used_in_cond |= ctx.in_cond();
401401

402402
if is_op {
403403
usage.usage_count += 1;
@@ -422,7 +422,7 @@ impl Storage for ProgramData {
422422
// }
423423

424424
let v = self.vars.entry(i.to_id()).or_default();
425-
v.is_top_level |= ctx.is_top_level;
425+
v.is_top_level |= ctx.is_top_level();
426426

427427
// assigned or declared before this declaration
428428
if init_type.is_some() {
@@ -441,7 +441,8 @@ impl Storage for ProgramData {
441441
// This is not delcared yet, so this is the first declaration.
442442
if !v.declared {
443443
v.var_kind = kind;
444-
v.no_side_effect_for_member_access = ctx.in_decl_with_no_side_effect_for_member_access;
444+
v.no_side_effect_for_member_access =
445+
ctx.in_decl_with_no_side_effect_for_member_access();
445446
}
446447

447448
if v.used_in_non_child_fn {
@@ -450,7 +451,7 @@ impl Storage for ProgramData {
450451

451452
v.var_initialized |= init_type.is_some();
452453

453-
if ctx.in_pat_of_param {
454+
if ctx.in_pat_of_param() {
454455
v.merged_var_type = Some(Value::Unknown);
455456
} else {
456457
v.merged_var_type.merge(init_type);
@@ -462,7 +463,7 @@ impl Storage for ProgramData {
462463
if init_type.is_some() || kind.is_none() {
463464
self.initialized_vars.insert(i.to_id());
464465
}
465-
v.declared_as_catch_param |= ctx.in_catch_param;
466+
v.declared_as_catch_param |= ctx.in_catch_param();
466467

467468
v
468469
}

crates/swc_ecma_usage_analyzer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ trace-ast = []
2323
tracing-spans = []
2424

2525
[dependencies]
26+
bitflags = { workspace = true }
2627
indexmap = { workspace = true }
2728
rustc-hash = { workspace = true }
2829
tracing = { workspace = true }

crates/swc_ecma_usage_analyzer/src/analyzer/ctx.rs

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use std::ops::{Deref, DerefMut};
44

5+
use bitflags::bitflags;
56
use swc_ecma_ast::VarDeclKind;
67
use swc_ecma_utils::{Type, Value};
78

@@ -25,26 +26,82 @@ where
2526
#[non_exhaustive]
2627
pub struct Ctx {
2728
pub var_decl_kind_of_pat: Option<VarDeclKind>,
29+
pub in_pat_of_var_decl_with_init: Option<Value<Type>>,
30+
pub(crate) bit_ctx: BitContext,
31+
}
2832

29-
pub in_decl_with_no_side_effect_for_member_access: bool,
33+
impl Ctx {
34+
#[inline]
35+
pub(crate) fn with(mut self, flag: BitContext, value: bool) -> Self {
36+
self.bit_ctx = self.bit_ctx.with(flag, value);
37+
self
38+
}
3039

31-
pub in_pat_of_var_decl: bool,
32-
pub in_pat_of_var_decl_with_init: Option<Value<Type>>,
33-
pub in_pat_of_param: bool,
34-
pub in_catch_param: bool,
40+
#[inline]
41+
pub fn in_decl_with_no_side_effect_for_member_access(&self) -> bool {
42+
self.bit_ctx
43+
.contains(BitContext::InDeclWithNoSideEffectForMemberAccess)
44+
}
3545

36-
pub is_id_ref: bool,
46+
#[inline]
47+
pub fn in_pat_of_param(&self) -> bool {
48+
self.bit_ctx.contains(BitContext::InPatOfParam)
49+
}
3750

38-
pub in_await_arg: bool,
51+
#[inline]
52+
pub fn in_catch_param(&self) -> bool {
53+
self.bit_ctx.contains(BitContext::InCatchParam)
54+
}
3955

40-
pub in_left_of_for_loop: bool,
56+
#[inline]
57+
pub fn is_id_ref(&self) -> bool {
58+
self.bit_ctx.contains(BitContext::IsIdRef)
59+
}
4160

42-
pub executed_multiple_time: bool,
43-
pub in_cond: bool,
61+
#[inline]
62+
pub fn inline_prevented(&self) -> bool {
63+
self.bit_ctx.contains(BitContext::InlinePrevented)
64+
}
4465

45-
pub inline_prevented: bool,
66+
#[inline]
67+
pub fn in_cond(&self) -> bool {
68+
self.bit_ctx.contains(BitContext::InCond)
69+
}
4670

47-
pub is_top_level: bool,
71+
#[inline]
72+
pub fn executed_multiple_time(&self) -> bool {
73+
self.bit_ctx.contains(BitContext::ExecutedMultipleTime)
74+
}
75+
76+
#[inline]
77+
pub fn is_top_level(&self) -> bool {
78+
self.bit_ctx.contains(BitContext::IsTopLevel)
79+
}
80+
}
81+
82+
bitflags! {
83+
#[derive(Debug, Clone, Copy, Default)]
84+
pub(crate) struct BitContext: u16 {
85+
const InDeclWithNoSideEffectForMemberAccess = 1 << 0;
86+
const InPatOfVarDecl = 1 << 1;
87+
const InPatOfParam = 1 << 2;
88+
const InCatchParam = 1 << 3;
89+
const IsIdRef = 1 << 4;
90+
const InAwaitArg = 1 << 5;
91+
const InLeftOfForLoop = 1 << 6;
92+
const ExecutedMultipleTime = 1 << 7;
93+
const InCond = 1 << 8;
94+
const InlinePrevented = 1 << 9;
95+
const IsTopLevel = 1 << 10;
96+
}
97+
}
98+
99+
impl BitContext {
100+
#[inline]
101+
pub fn with(mut self, flag: Self, value: bool) -> Self {
102+
self.set(flag, value);
103+
self
104+
}
48105
}
49106

50107
pub(super) struct WithCtx<'a, S>

0 commit comments

Comments
 (0)