From 0b9799dc2682ed0d578fdbc8bc8a6d1417392af8 Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 29 Sep 2026 17:38:17 +0200 Subject: [PATCH] perf(minifier): reduce usage of minimize_conditional (#26028) `minimize_conditional_expression` is complex and long this is first step that simplifies generation this refactor, this can be simplified further as we should not need almost any dummy nodes in here, but for now we are going to just reuse exsiting nodes instead of rebuilding everything --- .../minimize_conditional_expression.rs | 97 ++++++++----------- .../allocs_minifier.yaml | 6 +- 2 files changed, 45 insertions(+), 58 deletions(-) diff --git a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs index 39076f20dd..1d3349f593 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs @@ -51,24 +51,13 @@ impl<'a> PeepholeOptimizations { ctx: &mut TraverseCtx<'a>, ) -> Option> { match &mut expr.test { - // "(a, b) ? c : d" => "a, b ? c : d" + // `(a, b) ? c : d` => `a, b ? c : d` Expression::SequenceExpression(sequence_expr) if sequence_expr.expressions.len() > 1 => { - let span = expr.span(); - let mut sequence = expr.test.take_in(ctx); - let Expression::SequenceExpression(sequence_expr) = &mut sequence else { - unreachable!() - }; - let expr = Self::minimize_conditional( - span, - sequence_expr.expressions.pop().unwrap(), - expr.consequent.take_in(ctx), - expr.alternate.take_in(ctx), - ctx, - ); - sequence_expr.expressions.push(expr); - return Some(sequence); + let ConditionalExpression { test, consequent, alternate, span, .. } = + expr.take_in(ctx); + return Some(Self::minimize_conditional(span, test, consequent, alternate, ctx)); } // "!a ? b : c" => "a ? c : b" Expression::UnaryExpression(test_expr) if test_expr.operator.is_not() => { @@ -116,42 +105,42 @@ impl<'a> PeepholeOptimizations { _ => {} } - // "a ? b ? c : d : d" => "a && b ? c : d" + // `a ? b ? c : d : d` => `a && b ? c : d` if let Expression::ConditionalExpression(consequent) = &mut expr.consequent && ctx.expr_eq(&consequent.alternate, &expr.alternate) { - return Some(Expression::new_conditional_expression( - expr.span, + let cons_expr = consequent.take_in(ctx); + ctx.replace_expression_with(&mut expr.test, |expr_0, ctx| { Self::join_with_left_associative_op( - expr.test.span(), + expr_0.span(), LogicalOperator::And, - expr.test.take_in(ctx), - consequent.test.take_in(ctx), + expr_0, + cons_expr.test, ctx, - ), - consequent.consequent.take_in(ctx), - consequent.alternate.take_in(ctx), - ctx, - )); + ) + }); + ctx.replace_expression(&mut expr.consequent, cons_expr.consequent); + ctx.drop_expression(&cons_expr.alternate); + return Self::minimize_conditional_expression(expr, ctx); } - // "a ? b : c ? b : d" => "a || c ? b : d" + // `a ? b : c ? b : d` => `a || c ? b : d` if let Expression::ConditionalExpression(alternate) = &mut expr.alternate && ctx.expr_eq(&alternate.consequent, &expr.consequent) { - return Some(Expression::new_conditional_expression( - expr.span, + let alt_expr = alternate.take_in(ctx); + ctx.replace_expression_with(&mut expr.test, |expr_0, ctx| { Self::join_with_left_associative_op( - expr.test.span(), + expr_0.span(), LogicalOperator::Or, - expr.test.take_in(ctx), - alternate.test.take_in(ctx), + expr_0, + alt_expr.test, ctx, - ), - expr.consequent.take_in(ctx), - alternate.alternate.take_in(ctx), - ctx, - )); + ) + }); + ctx.replace_expression(&mut expr.alternate, alt_expr.alternate); + ctx.drop_expression(&alt_expr.consequent); + return Self::minimize_conditional_expression(expr, ctx); } // `a ? c : (b, c)` => `(a || b), c` @@ -213,44 +202,42 @@ impl<'a> PeepholeOptimizations { )); } - // "a ? b || c : c" => "(a && b) || c" + // `a ? b || c : c` => `(a && b) || c` if let Expression::LogicalExpression(logical_expr) = &mut expr.consequent && logical_expr.operator.is_or() && ctx.expr_eq(&logical_expr.right, &expr.alternate) { - return Some(Expression::new_logical_expression( - expr.span, + let mut new_logical = logical_expr.take_in_box(ctx); + new_logical.span = expr.span(); + ctx.replace_expression_with(&mut new_logical.left, |left, ctx| { Self::join_with_left_associative_op( expr.test.span(), LogicalOperator::And, expr.test.take_in(ctx), - logical_expr.left.take_in(ctx), + left, ctx, - ), - LogicalOperator::Or, - expr.alternate.take_in(ctx), - ctx, - )); + ) + }); + return Some(Expression::LogicalExpression(new_logical)); } - // "a ? c : b && c" => "(a || b) && c" + // `a ? c : b && c` => `(a || b) && c` if let Expression::LogicalExpression(logical_expr) = &mut expr.alternate && logical_expr.operator == LogicalOperator::And && ctx.expr_eq(&logical_expr.right, &expr.consequent) { - return Some(Expression::new_logical_expression( - expr.span, + let mut new_logical = logical_expr.take_in_box(ctx); + new_logical.span = expr.span(); + ctx.replace_expression_with(&mut new_logical.left, |left, ctx| { Self::join_with_left_associative_op( expr.test.span(), LogicalOperator::Or, expr.test.take_in(ctx), - logical_expr.left.take_in(ctx), + left, ctx, - ), - LogicalOperator::And, - expr.consequent.take_in(ctx), - ctx, - )); + ) + }); + return Some(Expression::LogicalExpression(new_logical)); } // `a ? b(c, d) : b(e, d)` -> `b(a ? c : e, d)` diff --git a/tasks/track_memory_allocations/allocs_minifier.yaml b/tasks/track_memory_allocations/allocs_minifier.yaml index debb1af505..5b1c6e4d8a 100644 --- a/tasks/track_memory_allocations/allocs_minifier.yaml +++ b/tasks/track_memory_allocations/allocs_minifier.yaml @@ -5,7 +5,7 @@ checker.ts: sys deallocs: 122 sys alloc bytes: 14996287 # 15.00 MB sys peak growth: 10169560 # 10.17 MB - arena allocs: 56225 + arena allocs: 56217 arena reallocs: 5084 arena size: 16317568 # 16.32 MB @@ -16,7 +16,7 @@ App.tsx: sys deallocs: 61 sys alloc bytes: 2128539 # 2.13 MB sys peak growth: 1612427 # 1.61 MB - arena allocs: 7474 + arena allocs: 7470 arena reallocs: 920 arena size: 2683792 # 2.68 MB @@ -49,7 +49,7 @@ antd.js: sys deallocs: 860 sys alloc bytes: 29973448 # 29.97 MB sys peak growth: 19934725 # 19.93 MB - arena allocs: 181540 + arena allocs: 181536 arena reallocs: 34406 arena size: 43039192 # 43.04 MB