mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
perf(minifier): try merging before creating new expression statements (#26556)
Add `push_new_expression_stmt_to_result` to attempt merging expressions into existing sequence statements before pushing new ones. ```js // antd.js // 1: var r = n(`react`), i = n(`./node_modules/@ant-design/icons-svg/es/asn/PieChartFilled.js`); // 2: this iteration is removed n(`react`); n(`./node_modules/@ant-design/icons-svg/es/asn/AccountBookFilled.js`); // 3: n(`react`), n(`./node_modules/@ant-design/icons-svg/es/asn/AccountBookFilled.js`); ```
This commit is contained in:
@@ -169,6 +169,26 @@ impl<'a> PeepholeOptimizations {
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge `expr` expression with the previous expression statement or emit as a new one.
|
||||
fn push_new_expression_stmt_to_result(
|
||||
expr: Expression<'a>,
|
||||
result: &mut ArenaVec<'a, Statement<'a>>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
if ctx.options().sequences
|
||||
&& let Some(Statement::ExpressionStatement(prev_expr_stmt)) = result.last_mut()
|
||||
{
|
||||
ctx.replace_expression_with(&mut prev_expr_stmt.expression, |a, ctx| {
|
||||
Self::join_sequence(a, expr, ctx)
|
||||
});
|
||||
} else {
|
||||
result.push(Statement::new_expression_statement(expr.span(), expr, ctx));
|
||||
ctx.notice_change();
|
||||
}
|
||||
}
|
||||
|
||||
/// Fold `target` expression into previous expression as sequence
|
||||
/// `a; b` -> `a, b`.
|
||||
fn merge_last_expression_into_sequence(
|
||||
target: &mut Expression<'a>,
|
||||
result: &mut ArenaVec<'a, Statement<'a>>,
|
||||
@@ -262,7 +282,7 @@ impl<'a> PeepholeOptimizations {
|
||||
if Self::remove_unused_expression(&mut init, ctx) {
|
||||
ctx.drop_expression(&init);
|
||||
} else {
|
||||
result.push(Statement::new_expression_statement(init.span(), init, ctx));
|
||||
Self::push_new_expression_stmt_to_result(init, result, ctx);
|
||||
}
|
||||
}
|
||||
// Walk the rest of the dropped declarator (binding pattern +
|
||||
@@ -516,11 +536,7 @@ impl<'a> PeepholeOptimizations {
|
||||
}
|
||||
|
||||
if !discriminant.is_literal() {
|
||||
result.push(Statement::new_expression_statement(
|
||||
discriminant.span(),
|
||||
discriminant,
|
||||
ctx,
|
||||
));
|
||||
Self::push_new_expression_stmt_to_result(discriminant, result, ctx);
|
||||
}
|
||||
|
||||
result.push(block_stmt);
|
||||
@@ -660,19 +676,9 @@ impl<'a> PeepholeOptimizations {
|
||||
{
|
||||
let argument = ret_stmt.argument.take().unwrap();
|
||||
if argument.may_have_side_effects(ctx) {
|
||||
if ctx.options().sequences
|
||||
&& let Some(Statement::ExpressionStatement(prev_expr_stmt)) = result.last_mut()
|
||||
{
|
||||
// `x; return a,void 0;` -> `x,a,void 0; return;`
|
||||
ctx.replace_expression_with(&mut prev_expr_stmt.expression, |a, ctx| {
|
||||
Self::join_sequence(a, argument, ctx)
|
||||
});
|
||||
} else {
|
||||
// `return a,void 0;` -> `a,void 0; return;`
|
||||
let span = argument.span();
|
||||
result.push(Statement::new_expression_statement(span, argument, ctx));
|
||||
ctx.notice_change();
|
||||
}
|
||||
// `x; return a,void 0;` -> `x,a,void 0; return;`
|
||||
// `return a,void 0;` -> `a,void 0; return;`
|
||||
Self::push_new_expression_stmt_to_result(argument, result, ctx);
|
||||
} else {
|
||||
// `return void 0;` -> `return;`
|
||||
ctx.drop_expression(&argument);
|
||||
@@ -698,14 +704,9 @@ impl<'a> PeepholeOptimizations {
|
||||
ctx.notice_change();
|
||||
let prev_stmt = result.pop().unwrap();
|
||||
let Statement::IfStatement(prev_if) = prev_stmt else { unreachable!() };
|
||||
let prev_if = prev_if.unbox();
|
||||
let test_expr = prev_if.unbox().test;
|
||||
|
||||
let test_expr = prev_if.test;
|
||||
result.push(Statement::new_expression_statement(
|
||||
test_expr.span(),
|
||||
test_expr,
|
||||
ctx,
|
||||
));
|
||||
Self::push_new_expression_stmt_to_result(test_expr, result, ctx);
|
||||
break 'return_loop;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Iterations | Fi
|
||||
|
||||
3.20 MB | 958.89 kB | 1.01 MB | 317.07 kB | 331.56 kB | 2 | echarts.js
|
||||
|
||||
6.69 MB | 2.12 MB | 2.31 MB | 453.42 kB | 488.28 kB | 5 | antd.js
|
||||
6.69 MB | 2.12 MB | 2.31 MB | 453.42 kB | 488.28 kB | 4 | antd.js
|
||||
|
||||
10.95 MB | 3.31 MB | 3.49 MB | 849.97 kB | 915.50 kB | 4 | typescript.js
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ checker.ts:
|
||||
sys deallocs: 122
|
||||
sys alloc bytes: 14996632 # 15.00 MB
|
||||
sys peak growth: 10169560 # 10.17 MB
|
||||
arena allocs: 59908
|
||||
arena reallocs: 21415
|
||||
arena allocs: 59899
|
||||
arena reallocs: 21411
|
||||
arena size: 16569784 # 16.57 MB
|
||||
|
||||
App.tsx:
|
||||
@@ -38,20 +38,20 @@ pdf.mjs:
|
||||
sys deallocs: 2427
|
||||
sys alloc bytes: 5316219 # 5.32 MB
|
||||
sys peak growth: 3693363 # 3.69 MB
|
||||
arena allocs: 20927
|
||||
arena reallocs: 7697
|
||||
arena allocs: 20924
|
||||
arena reallocs: 7696
|
||||
arena size: 5782208 # 5.78 MB
|
||||
|
||||
antd.js:
|
||||
file size: 6686316 # 6.69 MB
|
||||
sys allocs: 1038
|
||||
sys allocs: 860
|
||||
sys reallocs: 56
|
||||
sys deallocs: 1038
|
||||
sys deallocs: 860
|
||||
sys alloc bytes: 29976375 # 29.98 MB
|
||||
sys peak growth: 19934749 # 19.93 MB
|
||||
arena allocs: 207313
|
||||
arena reallocs: 75941
|
||||
arena size: 45450136 # 45.45 MB
|
||||
arena allocs: 187331
|
||||
arena reallocs: 63323
|
||||
arena size: 43374888 # 43.37 MB
|
||||
|
||||
binder.ts:
|
||||
file size: 193077 # 193.08 kB
|
||||
@@ -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: 31993
|
||||
arena reallocs: 12186
|
||||
arena size: 8689832 # 8.69 MB
|
||||
arena allocs: 31944
|
||||
arena reallocs: 12185
|
||||
arena size: 8688104 # 8.69 MB
|
||||
|
||||
Reference in New Issue
Block a user