Skip to content

Commit

Permalink
feat(minifier): only constant fold numbers when result is smaller
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 24, 2024
1 parent fccfda9 commit fe748b4
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
48 changes: 41 additions & 7 deletions crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ impl<'a> Traverse<'a> for PeepholeFoldConstants {
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
let ctx = Ctx(ctx);
if let Some(folded_expr) = match expr {
Expression::Identifier(ident) => (ident.name == "Infinity")
.then(|| {
ctx.eval_to_number(expr)
.map(|v| ctx.value_to_expr(expr.span(), ConstantValue::Number(v)))
})
.flatten(),
Expression::CallExpression(e) => {
Self::try_fold_useless_object_dot_define_properties_call(e, ctx)
}
Expand Down Expand Up @@ -246,9 +252,22 @@ impl<'a, 'b> PeepholeFoldConstants {
| BinaryOperator::Division
| BinaryOperator::Remainder
| BinaryOperator::Multiplication
| BinaryOperator::Exponential => {
ctx.eval_binary_expression(e).map(|v| ctx.value_to_expr(e.span, v))
| BinaryOperator::Exponential => match (&e.left, &e.right) {
(Expression::NumericLiteral(left), Expression::NumericLiteral(right)) => {
let value = ctx.eval_binary_expression(e)?;
let ConstantValue::Number(num) = value else { return None };
(num.is_nan()
|| num.is_infinite()
|| (num.abs() <= f64::powf(2.0, 53.0)
&& Self::approximate_printed_int_char_count(num)
<= Self::approximate_printed_int_char_count(left.value)
+ Self::approximate_printed_int_char_count(right.value)
+ e.operator.as_str().len()))
.then(|| value)
}
_ => ctx.eval_binary_expression(e),
}
.map(|v| ctx.value_to_expr(e.span, v)),
BinaryOperator::BitwiseAnd | BinaryOperator::BitwiseOR | BinaryOperator::BitwiseXOR => {
if let Some(v) = ctx.eval_binary_expression(e) {
return Some(ctx.value_to_expr(e.span, v));
Expand All @@ -260,6 +279,21 @@ impl<'a, 'b> PeepholeFoldConstants {
}
}

// https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_ast_helpers.go#L1128
fn approximate_printed_int_char_count(value: f64) -> usize {
let mut count = if value.is_infinite() {
"Infinity".len()
} else if value.is_nan() {
"NaN".len()
} else {
1 + 0.max(value.abs().log10().floor() as usize)
};
if value.is_sign_negative() {
count += 1;
}
count
}

fn try_fold_left_child_op(
e: &mut BinaryExpression<'a>,
ctx: Ctx<'a, '_>,
Expand Down Expand Up @@ -1310,8 +1344,8 @@ mod test {
#[test]
fn test_fold_bitwise_op_additional() {
test("x = null & 1", "x = 0");
test("x = (2 ** 31 - 1) | 1", "x = 2147483647");
test("x = (2 ** 31) | 1", "x = -2147483647");
test_same("x = (2 ** 31 - 1) | 1");
test_same("x = (2 ** 31) | 1");

// https://github.com/oxc-project/oxc/issues/7944
test_same("(x - 1) & 1");
Expand Down Expand Up @@ -1344,9 +1378,9 @@ mod test {
test("x = 10 >>> 1", "x=5");
test("x = 10 >>> 2", "x=2");
test("x = 10 >>> 5", "x=0");
test("x = -1 >>> 1", "x=2147483647"); // 0x7fffffff
test("x = -1 >>> 0", "x=4294967295"); // 0xffffffff
test("x = -2 >>> 0", "x=4294967294"); // 0xfffffffe
test_same("x = -1 >>> 1");
test_same("x = -1 >>> 0");
test_same("x = -2 >>> 0");
test("x = 0x90000000 >>> 28", "x=9");

test("x = 0xffffffff << 0", "x=-1");
Expand Down
10 changes: 5 additions & 5 deletions tasks/minsize/minsize.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ Original | minified | minified | gzip | gzip | Fixture

342.15 kB | 121.55 kB | 118.14 kB | 44.64 kB | 44.37 kB | vue.js

544.10 kB | 73.32 kB | 72.48 kB | 26.13 kB | 26.20 kB | lodash.js
544.10 kB | 73.31 kB | 72.48 kB | 26.12 kB | 26.20 kB | lodash.js

555.77 kB | 276.06 kB | 270.13 kB | 91.14 kB | 90.80 kB | d3.js
555.77 kB | 275.92 kB | 270.13 kB | 91.13 kB | 90.80 kB | d3.js

1.01 MB | 466.83 kB | 458.89 kB | 126.74 kB | 126.71 kB | bundle.min.js

1.25 MB | 661.47 kB | 646.76 kB | 163.94 kB | 163.73 kB | three.js
1.25 MB | 661.43 kB | 646.76 kB | 163.92 kB | 163.73 kB | three.js

2.14 MB | 740.44 kB | 724.14 kB | 181.35 kB | 181.07 kB | victory.js
2.14 MB | 740.33 kB | 724.14 kB | 181.33 kB | 181.07 kB | victory.js

3.20 MB | 1.02 MB | 1.01 MB | 332.00 kB | 331.56 kB | echarts.js
3.20 MB | 1.02 MB | 1.01 MB | 331.93 kB | 331.56 kB | echarts.js

6.69 MB | 2.39 MB | 2.31 MB | 495.62 kB | 488.28 kB | antd.js

Expand Down

0 comments on commit fe748b4

Please sign in to comment.