Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/oxc_minifier/src/compressor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<'a> Compressor<'a> {
options: CompressOptions,
) -> u8 {
let max_iterations = options.max_iterations;
let state = MinifierState::new(program.source_type, options);
let state = MinifierState::new(self.allocator, program.source_type, options);
let mut ctx = ReusableTraverseCtx::new(state, scoping, self.allocator);
let normalize_options =
NormalizeOptions { convert_while_to_fors: true, convert_const_to_let: true };
Expand All @@ -52,7 +52,7 @@ impl<'a> Compressor<'a> {
options: CompressOptions,
) -> u8 {
let max_iterations = options.max_iterations;
let state = MinifierState::new(program.source_type, options);
let state = MinifierState::new(self.allocator, program.source_type, options);
let mut ctx = ReusableTraverseCtx::new(state, scoping, self.allocator);
let normalize_options =
NormalizeOptions { convert_while_to_fors: false, convert_const_to_let: false };
Expand Down
45 changes: 29 additions & 16 deletions crates/oxc_minifier/src/peephole/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ mod remove_unused_private_members;
mod replace_known_methods;
mod substitute_alternate_syntax;

use oxc_allocator::HashSet;
use oxc_ast_visit::Visit;
use oxc_semantic::ReferenceId;
use rustc_hash::FxHashSet;

use oxc_allocator::Vec;
use oxc_ast::ast::*;
Expand Down Expand Up @@ -116,12 +116,16 @@ impl<'a> Traverse<'a, MinifierState<'a>> for PeepholeOptimizations {
self.changed = ctx.state.changed;
if self.changed {
// Remove unused references by visiting the AST again and diff the collected references.
let refs_before =
ctx.scoping().resolved_references().flatten().copied().collect::<FxHashSet<_>>();
let mut counter = ReferencesCounter::default();
let refs_before = HashSet::from_iter_in(
ctx.scoping().resolved_references().flatten().copied(),
ctx.ast.allocator,
);
let mut counter = ReferencesCounter::new_in(ctx.ast.allocator);
counter.visit_program(program);
for reference_id_to_remove in refs_before.difference(&counter.refs) {
ctx.scoping_mut().delete_reference(*reference_id_to_remove);
for reference_id in &refs_before {
if !counter.refs.contains(reference_id) {
ctx.scoping_mut().delete_reference(*reference_id);
}
}
}
debug_assert!(ctx.state.class_symbols_stack.is_exhausted());
Expand Down Expand Up @@ -365,7 +369,7 @@ impl<'a> Traverse<'a, MinifierState<'a>> for PeepholeOptimizations {
}

fn enter_class_body(&mut self, _body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
ctx.state.class_symbols_stack.push_class_scope();
ctx.state.class_symbols_stack.push_class_scope(ctx.ast.allocator);
}

fn exit_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
Expand Down Expand Up @@ -451,12 +455,16 @@ impl<'a> Traverse<'a, MinifierState<'a>> for DeadCodeElimination {
self.changed = ctx.state.changed;
if self.changed {
// Remove unused references by visiting the AST again and diff the collected references.
let refs_before =
ctx.scoping().resolved_references().flatten().copied().collect::<FxHashSet<_>>();
let mut counter = ReferencesCounter::default();
let refs_before = HashSet::from_iter_in(
ctx.scoping().resolved_references().flatten().copied(),
ctx.ast.allocator,
);
let mut counter = ReferencesCounter::new_in(ctx.ast.allocator);
counter.visit_program(program);
for reference_id_to_remove in refs_before.difference(&counter.refs) {
ctx.scoping_mut().delete_reference(*reference_id_to_remove);
for reference_id in &refs_before {
if !counter.refs.contains(reference_id) {
ctx.scoping_mut().delete_reference(*reference_id);
}
}
}
}
Expand Down Expand Up @@ -534,12 +542,17 @@ impl<'a> Traverse<'a, MinifierState<'a>> for DeadCodeElimination {
}
}

