Skip to content

Commit

Permalink
perf(es/utils): Prevent too many recursion (swc-project#9931)
Browse files Browse the repository at this point in the history
**Description:**


![image](https://github.com/user-attachments/assets/40841d3a-9fbf-41b5-98dd-45320d2e5261)

Some functions may recurse too much and have a bad effect on the performance.
  • Loading branch information
kdy1 authored Jan 23, 2025
1 parent e4c1e03 commit d24f785
Show file tree
Hide file tree
Showing 51 changed files with 2,720 additions and 2,593 deletions.
6 changes: 6 additions & 0 deletions .changeset/tall-tigers-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
swc_ecma_ast: patch
swc_ecma_utils: major
---

perf(es/utils): Prevent too many recursion
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//// [destructuringArrayBindingPatternAndAssignment3.ts]
var _param, _param1, _param2;
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
var _param, _param1, tmp1, e, _param2, tmp2 = void 0, e1 = void 0 === tmp2 ? e1 : tmp2;
(_param = _sliced_to_array([
1
], 2))[0], _param[1], (_param1 = _sliced_to_array([
1
], 3))[0], _param1[1], _param1[2], (_param2 = _sliced_to_array([
], 3))[0], _param1[1], e = void 0 === (tmp1 = _param1[2]) ? e : tmp1, (_param2 = _sliced_to_array([
1
], 4))[0], _param2[1], _param2[2], _param2[3];
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
//// [destructuringObjectBindingPatternAndAssignment4.ts]
var _ref = {};
_ref.a, _ref.b, _ref.c, _ref.d, _ref.e, _ref.f;
var _ref = {}, _ref_f = (_ref.a, _ref.b, _ref.c, _ref.d, _ref.e, _ref.f), f = void 0 === _ref_f ? f : _ref_f;
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ var _ref2 = [
void 0,
void 0,
void 0
];
_ref2[0], _ref2[1], _ref2[2];
var _concat = _sliced_to_array([
], _concat = (_ref2[0], _ref2[1], _ref2[2], _sliced_to_array([
1,
"string"
].concat(_to_consumable_array([
!0,
!1,
!0
])), 2);
])), 2));
_concat[0], _concat[1];
var _ref_e = _sliced_to_array([
1,
Expand All @@ -29,14 +27,12 @@ var _ref_e = _sliced_to_array([
b1: 4,
b4: 0
}
], 3);
_ref_e[0], _ref_e[1], _ref_e[2];
var _ref_f = _sliced_to_array([
], 3), _ref_f = (_ref_e[0], _ref_e[1], _ref_e[2], _sliced_to_array([
1,
2,
{
f3: 4,
f5: 0
}
], 3), _ref_f_ = (_ref_f[0], _ref_f[1], _ref_f[2]);
], 3)), _ref_f_ = (_ref_f[0], _ref_f[1], _ref_f[2]);
_ref_f_.f3, _ref_f_.f5;
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ var _ref2 = [
void 0,
void 0,
void 0
];
_ref2[0], _ref2[1], _ref2[2];
var _concat = _sliced_to_array([
], _concat = (_ref2[0], _ref2[1], _ref2[2], _sliced_to_array([
1,
"string"
].concat(_to_consumable_array([
!0,
!1,
!0
])), 2);
])), 2));
_concat[0], _concat[1];
var _ref_e = _sliced_to_array([
1,
Expand All @@ -29,14 +27,12 @@ var _ref_e = _sliced_to_array([
b1: 4,
b4: 0
}
], 3);
_ref_e[0], _ref_e[1], _ref_e[2];
var _ref_f = _sliced_to_array([
], 3), _ref_f = (_ref_e[0], _ref_e[1], _ref_e[2], _sliced_to_array([
1,
2,
{
f3: 4,
f5: 0
}
], 3), _ref_f_ = (_ref_f[0], _ref_f[1], _ref_f[2]);
], 3)), _ref_f_ = (_ref_f[0], _ref_f[1], _ref_f[2]);
_ref_f_.f3, _ref_f_.f5;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//// [destructuringWithLiteralInitializers.ts]
var param, param1, param2, param3, param4, param5, param6, _param, _param1;
var param, _param, _param1, param1, param2, param3, param4, param5, param6;
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
function f4() {
var _ref = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//// [privateNameStaticEmitHelpers.ts]
//// [main.ts]
import "@swc/helpers/_/_class_static_private_field_spec_set";
import "@swc/helpers/_/_class_static_private_method_get";
import { _ as _class_static_private_field_spec_set } from "@swc/helpers/_/_class_static_private_field_spec_set";
import { _ as _class_static_private_method_get } from "@swc/helpers/_/_class_static_private_method_get";
export class S {
}
//// [tslib.d.ts]
Expand Down
8 changes: 6 additions & 2 deletions crates/swc_ecma_ast/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,13 @@ impl Expr {
}
}

