perf(es/compat): Migrate regenerator to VisitMut partially (#3007)

This commit is contained in:
OJ Kwon 2021-12-10 21:30:56 -08:00 committed by GitHub
parent 9a00c9a13f
commit 91d6343d7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 143 deletions

View File

@ -3,14 +3,16 @@ use smallvec::SmallVec;
use std::mem::take;
use swc_atoms::JsWord;
use swc_common::{
util::{map::Map, move_map::MoveMap},
util::{map::Map, move_map::MoveMap, take::Take},
BytePos, Span, Spanned, SyntaxContext, DUMMY_SP,
};
use swc_ecma_ast::*;
use swc_ecma_utils::{
ident::IdentLike, member_expr, quote_ident, quote_str, undefined, ExprFactory,
};
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Visit, VisitWith};
use swc_ecma_visit::{
noop_visit_mut_type, noop_visit_type, Visit, VisitMut, VisitMutWith, VisitWith,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) struct Loc {
@ -849,14 +851,15 @@ impl CaseHandler<'_> {
// case, we can skip the rest of the statements until the next case.
let mut already_ended = false;
let stmts = {
let stmts = take(&mut self.listing);
let mut stmts = {
let mut stmts = take(&mut self.listing);
let mut v = InvalidToLit { map: &self.marked };
stmts.fold_with(&mut v)
stmts.visit_mut_with(&mut v);
stmts
};
for (i, stmt) in stmts.into_iter().enumerate() {
for (i, stmt) in stmts.iter_mut().enumerate() {
let case = SwitchCase {
span: DUMMY_SP,
test: Some(Box::new(Expr::Lit(Lit::Num(Number {
@ -879,11 +882,10 @@ impl CaseHandler<'_> {
}
_ => false,
};
cases
.last_mut()
.unwrap()
.cons
.push(stmt.fold_with(&mut UnmarkedInvalidHandler { case_id: i }));
stmt.visit_mut_with(&mut UnmarkedInvalidHandler { case_id: i });
cases.last_mut().unwrap().cons.push(stmt.take());
if is_completion {
already_ended = true;
@ -1273,13 +1275,16 @@ impl CaseHandler<'_> {
// getSafeParam: () => t.cloneDeep(safeParam),
// catchParamName: handler.param.name
//});
handler = handler.map(|handler| {
let body = handler.body.fold_with(&mut CatchParamHandler {
handler = handler.map(|mut handler| {
handler.body.visit_mut_with(&mut CatchParamHandler {
safe_param: &safe_param,
param: handler.param.as_ref(),
});
CatchClause { body, ..handler }
CatchClause {
body: handler.body,
..handler
}
});
try_entry.catch_entry = match folder.with_entry(
@ -1583,19 +1588,17 @@ struct UnmarkedInvalidHandler {
case_id: usize,
}
/// TODO: VisitMut
impl Fold for UnmarkedInvalidHandler {
noop_fold_type!();
impl VisitMut for UnmarkedInvalidHandler {
noop_visit_mut_type!();
fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self);
fn visit_mut_expr(&mut self, e: &mut Expr) {
e.visit_mut_children_with(self);
match e {
Expr::Invalid(Invalid { span }) => Expr::Lit(Lit::Num(Number {
span,
if let Expr::Invalid(Invalid { span }) = e {
*e = Expr::Lit(Lit::Num(Number {
span: *span,
value: self.case_id as _,
})),
_ => e,
}));
}
}
}
@ -1606,30 +1609,24 @@ struct InvalidToLit<'a> {
map: &'a [Loc],
}
/// TODO: VisitMut
impl Fold for InvalidToLit<'_> {
noop_fold_type!();
impl VisitMut for InvalidToLit<'_> {
noop_visit_mut_type!();
fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self);
fn visit_mut_expr(&mut self, e: &mut Expr) {
e.visit_mut_children_with(self);
match e {
Expr::Invalid(Invalid { span }) => {
//
if span.lo == span.hi {
if let Some(Loc { stmt_index, .. }) =
self.map.iter().find(|loc| loc.id == span.lo.0)
{
return Expr::Lit(Lit::Num(Number {
span: DUMMY_SP,
value: (*stmt_index) as _,
}));
}
if let Expr::Invalid(Invalid { span }) = e {
if span.lo == span.hi {
if let Some(Loc { stmt_index, .. }) =
self.map.iter().find(|loc| loc.id == span.lo.0)
{
*e = Expr::Lit(Lit::Num(Number {
span: DUMMY_SP,
value: (*stmt_index) as _,
}));
return;
}
Expr::Invalid(Invalid { span })
}
_ => e,
}
}
}
@ -1639,24 +1636,19 @@ struct CatchParamHandler<'a> {
param: Option<&'a Pat>,
}
/// TODO: VisitMut
impl Fold for CatchParamHandler<'_> {
noop_fold_type!();
impl VisitMut for CatchParamHandler<'_> {
noop_visit_mut_type!();
fn fold_expr(&mut self, node: Expr) -> Expr {
match self.param {
None => return node,
Some(Pat::Ident(i)) => match &node {
Expr::Ident(r) => {
if r.sym == i.id.sym && i.id.span.ctxt() == r.span.ctxt() {
return self.safe_param.clone();
}
fn visit_mut_expr(&mut self, node: &mut Expr) {
if let Some(Pat::Ident(i)) = self.param {
if let Expr::Ident(r) = node {
if r.sym == i.id.sym && i.id.span.ctxt() == r.span.ctxt() {
*node = self.safe_param.clone();
return;
}
_ => {}
},
_ => {}
}
}
node.fold_children_with(self)
node.visit_mut_children_with(self);
}
}

View File

@ -1,23 +1,23 @@
use smallvec::SmallVec;
use swc_atoms::js_word;
use swc_common::DUMMY_SP;
use swc_common::{util::take::Take, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{find_ids, private_ident};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
pub(super) type Vars = SmallVec<[Ident; 12]>;
pub(super) fn hoist<T>(node: T) -> (T, Hoister)
pub(super) fn hoist<T>(mut node: T) -> (T, Hoister)
where
T: FoldWith<Hoister>,
T: VisitMutWith<Hoister>,
{
let mut v = Hoister {
vars: Default::default(),
arguments: None,
};
let t = node.fold_with(&mut v);
node.visit_mut_with(&mut v);
(t, v)
(node, v)
}
#[derive(Debug)]
@ -27,8 +27,8 @@ pub(super) struct Hoister {
}
impl Hoister {
fn var_decl_to_expr(&mut self, var: VarDecl) -> Expr {
let var = var.fold_children_with(self);
fn var_decl_to_expr(&mut self, mut var: VarDecl) -> Expr {
var.visit_mut_children_with(self);
let ids = find_ids(&var);
self.vars.extend(ids);
@ -56,122 +56,103 @@ impl Hoister {
}
}
/// TODO: VisitMut
impl Fold for Hoister {
noop_fold_type!();
impl VisitMut for Hoister {
noop_visit_mut_type!();
/// Noop
fn fold_function(&mut self, n: Function) -> Function {
n
fn visit_mut_function(&mut self, _n: &mut Function) {
//noop
}
fn fold_expr(&mut self, e: Expr) -> Expr {
let e = e.fold_children_with(self);
fn visit_mut_expr(&mut self, e: &mut Expr) {
e.visit_mut_children_with(self);
match e {
Expr::Ident(Ident {
sym: js_word!("arguments"),
..
}) => {
if self.arguments.is_none() {
self.arguments = Some(private_ident!("_args"));
}
return Expr::Ident(self.arguments.clone().unwrap());
if let Expr::Ident(Ident {
sym: js_word!("arguments"),
..
}) = e
{
if self.arguments.is_none() {
self.arguments = Some(private_ident!("_args"));
}
_ => {}
*e = Expr::Ident(self.arguments.clone().unwrap());
}
e
}
fn fold_member_expr(&mut self, mut e: MemberExpr) -> MemberExpr {
e.obj = e.obj.fold_with(self);
fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
e.obj.visit_mut_with(self);
if e.computed {
e.prop = e.prop.fold_with(self);
e.prop.visit_mut_with(self);
}
e
}
fn fold_module_decl(&mut self, decl: ModuleDecl) -> ModuleDecl {
match decl {
ModuleDecl::ExportDecl(ExportDecl {
span,
decl: Decl::Var(var),
}) => {
return ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
span,
expr: Box::new(self.var_decl_to_expr(var)),
})
}
_ => {}
fn visit_mut_module_decl(&mut self, decl: &mut ModuleDecl) {
if let ModuleDecl::ExportDecl(ExportDecl {
span,
decl: Decl::Var(var),
}) = decl
{
*decl = ModuleDecl::ExportDefaultExpr(ExportDefaultExpr {
span: *span,
expr: Box::new(self.var_decl_to_expr(var.take())),
});
return;
}
decl.fold_children_with(self)
decl.visit_mut_children_with(self);
}
fn fold_stmt(&mut self, s: Stmt) -> Stmt {
match s {
Stmt::Decl(Decl::Var(var)) => {
let span = var.span;
let expr = Box::new(self.var_decl_to_expr(var));
fn visit_mut_stmt(&mut self, s: &mut Stmt) {
if let Stmt::Decl(Decl::Var(var)) = s {
let span = var.span;
let expr = Box::new(self.var_decl_to_expr(var.take()));
return Stmt::Expr(ExprStmt { span, expr });
}
_ => {}
*s = Stmt::Expr(ExprStmt { span, expr });
return;
}
s.fold_children_with(self)
s.visit_mut_children_with(self);
}
fn fold_var_decl(&mut self, var: VarDecl) -> VarDecl {
fn visit_mut_var_decl(&mut self, var: &mut VarDecl) {
unreachable!("VarDecl should be removed by other pass: {:?}", var);
}
fn fold_var_decl_or_pat(&mut self, v: VarDeclOrPat) -> VarDeclOrPat {
fn visit_mut_var_decl_or_pat(&mut self, v: &mut VarDeclOrPat) {
match v {
VarDeclOrPat::Pat(v) => VarDeclOrPat::Pat(v.fold_children_with(self)),
VarDeclOrPat::Pat(v) => {
v.visit_mut_children_with(self);
}
VarDeclOrPat::VarDecl(mut var) => {
VarDeclOrPat::VarDecl(var) => {
if var.decls.len() == 1 && var.decls[0].init.is_none() {
let pat = var.decls.remove(0).name;
self.vars.extend(find_ids(&pat));
return pat.into();
*v = pat.into();
return;
}
var.into()
}
}
};
}
fn fold_var_decl_or_expr(&mut self, var: VarDeclOrExpr) -> VarDeclOrExpr {
fn visit_mut_var_decl_or_expr(&mut self, var: &mut VarDeclOrExpr) {
match var {
VarDeclOrExpr::VarDecl(var) => {
VarDeclOrExpr::Expr(Box::new(self.var_decl_to_expr(var)))
VarDeclOrExpr::VarDecl(var_decl) => {
*var = VarDeclOrExpr::Expr(Box::new(self.var_decl_to_expr(var_decl.take())));
}
_ => var.fold_children_with(self),
}
_ => {
var.visit_mut_children_with(self);
}
};
}
fn fold_opt_var_decl_or_expr(&mut self, v: Option<VarDeclOrExpr>) -> Option<VarDeclOrExpr> {
let v = v.fold_children_with(self);
fn visit_mut_opt_var_decl_or_expr(&mut self, v: &mut Option<VarDeclOrExpr>) {
v.visit_mut_children_with(self);
match &v {
Some(VarDeclOrExpr::Expr(e)) => {
if e.is_invalid() {
return None;
}
if let Some(VarDeclOrExpr::Expr(e)) = v {
if e.is_invalid() {
*v = None;
}
_ => {}
}
v
}
}