#[derive(Default)]
struct ReferencesCounter {
refs: FxHashSet<ReferenceId>,
struct ReferencesCounter<'a> {
refs: HashSet<'a, ReferenceId>,
}

impl<'a> ReferencesCounter<'a> {
fn new_in(allocator: &'a oxc_allocator::Allocator) -> Self {
Self { refs: HashSet::new_in(allocator) }
}
}

impl<'a> Visit<'a> for ReferencesCounter {
impl<'a> Visit<'a> for ReferencesCounter<'a> {
fn visit_identifier_reference(&mut self, it: &IdentifierReference<'a>) {
let reference_id = it.reference_id();
self.refs.insert(reference_id);
Expand Down
23 changes: 14 additions & 9 deletions crates/oxc_minifier/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use oxc_allocator::HashSet;
use oxc_ecmascript::constant_evaluation::ConstantValue;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_hash::FxHashMap;

use oxc_data_structures::stack::NonEmptyStack;
use oxc_span::{Atom, SourceType};
Expand All @@ -23,27 +24,31 @@ pub struct MinifierState<'a> {
pub changed: bool,
}

impl MinifierState<'_> {
pub fn new(source_type: SourceType, options: CompressOptions) -> Self {
impl<'a> MinifierState<'a> {
pub fn new(
allocator: &'a oxc_allocator::Allocator,
source_type: SourceType,
options: CompressOptions,
) -> Self {
Self {
source_type,
options,
pure_functions: FxHashMap::default(),
symbol_values: SymbolValues::default(),
class_symbols_stack: ClassSymbolsStack::new(),
class_symbols_stack: ClassSymbolsStack::new_in(allocator),
changed: false,
}
}
}

/// Stack to track class symbol information
pub struct ClassSymbolsStack<'a> {
stack: NonEmptyStack<FxHashSet<Atom<'a>>>,
stack: NonEmptyStack<HashSet<'a, Atom<'a>>>,
}

impl<'a> ClassSymbolsStack<'a> {
pub fn new() -> Self {
Self { stack: NonEmptyStack::new(FxHashSet::default()) }
pub fn new_in(allocator: &'a oxc_allocator::Allocator) -> Self {
Self { stack: NonEmptyStack::new(HashSet::new_in(allocator)) }
}

/// Check if the stack is exhausted
Expand All @@ -52,8 +57,8 @@ impl<'a> ClassSymbolsStack<'a> {
}

/// Enter a new class scope
pub fn push_class_scope(&mut self) {
self.stack.push(FxHashSet::default());
pub fn push_class_scope(&mut self, allocator: &'a oxc_allocator::Allocator) {
self.stack.push(HashSet::new_in(allocator));
}

/// Exit the current class scope
Expand Down
12 changes: 6 additions & 6 deletions tasks/track_memory_allocations/allocs_minifier.snap
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
File | File size || Sys allocs | Sys reallocs || Arena allocs | Arena reallocs | Arena bytes
-------------------------------------------------------------------------------------------------------------------------------------------
checker.ts | 2.92 MB || 83500 | 14179 || 152592 | 28237
checker.ts | 2.92 MB || 83404 | 14179 || 152592 | 28237

cal.com.tsx | 1.06 MB || 40449 | 3033 || 37146 | 4583
cal.com.tsx | 1.06 MB || 40393 | 3033 || 37146 | 4583

RadixUIAdoptionSection.jsx | 2.52 kB || 85 | 9 || 30 | 6
RadixUIAdoptionSection.jsx | 2.52 kB || 75 | 9 || 30 | 6

pdf.mjs | 567.30 kB || 19808 | 2899 || 47442 | 7725
pdf.mjs | 567.30 kB || 19510 | 2899 || 47442 | 7725

antd.js | 6.69 MB || 99524 | 13523 || 331573 | 69338
antd.js | 6.69 MB || 99396 | 13523 || 331573 | 69338

binder.ts | 193.08 kB || 4760 | 974 || 7075 | 824
binder.ts | 193.08 kB || 4736 | 974 || 7075 | 824

Loading