pub fn is_ident_ref_to(&self, ident: &str) -> bool {
pub fn is_ident_ref_to<S>(&self, ident: &S) -> bool
where
S: ?Sized,
Atom: PartialEq<S>,
{
match self {
Expr::Ident(i) => i.sym == ident,
Expr::Ident(i) => i.sym == *ident,
_ => false,
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_minifier/src/compress/optimize/bools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl Optimizer<'_> {
is_ret_val_ignored: bool,
) -> bool {
let cost = negate_cost(
&self.ctx.expr_ctx,
self.ctx.expr_ctx,
expr,
is_ret_val_ignored,
is_ret_val_ignored,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Optimizer<'_> {
_ => {}
}

if negate_cost(&self.ctx.expr_ctx, &stmt.test, true, false) < 0 {
if negate_cost(self.ctx.expr_ctx, &stmt.test, true, false) < 0 {
report_change!("if_return: Negating `cond` of an if statement which has cons and alt");
let ctx = Ctx {
in_bool_ctx: true,
Expand Down Expand Up @@ -63,7 +63,7 @@ impl Optimizer<'_> {
_ => return,
};

if !cond.cons.may_have_side_effects(&self.ctx.expr_ctx) {
if !cond.cons.may_have_side_effects(self.ctx.expr_ctx) {
self.changed = true;
report_change!("conditionals: `cond ? useless : alt` => `cond || alt`");
*e = BinExpr {
Expand All @@ -76,7 +76,7 @@ impl Optimizer<'_> {
return;
}

if !cond.alt.may_have_side_effects(&self.ctx.expr_ctx) {
if !cond.alt.may_have_side_effects(self.ctx.expr_ctx) {
self.changed = true;
report_change!("conditionals: `cond ? cons : useless` => `cond && cons`");
*e = BinExpr {
Expand Down Expand Up @@ -880,7 +880,7 @@ impl Optimizer<'_> {
) = (&*cons, &*alt)
{
// I don't know why, but terser behaves differently
negate(&self.ctx.expr_ctx, &mut test, true, false);
negate(self.ctx.expr_ctx, &mut test, true, false);

swap(&mut cons, &mut alt);
}
Expand Down
16 changes: 8 additions & 8 deletions crates/swc_ecma_minifier/src/compress/optimize/evaluate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl Optimizer<'_> {
//

for arg in &*args {
if arg.spread.is_some() || arg.expr.may_have_side_effects(&self.ctx.expr_ctx) {
if arg.spread.is_some() || arg.expr.may_have_side_effects(self.ctx.expr_ctx) {
return;
}
}
Expand Down Expand Up @@ -233,7 +233,7 @@ impl Optimizer<'_> {
return;
}

if let Known(char_code) = args[0].expr.as_pure_number(&self.ctx.expr_ctx) {
if let Known(char_code) = args[0].expr.as_pure_number(self.ctx.expr_ctx) {
let v = char_code.floor() as u32;

if let Some(v) = char::from_u32(v) {
Expand Down Expand Up @@ -341,7 +341,7 @@ impl Optimizer<'_> {
}

if let Expr::Call(..) = e {
if let Some(value) = eval_as_number(&self.ctx.expr_ctx, e) {
if let Some(value) = eval_as_number(self.ctx.expr_ctx, e) {
self.changed = true;
report_change!("evaluate: Evaluated an expression as `{}`", value);

Expand All @@ -367,8 +367,8 @@ impl Optimizer<'_> {

match e {
Expr::Bin(bin @ BinExpr { op: op!("**"), .. }) => {
let l = bin.left.as_pure_number(&self.ctx.expr_ctx);
let r = bin.right.as_pure_number(&self.ctx.expr_ctx);
let l = bin.left.as_pure_number(self.ctx.expr_ctx);
let r = bin.right.as_pure_number(self.ctx.expr_ctx);

if let Known(l) = l {
if let Known(r) = r {
Expand All @@ -395,9 +395,9 @@ impl Optimizer<'_> {
}

Expr::Bin(bin @ BinExpr { op: op!("/"), .. }) => {
let ln = bin.left.as_pure_number(&self.ctx.expr_ctx);
let ln = bin.left.as_pure_number(self.ctx.expr_ctx);

let rn = bin.right.as_pure_number(&self.ctx.expr_ctx);
let rn = bin.right.as_pure_number(self.ctx.expr_ctx);
if let (Known(ln), Known(rn)) = (ln, rn) {
// Prefer `0/0` over NaN.
if ln == 0.0 && rn == 0.0 {
Expand Down Expand Up @@ -477,7 +477,7 @@ impl Optimizer<'_> {
}
// Remove rhs of lhs if possible.

let v = left.right.as_pure_bool(&self.ctx.expr_ctx);
let v = left.right.as_pure_bool(self.ctx.expr_ctx);
if let Known(v) = v {
// As we used as_pure_bool, we can drop it.
if v && e.op == op!("&&") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl Optimizer<'_> {
&& seq
.exprs
.last()
.map(|v| is_pure_undefined(&self.ctx.expr_ctx, v))
.map(|v| is_pure_undefined(self.ctx.expr_ctx, v))
.unwrap_or(true) =>
{
let expr = self.ignore_return_value(&mut cur);
Expand Down
6 changes: 3 additions & 3 deletions crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Optimizer<'_> {
if ref_count == 0 {
self.mode.store(ident.to_id(), &*init);

if init.may_have_side_effects(&self.ctx.expr_ctx) {
if init.may_have_side_effects(self.ctx.expr_ctx) {
// TODO: Inline partially
return;
}
Expand Down Expand Up @@ -502,7 +502,7 @@ impl Optimizer<'_> {
}
}

if init.may_have_side_effects(&self.ctx.expr_ctx) {
if init.may_have_side_effects(self.ctx.expr_ctx) {
return;
}

Expand Down Expand Up @@ -731,7 +731,7 @@ impl Optimizer<'_> {
})
{
if let Decl::Class(ClassDecl { class, .. }) = decl {
if class_has_side_effect(&self.ctx.expr_ctx, class) {
if class_has_side_effect(self.ctx.expr_ctx, class) {
return;
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/swc_ecma_minifier/src/compress/optimize/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Optimizer<'_> {

match stmt {
Stmt::While(w) => {
let (purity, val) = w.test.cast_to_bool(&self.ctx.expr_ctx);
let (purity, val) = w.test.cast_to_bool(self.ctx.expr_ctx);
if let Known(false) = val {
if purity.is_pure() {
let changed = UnreachableHandler::preserve_vars(stmt);
Expand All @@ -86,7 +86,7 @@ impl Optimizer<'_> {
}
Stmt::For(f) => {
if let Some(test) = &mut f.test {
let (purity, val) = test.cast_to_bool(&self.ctx.expr_ctx);
let (purity, val) = test.cast_to_bool(self.ctx.expr_ctx);
if let Known(false) = val {
let changed = UnreachableHandler::preserve_vars(&mut f.body);
self.changed |= changed;
Expand Down
Loading

0 comments on commit d24f785

Please sign in to comment.