mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
perf(minifier): use IdentHashSet in PrivateMemberUsageStack (#26331)
Use `IdentHashSet` in `PrivateMemberUsageStack`. This reduces the `Ident` -> `Str` conversion and also makes the `Set::contains` operation faster as the hashing doesn't happen. I used AI to generate the code and then reviewed the code.
This commit is contained in:
3 files changed
+17
-21
No files matched your search
@@ -792,7 +792,7 @@ impl<'a> Traverse<'a> for PeepholeOptimizations {
|
||||
if ctx.is_tree_shake_only() {
|
||||
return;
|
||||
}
|
||||
ctx.state.private_member_usage.record_use(node.field.name.into());
|
||||
ctx.state.private_member_usage.record_use(node.field.name);
|
||||
}
|
||||
|
||||
fn exit_private_in_expression(
|
||||
@@ -803,6 +803,6 @@ impl<'a> Traverse<'a> for PeepholeOptimizations {
|
||||
if ctx.is_tree_shake_only() {
|
||||
return;
|
||||
}
|
||||
ctx.state.private_member_usage.record_use(node.left.name.into());
|
||||
ctx.state.private_member_usage.record_use(node.left.name);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_ecmascript::side_effects::MayHaveSideEffects;
|
||||
use oxc_str::Ident;
|
||||
|
||||
use crate::TraverseCtx;
|
||||
|
||||
@@ -21,8 +22,7 @@ impl<'a> PeepholeOptimizations {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &prop.key else {
|
||||
return true;
|
||||
};
|
||||
let name: Str = private_id.name.into();
|
||||
if ctx.state.private_member_usage.is_used(&name) {
|
||||
if ctx.state.private_member_usage.is_used(&private_id.name) {
|
||||
return true;
|
||||
}
|
||||
prop.value.as_ref().is_some_and(|value| value.may_have_side_effects(ctx))
|
||||
@@ -31,15 +31,13 @@ impl<'a> PeepholeOptimizations {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &method.key else {
|
||||
return true;
|
||||
};
|
||||
let name: Str = private_id.name.into();
|
||||
ctx.state.private_member_usage.is_used(&name)
|
||||
ctx.state.private_member_usage.is_used(&private_id.name)
|
||||
}
|
||||
ClassElement::AccessorProperty(accessor) => {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &accessor.key else {
|
||||
return true;
|
||||
};
|
||||
let name: Str = private_id.name.into();
|
||||
if ctx.state.private_member_usage.is_used(&name) {
|
||||
if ctx.state.private_member_usage.is_used(&private_id.name) {
|
||||
return true;
|
||||
}
|
||||
accessor.value.as_ref().is_some_and(|value| value.may_have_side_effects(ctx))
|
||||
@@ -62,25 +60,25 @@ impl<'a> PeepholeOptimizations {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn declared_private_member_names(body: &ClassBody<'a>) -> impl Iterator<Item = Str<'a>> {
|
||||
pub fn declared_private_member_names(body: &ClassBody<'a>) -> impl Iterator<Item = Ident<'a>> {
|
||||
body.body.iter().filter_map(|element| match element {
|
||||
ClassElement::PropertyDefinition(prop) => {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &prop.key else {
|
||||
return None;
|
||||
};
|
||||
Some(private_id.name.into())
|
||||
Some(private_id.name)
|
||||
}
|
||||
ClassElement::MethodDefinition(method) => {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &method.key else {
|
||||
return None;
|
||||
};
|
||||
Some(private_id.name.into())
|
||||
Some(private_id.name)
|
||||
}
|
||||
ClassElement::AccessorProperty(accessor) => {
|
||||
let PropertyKey::PrivateIdentifier(private_id) = &accessor.key else {
|
||||
return None;
|
||||
};
|
||||
Some(private_id.name.into())
|
||||
Some(private_id.name)
|
||||
}
|
||||
ClassElement::StaticBlock(_) => None,
|
||||
ClassElement::TSIndexSignature(_) => {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use oxc_allocator::{Allocator, BitSet};
|
||||
use oxc_data_structures::stack::NonEmptyStack;
|
||||
use oxc_semantic::Scoping;
|
||||
use oxc_span::SourceType;
|
||||
use oxc_str::Str;
|
||||
use oxc_str::{Ident, IdentHashSet};
|
||||
use oxc_syntax::scope::ScopeId;
|
||||
|
||||
use crate::{CompressOptions, symbol_state::SymbolState};
|
||||
@@ -195,12 +193,12 @@ impl<'a> MinifierState<'a> {
|
||||
|
||||
/// Private member names used in each currently enclosing class.
|
||||
pub struct PrivateMemberUsageStack<'a> {
|
||||
stack: NonEmptyStack<FxHashSet<Str<'a>>>,
|
||||
stack: NonEmptyStack<IdentHashSet<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> PrivateMemberUsageStack<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self { stack: NonEmptyStack::new(FxHashSet::default()) }
|
||||
Self { stack: NonEmptyStack::new(IdentHashSet::default()) }
|
||||
}
|
||||
|
||||
/// Whether all class scopes have been exited.
|
||||
@@ -209,11 +207,11 @@ impl<'a> PrivateMemberUsageStack<'a> {
|
||||
}
|
||||
|
||||
pub fn enter_class(&mut self) {
|
||||
self.stack.push(FxHashSet::default());
|
||||
self.stack.push(IdentHashSet::default());
|
||||
}
|
||||
|
||||
/// Exit a class and propagate uses of names declared by an outer class.
|
||||
pub fn exit_class(&mut self, declared_private_members: impl Iterator<Item = Str<'a>>) {
|
||||
pub fn exit_class(&mut self, declared_private_members: impl Iterator<Item = Ident<'a>>) {
|
||||
let mut used_private_members = self.stack.pop();
|
||||
declared_private_members.for_each(|name| {
|
||||
used_private_members.remove(&name);
|
||||
@@ -221,11 +219,11 @@ impl<'a> PrivateMemberUsageStack<'a> {
|
||||
self.stack.last_mut().extend(used_private_members);
|
||||
}
|
||||
|
||||
pub fn record_use(&mut self, name: Str<'a>) {
|
||||
pub fn record_use(&mut self, name: Ident<'a>) {
|
||||
self.stack.last_mut().insert(name);
|
||||
}
|
||||
|
||||
pub fn is_used(&self, name: &Str<'a>) -> bool {
|
||||
pub fn is_used(&self, name: &Ident<'a>) -> bool {
|
||||
self.stack.last().contains(name)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user