mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
perf(minfiier): reduce allocs when creating indirect access (#26601)
- simplify code for `try_fold_conditional_expression` - `preserve_indirect_access` should now preserve more accurate `span` range - `try_fold_coalesce` and `try_fold_and_or` reuses now `preserve_indirect_access` helper
This commit is contained in:
@@ -143,22 +143,11 @@ impl<'a> PeepholeOptimizations {
|
||||
}
|
||||
return Some(logical_expr.left.take_in(ctx));
|
||||
} else if !left.may_have_side_effects(ctx) {
|
||||
let should_keep_indirect_access =
|
||||
Self::should_keep_indirect_access(&logical_expr.right, ctx);
|
||||
// (true && o.f) => (0, o.f)
|
||||
if should_keep_indirect_access {
|
||||
return Some(Expression::new_sequence_expression(
|
||||
logical_expr.span,
|
||||
[
|
||||
Expression::new_numeric_literal(
|
||||
logical_expr.left.span(),
|
||||
0.0,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
ctx,
|
||||
),
|
||||
logical_expr.right.take_in(ctx),
|
||||
],
|
||||
// `(true && o.f)` => `(0, o.f)`
|
||||
if Self::should_keep_indirect_access(&logical_expr.right, ctx) {
|
||||
return Some(Self::preserve_indirect_access(
|
||||
logical_expr.left.span(),
|
||||
logical_expr.right.take_in(ctx),
|
||||
ctx,
|
||||
));
|
||||
}
|
||||
@@ -214,27 +203,16 @@ impl<'a> PeepholeOptimizations {
|
||||
match left_val {
|
||||
ValueType::Null | ValueType::Undefined => {
|
||||
Some(if left.may_have_side_effects(ctx) {
|
||||
// e.g. `(a(), null) ?? 1` => `(a(), null, 1)`
|
||||
// `(a(), null) ?? 1` => `(a(), null, 1)`
|
||||
let expressions =
|
||||
[logical_expr.left.take_in(ctx), logical_expr.right.take_in(ctx)];
|
||||
Expression::new_sequence_expression(logical_expr.span, expressions, ctx)
|
||||
} else {
|
||||
let should_keep_indirect_access =
|
||||
Self::should_keep_indirect_access(&logical_expr.right, ctx);
|
||||
// (null ?? o.f) => (0, o.f)
|
||||
if should_keep_indirect_access {
|
||||
return Some(Expression::new_sequence_expression(
|
||||
logical_expr.span,
|
||||
[
|
||||
Expression::new_numeric_literal(
|
||||
logical_expr.left.span(),
|
||||
0.0,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
ctx,
|
||||
),
|
||||
logical_expr.right.take_in(ctx),
|
||||
],
|
||||
// `(null ?? o.f)` => `(0, o.f)`
|
||||
if Self::should_keep_indirect_access(&logical_expr.right, ctx) {
|
||||
return Some(Self::preserve_indirect_access(
|
||||
logical_expr.left.span(),
|
||||
logical_expr.right.take_in(ctx),
|
||||
ctx,
|
||||
));
|
||||
}
|
||||
@@ -247,22 +225,11 @@ impl<'a> PeepholeOptimizations {
|
||||
| ValueType::String
|
||||
| ValueType::Boolean
|
||||
| ValueType::Object => {
|
||||
let should_keep_indirect_access =
|
||||
Self::should_keep_indirect_access(&logical_expr.left, ctx);
|
||||
// (o.f ?? something) => (0, o.f)
|
||||
if should_keep_indirect_access {
|
||||
return Some(Expression::new_sequence_expression(
|
||||
logical_expr.span,
|
||||
[
|
||||
Expression::new_numeric_literal(
|
||||
logical_expr.right.span(),
|
||||
0.0,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
ctx,
|
||||
),
|
||||
logical_expr.left.take_in(ctx),
|
||||
],
|
||||
// `(o.f ?? something)` => `(0, o.f)`
|
||||
if Self::should_keep_indirect_access(&logical_expr.left, ctx) {
|
||||
return Some(Self::preserve_indirect_access(
|
||||
logical_expr.right.span(),
|
||||
logical_expr.left.take_in(ctx),
|
||||
ctx,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -428,44 +428,28 @@ impl<'a> PeepholeOptimizations {
|
||||
pub fn try_fold_conditional_expression(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
let Expression::ConditionalExpression(e) = expr else { return };
|
||||
let Some(v) = e.test.evaluate_value_to_boolean(ctx) else { return };
|
||||
let new_expr = if e.test.may_have_side_effects(ctx) {
|
||||
// "(a, true) ? b : c" => "a, b"
|
||||
Expression::new_sequence_expression(
|
||||
e.span,
|
||||
[
|
||||
{
|
||||
let mut test = e.test.take_in(ctx);
|
||||
Self::remove_unused_expression(&mut test, ctx);
|
||||
test
|
||||
},
|
||||
if v { e.consequent.take_in(ctx) } else { e.alternate.take_in(ctx) },
|
||||
],
|
||||
ctx,
|
||||
)
|
||||
} else {
|
||||
let result_expr = if v { e.consequent.take_in(ctx) } else { e.alternate.take_in(ctx) };
|
||||
let should_keep_as_sequence_expr = Self::should_keep_indirect_access(&result_expr, ctx);
|
||||
// "(1 ? a.b : 0)()" => "(0, a.b)()"
|
||||
if should_keep_as_sequence_expr {
|
||||
Expression::new_sequence_expression(
|
||||
e.span,
|
||||
[
|
||||
Expression::new_numeric_literal(
|
||||
e.span,
|
||||
0.0,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
ctx,
|
||||
),
|
||||
result_expr,
|
||||
],
|
||||
ctx,
|
||||
)
|
||||
|
||||
ctx.drop_expression(if v { &e.alternate } else { &e.consequent });
|
||||
ctx.replace_expression_with(expr, |e, ctx| {
|
||||
let Expression::ConditionalExpression(e) = e else {
|
||||
unreachable!();
|
||||
};
|
||||
let mut e = e.unbox();
|
||||
let result_expr = if v { e.consequent } else { e.alternate };
|
||||
|
||||
if Self::remove_unused_expression(&mut e.test, ctx) {
|
||||
ctx.drop_expression(&e.test);
|
||||
// `(1 ? a.b : 0)()` => `(0, a.b)()`
|
||||
if Self::should_keep_indirect_access(&result_expr, ctx) {
|
||||
Self::preserve_indirect_access(e.span, result_expr, ctx)
|
||||
} else {
|
||||
result_expr
|
||||
}
|
||||
} else {
|
||||
result_expr
|
||||
// `(a, true) ? b : c` => `a, b`
|
||||
Expression::new_sequence_expression(e.span, [e.test, result_expr], ctx)
|
||||
}
|
||||
};
|
||||
ctx.replace_expression(expr, new_expr);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn remove_sequence_expression(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
@@ -720,7 +704,7 @@ impl<'a> PeepholeOptimizations {
|
||||
ctx: &TraverseCtx<'a>,
|
||||
) -> Expression<'a> {
|
||||
Expression::new_sequence_expression(
|
||||
span,
|
||||
span.merge(expr.span()),
|
||||
[Expression::new_numeric_literal(span, 0.0, None, NumberBase::Decimal, ctx), expr],
|
||||
ctx,
|
||||
)
|
||||
|
||||
@@ -1542,14 +1542,7 @@ impl<'a> PeepholeOptimizations {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_callee = Expression::new_sequence_expression(
|
||||
span,
|
||||
[
|
||||
Expression::new_numeric_literal(span, 0.0, None, NumberBase::Decimal, ctx),
|
||||
arg_expr.take_in(ctx),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
let new_callee = Self::preserve_indirect_access(span, arg_expr.take_in(ctx), ctx);
|
||||
ctx.replace_expression(&mut expr.callee, new_callee);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ antd.js:
|
||||
sys deallocs: 860
|
||||
sys alloc bytes: 29976375 # 29.98 MB
|
||||
sys peak growth: 19934749 # 19.93 MB
|
||||
arena allocs: 187032
|
||||
arena allocs: 187025
|
||||
arena reallocs: 63323
|
||||
arena size: 43370040 # 43.37 MB
|
||||
|
||||
@@ -71,6 +71,6 @@ kitchen-sink.tsx:
|
||||
sys deallocs: 1854
|
||||
sys alloc bytes: 5304692 # 5.30 MB
|
||||
sys peak growth: 3707457 # 3.71 MB
|
||||
arena allocs: 31944
|
||||
arena allocs: 31927
|
||||
arena reallocs: 12185
|
||||
arena size: 8688104 # 8.69 MB
|
||||
|
||||
Reference in New Issue
Block a user