mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(minifier): move dce conditional expression to RemoveDeadCode (#5971)
This is aligned to closure compiler
This commit is contained in:
parent
860f108a75
commit
0a2f68756f
5 changed files with 60 additions and 65 deletions
|
|
@ -113,7 +113,13 @@ impl<'a> PeepholeFoldConstants {
|
|||
match expr.operator {
|
||||
UnaryOperator::Void => Self::try_reduce_void(expr, ctx),
|
||||
UnaryOperator::Typeof => self.try_fold_type_of(expr, ctx),
|
||||
#[allow(clippy::float_cmp)]
|
||||
UnaryOperator::LogicalNot => {
|
||||
if let Expression::NumericLiteral(n) = &expr.argument {
|
||||
if n.value == 0.0 || n.value == 1.0 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
expr.argument.to_boolean().map(|b| ctx.ast.expression_boolean_literal(SPAN, !b))
|
||||
}
|
||||
// `-NaN` -> `NaN`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use oxc_ast::ast::*;
|
||||
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
|
||||
use oxc_traverse::{Traverse, TraverseCtx};
|
||||
|
||||
use crate::{node_util::NodeUtil, tri::Tri, CompressorPass};
|
||||
use crate::CompressorPass;
|
||||
|
||||
/// Minimize Conditions
|
||||
///
|
||||
|
|
@ -16,44 +16,18 @@ impl<'a> CompressorPass<'a> for PeepholeMinimizeConditions {}
|
|||
|
||||
impl<'a> Traverse<'a> for PeepholeMinimizeConditions {
|
||||
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
self.fold_expression(expr, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PeepholeMinimizeConditions {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn fold_expression(&self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
if let Some(folded_expr) = match expr {
|
||||
Expression::ConditionalExpression(e) => self.try_fold_conditional_expression(e, ctx),
|
||||
Expression::UnaryExpression(e) if e.operator.is_not() => self.try_minimize_not(e, ctx),
|
||||
_ => None,
|
||||
} {
|
||||
*expr = folded_expr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_conditional_expression(
|
||||
&self,
|
||||
expr: &mut ConditionalExpression<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Option<Expression<'a>> {
|
||||
match ctx.get_boolean_value(&expr.test) {
|
||||
Tri::True => {
|
||||
// Bail `let o = { f() { assert.ok(this !== o); } }; (true ? o.f : false)(); (true ? o.f : false)``;`
|
||||
let parent = ctx.ancestry.parent();
|
||||
if parent.is_tagged_template_expression()
|
||||
|| matches!(parent, Ancestor::CallExpressionCallee(_))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(ctx.ast.move_expression(&mut expr.consequent))
|
||||
}
|
||||
Tri::False => Some(ctx.ast.move_expression(&mut expr.alternate)),
|
||||
Tri::Unknown => None,
|
||||
}
|
||||
impl<'a> PeepholeMinimizeConditions {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
/// Try to minimize NOT nodes such as `!(x==y)`.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use oxc_allocator::Vec;
|
||||
use oxc_ast::{ast::*, Visit};
|
||||
use oxc_span::SPAN;
|
||||
use oxc_traverse::{Traverse, TraverseCtx};
|
||||
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
|
||||
|
||||
use crate::{keep_var::KeepVar, node_util::NodeUtil, tri::Tri, CompressorPass};
|
||||
|
||||
|
|
@ -23,6 +23,15 @@ impl<'a> Traverse<'a> for PeepholeRemoveDeadCode {
|
|||
stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_)));
|
||||
self.dead_code_elimination(stmts, ctx);
|
||||
}
|
||||
|
||||
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
if let Some(folded_expr) = match expr {
|
||||
Expression::ConditionalExpression(e) => self.try_fold_conditional_expression(e, ctx),
|
||||
_ => None,
|
||||
} {
|
||||
*expr = folded_expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PeepholeRemoveDeadCode {
|
||||
|
|
@ -114,22 +123,26 @@ impl<'a> PeepholeRemoveDeadCode {
|
|||
Tri::Unknown => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try folding conditional expression (?:) if the condition results of the condition is known.
|
||||
fn try_fold_conditional_expression(
|
||||
&self,
|
||||
expr: &mut ConditionalExpression<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Option<Expression<'a>> {
|
||||
match ctx.get_boolean_value(&expr.test) {
|
||||
Tri::True => {
|
||||
// Bail `let o = { f() { assert.ok(this !== o); } }; (true ? o.f : false)(); (true ? o.f : false)``;`
|
||||
let parent = ctx.ancestry.parent();
|
||||
if parent.is_tagged_template_expression()
|
||||
|| matches!(parent, Ancestor::CallExpressionCallee(_))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(ctx.ast.move_expression(&mut expr.consequent))
|
||||
}
|
||||
Tri::False => Some(ctx.ast.move_expression(&mut expr.alternate)),
|
||||
Tri::Unknown => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /// <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java>
|
||||
// #[cfg(test)]
|
||||
// mod test {
|
||||
// use oxc_allocator::Allocator;
|
||||
|
||||
// use crate::{tester, CompressOptions};
|
||||
|
||||
// fn test(source_text: &str, expected: &str) {
|
||||
// let allocator = Allocator::default();
|
||||
// let mut pass = super::PeepholeRemoveDeadCode::new();
|
||||
// tester::test(&allocator, source_text, expected, &mut pass);
|
||||
// }
|
||||
|
||||
// fn test_same(source_text: &str) {
|
||||
// test(source_text, source_text);
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -42,13 +42,24 @@ impl<'a> Compressor<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.fold_constants(program, &mut ctx);
|
||||
// earlyPeepholeOptimizations
|
||||
// TODO: MinimizeExitPoints
|
||||
self.minimize_conditions(program, &mut ctx);
|
||||
self.remove_dead_code(program, &mut ctx);
|
||||
// self.statement_fusion(program, &mut ctx);
|
||||
self.substitute_alternate_syntax(program, &mut ctx);
|
||||
self.collapse_variable_declarations(program, &mut ctx);
|
||||
// TODO: PeepholeReplaceKnownMethods
|
||||
self.remove_dead_code(program, &mut ctx);
|
||||
self.fold_constants(program, &mut ctx);
|
||||
|
||||
// latePeepholeOptimizations
|
||||
// TODO: StatementFusion
|
||||
self.remove_dead_code(program, &mut ctx);
|
||||
self.minimize_conditions(program, &mut ctx);
|
||||
self.substitute_alternate_syntax(program, &mut ctx);
|
||||
// TODO: PeepholeReplaceKnownMethods
|
||||
self.fold_constants(program, &mut ctx);
|
||||
|
||||
self.exploit_assigns(program, &mut ctx);
|
||||
self.collapse_variable_declarations(program, &mut ctx);
|
||||
}
|
||||
|
||||
fn dead_code_elimination(self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,4 @@ commit: d62fa93c
|
|||
|
||||
minifier_test262 Summary:
|
||||
AST Parsed : 43765/43765 (100.00%)
|
||||
Positive Passed: 43756/43765 (99.98%)
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T2.js
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T3.js
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T4.js
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T2.js
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T3.js
|
||||
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T4.js
|
||||
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T1.js
|
||||
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T3.js
|
||||
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T4.js
|
||||
Positive Passed: 43765/43765 (100.00%)
|
||||
|
|
|
|||
Loading…
Reference in a new issue