mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-14 22:29:17 +00:00
perf(minifier): reduce allocations when minimizing assignments (#26609)
This commit is contained in:
1 parent
57c91ffce4
commit
fc37ba07d3
2 files changed
+45
-51
No files matched your search
@@ -1,4 +1,3 @@
|
||||
use oxc_allocator::TakeIn;
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_compat::ESFeature;
|
||||
use oxc_ecmascript::{
|
||||
@@ -73,18 +72,15 @@ impl<'a> PeepholeOptimizations {
|
||||
}
|
||||
// `NaN == 0` and `!NaN` differ, so require proof that the left side is a non-NaN Number.
|
||||
if e.right.is_number_0() && e.left.is_int32_or_uint32(ctx) {
|
||||
let argument = e.left.take_in(ctx);
|
||||
let mut new_expr =
|
||||
Expression::new_unary_expression(e.span, UnaryOperator::LogicalNot, argument, ctx);
|
||||
if matches!(e.operator, BinaryOperator::Inequality | BinaryOperator::StrictInequality) {
|
||||
new_expr = Expression::new_unary_expression(
|
||||
e.span,
|
||||
UnaryOperator::LogicalNot,
|
||||
new_expr,
|
||||
ctx,
|
||||
);
|
||||
}
|
||||
ctx.replace_expression(expr, new_expr);
|
||||
let inequal =
|
||||
matches!(e.operator, BinaryOperator::Inequality | BinaryOperator::StrictInequality);
|
||||
ctx.replace_expression_with(expr, |old, ctx| {
|
||||
let Expression::BinaryExpression(e) = old else { unreachable!() };
|
||||
let e = e.unbox();
|
||||
let value =
|
||||
if inequal { Self::minimize_not(e.span, e.left, ctx, true) } else { e.left };
|
||||
Expression::new_unary_expression(e.span, UnaryOperator::LogicalNot, value, ctx)
|
||||
});
|
||||
return;
|
||||
}
|
||||
let left = e.left.value_type(ctx);
|
||||
@@ -103,33 +99,22 @@ impl<'a> PeepholeOptimizations {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if !left.is_boolean() {
|
||||
return;
|
||||
}
|
||||
if e.right.may_have_side_effects(ctx) {
|
||||
if !left.is_boolean() || e.right.may_have_side_effects(ctx) {
|
||||
return;
|
||||
}
|
||||
let Some(mut b) = e.right.evaluate_value(ctx).and_then(ConstantValue::into_boolean) else {
|
||||
return;
|
||||
};
|
||||
match e.operator {
|
||||
BinaryOperator::Inequality | BinaryOperator::StrictInequality => {
|
||||
e.operator = BinaryOperator::Equality;
|
||||
b = !b;
|
||||
}
|
||||
BinaryOperator::StrictEquality => {
|
||||
e.operator = BinaryOperator::Equality;
|
||||
}
|
||||
BinaryOperator::Equality => {}
|
||||
_ => return,
|
||||
if matches!(e.operator, BinaryOperator::Inequality) {
|
||||
b = !b;
|
||||
}
|
||||
let new_expr = if b {
|
||||
e.left.take_in(ctx)
|
||||
} else {
|
||||
let argument = e.left.take_in(ctx);
|
||||
Expression::new_unary_expression(e.span, UnaryOperator::LogicalNot, argument, ctx)
|
||||
};
|
||||
ctx.replace_expression(expr, new_expr);
|
||||
|
||||
ctx.drop_expression(&e.right);
|
||||
ctx.replace_expression_with(expr, |old, ctx| {
|
||||
let Expression::BinaryExpression(e) = old else { unreachable!() };
|
||||
let e = e.unbox();
|
||||
if b { e.left } else { Self::minimize_not(e.span, e.left, ctx, false) }
|
||||
});
|
||||
}
|
||||
|
||||
/// Compress `foo == true` into `foo == 1`.
|
||||
@@ -224,10 +209,12 @@ impl<'a> PeepholeOptimizations {
|
||||
let reference = ctx.scoping_mut().get_reference_mut(write_id_ref.reference_id());
|
||||
reference.flags_mut().insert(ReferenceFlags::Read);
|
||||
|
||||
let new_op = logical_expr.operator.to_assignment_operator();
|
||||
let new_right = logical_expr.right.take_in(ctx);
|
||||
expr.operator = new_op;
|
||||
ctx.replace_expression(&mut expr.right, new_right);
|
||||
expr.operator = logical_expr.operator.to_assignment_operator();
|
||||
ctx.drop_expression(&logical_expr.left);
|
||||
ctx.replace_expression_with(&mut expr.right, |e, _ctx| {
|
||||
let Expression::LogicalExpression(e) = e else { unreachable!() };
|
||||
e.unbox().right
|
||||
});
|
||||
}
|
||||
|
||||
/// Compress `a = a + b` to `a += b`
|
||||
@@ -238,7 +225,7 @@ impl<'a> PeepholeOptimizations {
|
||||
if !matches!(expr.operator, AssignmentOperator::Assign) {
|
||||
return;
|
||||
}
|
||||
let Expression::BinaryExpression(binary_expr) = &mut expr.right else { return };
|
||||
let Expression::BinaryExpression(binary_expr) = &expr.right else { return };
|
||||
let Some(new_op) = binary_expr.operator.to_assignment_operator() else { return };
|
||||
if !Self::has_no_side_effect_for_evaluation_same_target(&expr.left, &binary_expr.left, ctx)
|
||||
{
|
||||
@@ -247,9 +234,12 @@ impl<'a> PeepholeOptimizations {
|
||||
|
||||
Self::mark_assignment_target_as_read(&expr.left, ctx);
|
||||
|
||||
let new_right = binary_expr.right.take_in(ctx);
|
||||
expr.operator = new_op;
|
||||
ctx.replace_expression(&mut expr.right, new_right);
|
||||
ctx.drop_expression(&binary_expr.left);
|
||||
ctx.replace_expression_with(&mut expr.right, |e, _ctx| {
|
||||
let Expression::BinaryExpression(e) = e else { unreachable!() };
|
||||
e.unbox().right
|
||||
});
|
||||
}
|
||||
|
||||
/// Compress `a -= 1` to `--a` and `a -= -1` to `++a`
|
||||
@@ -259,7 +249,7 @@ impl<'a> PeepholeOptimizations {
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
let Expression::AssignmentExpression(e) = expr else { return };
|
||||
if !matches!(e.operator, AssignmentOperator::Subtraction) {
|
||||
if e.operator != AssignmentOperator::Subtraction || !e.left.is_simple_assignment_target() {
|
||||
return;
|
||||
}
|
||||
let operator = if let Expression::NumericLiteral(num) = &e.right {
|
||||
@@ -273,9 +263,13 @@ impl<'a> PeepholeOptimizations {
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let Some(target) = e.left.as_simple_assignment_target_mut() else { return };
|
||||
let target = target.take_in(ctx);
|
||||
let new_expr = Expression::new_update_expression(e.span, operator, true, target, ctx);
|
||||
ctx.replace_expression(expr, new_expr);
|
||||
ctx.replace_expression_with(expr, |e, ctx| {
|
||||
let Expression::AssignmentExpression(e) = e else {
|
||||
unreachable!();
|
||||
};
|
||||
let e = e.unbox();
|
||||
let target = e.left.into_simple_assignment_target();
|
||||
Expression::new_update_expression(e.span, operator, true, target, ctx)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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: 56226
|
||||
arena allocs: 56215
|
||||
arena reallocs: 5084
|
||||
arena size: 16317648 # 16.32 MB
|
||||
|
||||
@@ -38,7 +38,7 @@ pdf.mjs:
|
||||
sys deallocs: 2427
|
||||
sys alloc bytes: 5313795 # 5.31 MB
|
||||
sys peak growth: 3693355 # 3.69 MB
|
||||
arena allocs: 19526
|
||||
arena allocs: 19523
|
||||
arena reallocs: 2574
|
||||
arena size: 5708848 # 5.71 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: 181721
|
||||
arena allocs: 181686
|
||||
arena reallocs: 34406
|
||||
arena size: 43045192 # 43.05 MB
|
||||
|
||||
@@ -60,7 +60,7 @@ binder.ts:
|
||||
sys deallocs: 33
|
||||
sys alloc bytes: 963008 # 963.01 kB
|
||||
sys peak growth: 657404 # 657.40 kB
|
||||
arena allocs: 2923
|
||||
arena allocs: 2922
|
||||
arena reallocs: 244
|
||||
arena size: 1074976 # 1.07 MB
|
||||
|
||||
@@ -71,6 +71,6 @@ kitchen-sink.tsx:
|
||||
sys deallocs: 1854
|
||||
sys alloc bytes: 5304252 # 5.30 MB
|
||||
sys peak growth: 3707425 # 3.71 MB
|
||||
arena allocs: 31159
|
||||
arena allocs: 31152
|
||||
arena reallocs: 3012
|
||||
arena size: 8444304 # 8.44 MB
|
||||
Reference in new issue
Block a user