Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(es/minifier): Use rope-like structure for the name mangler #6661

Merged
merged 12 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};

use self::scope::Scope;

mod reverse_map;
pub(super) mod scope;

#[derive(Debug, Default)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use rustc_hash::FxHashMap;

use super::scope::{FastId, FastJsWord};

#[derive(Debug, Default)]
pub(crate) struct ReverseMap<'a> {
prev: Option<&'a ReverseMap<'a>>,

inner: FxHashMap<FastJsWord, Vec<FastId>>,
}

impl ReverseMap<'_> {
pub fn push_entry(&mut self, key: FastJsWord, id: FastId) {
self.inner.entry(key).or_default().push(id);
}

fn iter(&self) -> Iter {
Iter { cur: Some(self) }
}

pub fn get<'a>(&'a self, key: &'a FastJsWord) -> impl Iterator<Item = &'a FastId> + 'a {
self.iter()
.filter_map(|v| v.inner.get(key))
.flat_map(|v| v.iter())
}

pub fn next(&self) -> ReverseMap {
ReverseMap {
prev: Some(self),
..Default::default()
}
}
}

pub(crate) struct Iter<'a> {
cur: Option<&'a ReverseMap<'a>>,
}

impl<'a> Iterator for Iter<'a> {
type Item = &'a ReverseMap<'a>;

fn next(&mut self) -> Option<Self::Item> {
let cur = self.cur.take()?;
self.cur = cur.prev;
Some(cur)
}
}
45 changes: 27 additions & 18 deletions crates/swc_ecma_transforms_base/src/rename/analyzer/scope.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#![allow(clippy::too_many_arguments)]

use std::mem::{transmute_copy, ManuallyDrop};
use std::{
fmt::{Display, Formatter},
mem::{transmute_copy, ManuallyDrop},
};

#[cfg(feature = "concurrent-renamer")]
use rayon::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_hash::FxHashSet;
use swc_atoms::{js_word, JsWord};
use swc_common::{collections::AHashMap, util::take::Take, SyntaxContext};
use swc_ecma_ast::*;
use tracing::debug;

use super::reverse_map::ReverseMap;
use crate::rename::Renamer;

#[derive(Debug, Default)]
Expand All @@ -32,6 +36,12 @@ impl Clone for FastJsWord {
}
}

impl Display for FastJsWord {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&*self.0, f)
}
}

impl FastJsWord {
pub fn new(src: JsWord) -> Self {
FastJsWord(ManuallyDrop::new(src))
Expand All @@ -46,8 +56,6 @@ pub(crate) type FastId = (FastJsWord, SyntaxContext);

pub(crate) type RenameMap = AHashMap<FastId, JsWord>;

pub(crate) type ReverseMap = FxHashMap<JsWord, Vec<FastId>>;

#[derive(Debug, Default)]
pub(super) struct ScopeData {
/// This is add-only.
Expand Down Expand Up @@ -151,35 +159,34 @@ impl Scope {
if preserved_symbols.contains(&sym) {
continue;
}
let sym = FastJsWord::new(sym);

if self.can_rename(&id, &sym, reverse) {
if cfg!(debug_assertions) {
debug!("Renaming `{}{:?}` to `{}`", id.0, id.1, sym);
}

let fid = fast_id(id);
to.insert(fid.clone(), sym.clone());
reverse.entry(sym).or_default().push(fid);
reverse.push_entry(sym.clone(), fid.clone());
to.insert(fid, sym.into_inner());

break;
}
}
}
}

fn can_rename(&self, id: &Id, symbol: &JsWord, reverse: &ReverseMap) -> bool {
fn can_rename(&self, id: &Id, symbol: &FastJsWord, reverse: &ReverseMap) -> bool {
// We can optimize this
// We only need to check the current scope and parents (ignoring `a` generated
// for unrelated scopes)
if let Some(lefts) = reverse.get(symbol) {
for left in lefts {
if left.1 == id.1 && *left.0 .0 == id.0 {
continue;
}
for left in reverse.get(symbol) {
if left.1 == id.1 && *left.0 .0 == id.0 {
continue;
}

if self.data.all.contains(left) {
return false;
}
if self.data.all.contains(left) {
return false;
}
}

Expand All @@ -201,7 +208,7 @@ impl Scope {
{
let queue = self.data.queue.take();

let mut cloned_reverse = reverse.clone();
let mut cloned_reverse = reverse.next();

self.rename_one_scope_in_mangle_mode(
renamer,
Expand Down Expand Up @@ -289,15 +296,17 @@ impl Scope {
continue;
}

let sym = FastJsWord::new(sym);

if self.can_rename(&id, &sym, reverse) {
#[cfg(debug_assertions)]
{
debug!("mangle: `{}{:?}` -> {}", id.0, id.1, sym);
}

let fid = fast_id(id.clone());
to.insert(fid.clone(), sym.clone());
reverse.entry(sym).or_default().push(fid.clone());
reverse.push_entry(sym.clone(), fid.clone());
to.insert(fid.clone(), sym.into_inner());
// self.data.decls.remove(&id);
// self.data.usages.remove(&id);

Expand Down