Skip to content

Commit

Permalink
perf(es/transforms/compat): Migrate spread to VisitMut (#2888)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj authored Nov 27, 2021
1 parent 035b6d8 commit 283074c
Showing 1 changed file with 55 additions and 62 deletions.
117 changes: 55 additions & 62 deletions crates/swc_ecma_transforms_compat/src/es2015/spread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ use swc_ecma_utils::{
alias_ident_for, is_literal, member_expr, prepend, quote_ident, undefined, ExprFactory,
StmtLike,
};
use swc_ecma_visit::{noop_fold_type, noop_visit_type, Fold, FoldWith, Node, Visit, VisitWith};
use swc_ecma_visit::{
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Node, Visit, VisitMut, VisitMutWith,
VisitWith,
};

pub fn spread(c: Config) -> impl Fold {
Spread {
pub fn spread(c: Config) -> impl Fold + VisitMut {
as_folder(Spread {
c,
vars: Default::default(),
}
})
}

#[derive(Debug, Clone, Copy, Default, Deserialize)]
Expand All @@ -31,21 +34,20 @@ struct Spread {
vars: Vec<VarDeclarator>,
}

/// TODO: VisitMut
#[fast_path(SpreadFinder)]
impl Fold for Spread {
noop_fold_type!();
impl VisitMut for Spread {
noop_visit_mut_type!();

fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n)
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
self.visit_mut_stmt_like(n);
}

fn fold_stmts(&mut self, n: Vec<Stmt>) -> Vec<Stmt> {
self.fold_stmt_like(n)
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
self.visit_mut_stmt_like(n);
}

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::Array(ArrayLit { span, elems }) => {
Expand All @@ -55,50 +57,46 @@ impl Fold for Spread {
}) => true,
_ => false,
}) {
return Expr::Array(ArrayLit { span, elems });
return;
}

self.concat_args(span, elems.into_iter(), true)
*e = self.concat_args(*span, elems.take().into_iter(), true);
}

// super(...spread) should be removed by es2015::classes pass
Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(callee),
args,
span,
type_args,
..
}) => {
let has_spread = args
.iter()
.any(|ExprOrSpread { spread, .. }| spread.is_some());
if !has_spread {
return Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(callee),
args,
span,
type_args,
});
return;
}
let (this, callee) = match *callee {

let (this, callee_updated) = match &**callee {
Expr::Member(MemberExpr {
obj: ExprOrSuper::Super(Super { span, .. }),
..
}) => (Box::new(Expr::This(ThisExpr { span })), callee),
}) => (Box::new(Expr::This(ThisExpr { span: *span })), None),

Expr::Member(MemberExpr {
obj: ExprOrSuper::Expr(ref expr),
..
}) if expr.is_this() => (expr.clone(), callee),
}) if expr.is_this() => (expr.clone(), None),

// Injected variables can be accessed without any side effect
Expr::Member(MemberExpr {
obj: ExprOrSuper::Expr(ref e),
..
}) if e.as_ident().is_some() && e.as_ident().unwrap().span.is_dummy() => {
(Box::new(Expr::Ident(e.as_ident().unwrap().clone())), callee)
(Box::new(Expr::Ident(e.as_ident().unwrap().clone())), None)
}

Expr::Ident(Ident { span, .. }) => (undefined(span), callee),
Expr::Ident(Ident { span, .. }) => (undefined(*span), None),

Expr::Member(MemberExpr {
span,
Expand All @@ -121,16 +119,16 @@ impl Fold for Spread {
span: DUMMY_SP,
left: PatOrExpr::Pat(Box::new(Pat::Ident(ident.into()))),
op: op!("="),
right: expr,
right: expr.clone(),
});
(
this,
Box::new(Expr::Member(MemberExpr {
span,
Some(Box::new(Expr::Member(MemberExpr {
span: *span,
obj: callee.as_obj(),
prop,
computed,
})),
prop: prop.clone(),
computed: *computed,
}))),
)
}

Expand All @@ -140,27 +138,28 @@ impl Fold for Spread {
Box::new(Expr::This(ThisExpr {
span: callee.span(),
})),
callee,
None,
),
};

let args_array = if is_literal(&args) {
let args_array = if is_literal(args) {
Expr::Array(ArrayLit {
span,
elems: expand_literal_args(args.into_iter().map(Some)),
span: *span,
elems: expand_literal_args(args.take().into_iter().map(Some)),
})
} else {
self.concat_args(span, args.into_iter().map(Some), false)
self.concat_args(*span, args.take().into_iter().map(Some), false)
};

let apply = MemberExpr {
span: DUMMY_SP,
obj: callee.as_callee(),
prop: Box::new(Ident::new(js_word!("apply"), span).into()),
obj: callee_updated.unwrap_or(callee.take()).as_callee(),
prop: Box::new(Ident::new(js_word!("apply"), *span).into()),
computed: false,
};

Expr::Call(CallExpr {
span,
*e = Expr::Call(CallExpr {
span: *span,
callee: apply.as_callee(),
args: vec![this.as_arg(), args_array.as_arg()],
type_args: None,
Expand All @@ -170,46 +169,42 @@ impl Fold for Spread {
callee,
args: Some(args),
span,
type_args,
..
}) => {
let has_spread = args
.iter()
.any(|ExprOrSpread { spread, .. }| spread.is_some());
if !has_spread {
return Expr::New(NewExpr {
span,
callee,
args: Some(args),
type_args,
});
return;
}

let args = self.concat_args(span, args.into_iter().map(Some), true);
let args = self.concat_args(*span, args.take().into_iter().map(Some), true);

Expr::Call(CallExpr {
span,
*e = Expr::Call(CallExpr {
span: *span,
callee: helper!(construct, "construct"),
args: vec![callee.as_arg(), args.as_arg()],
args: vec![callee.take().as_arg(), args.as_arg()],
type_args: Default::default(),
})
});
}
_ => e,
}
_ => {}
};
}
}

impl Spread {
fn fold_stmt_like<T>(&mut self, items: Vec<T>) -> Vec<T>
fn visit_mut_stmt_like<T>(&mut self, items: &mut Vec<T>)
where
T: StmtLike,
Vec<T>: FoldWith<Self>,
Vec<T>: VisitMutWith<Self>,
{
let orig = self.vars.take();

let mut items = items.fold_children_with(self);
items.visit_mut_children_with(self);

if !self.vars.is_empty() {
prepend(
&mut items,
items,
T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
Expand All @@ -220,8 +215,6 @@ impl Spread {
}

self.vars = orig;

items
}
}

Expand Down

1 comment on commit 283074c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 283074c Previous: 035b6d8 Ratio
base_tr_fixer 23342 ns/iter (± 407) 33605 ns/iter (± 3285) 0.69
base_tr_resolver_and_hygiene 133463 ns/iter (± 25724) 187003 ns/iter (± 44942) 0.71
codegen_es2015 52007 ns/iter (± 326) 69496 ns/iter (± 12253) 0.75
codegen_es2016 51397 ns/iter (± 345) 66383 ns/iter (± 18315) 0.77
codegen_es2017 51569 ns/iter (± 505) 67909 ns/iter (± 18071) 0.76
codegen_es2018 51731 ns/iter (± 348) 67287 ns/iter (± 5706) 0.77
codegen_es2019 51655 ns/iter (± 384) 69528 ns/iter (± 6331) 0.74
codegen_es2020 52054 ns/iter (± 584) 70531 ns/iter (± 13121) 0.74
codegen_es3 51510 ns/iter (± 352) 68484 ns/iter (± 23153) 0.75
codegen_es5 51707 ns/iter (± 290) 70713 ns/iter (± 10030) 0.73
full_es2015 180079660 ns/iter (± 7098418) 232092062 ns/iter (± 42466820) 0.78
full_es2016 143831470 ns/iter (± 7287387) 187062182 ns/iter (± 18741000) 0.77
full_es2017 152308374 ns/iter (± 9629973) 193270552 ns/iter (± 16039852) 0.79
full_es2018 149396809 ns/iter (± 18585406) 193108181 ns/iter (± 28309681) 0.77
full_es2019 148196876 ns/iter (± 17943482) 199915439 ns/iter (± 19647507) 0.74
full_es2020 148811753 ns/iter (± 9144414) 197732477 ns/iter (± 41625449) 0.75
full_es3 209811979 ns/iter (± 17887226) 271627624 ns/iter (± 39134342) 0.77
full_es5 192877469 ns/iter (± 11619706) 249821895 ns/iter (± 27638653) 0.77
parser 651512 ns/iter (± 19790) 939345 ns/iter (± 182412) 0.69
ser_ast_node 148 ns/iter (± 3) 188 ns/iter (± 21) 0.79
ser_serde 164 ns/iter (± 3) 210 ns/iter (± 45) 0.78
emit_colors 17734450 ns/iter (± 23492392) 12817537 ns/iter (± 17260637) 1.38
emit_large 117340641 ns/iter (± 177941776) 84376246 ns/iter (± 116645356) 1.39
base_clone 2259287 ns/iter (± 327488) 2871290 ns/iter (± 341013) 0.79
fold_span 3778815 ns/iter (± 135936) 4939186 ns/iter (± 615160) 0.77
fold_span_panic 3977697 ns/iter (± 82576) 5108617 ns/iter (± 1455132) 0.78
visit_mut_span 2757977 ns/iter (± 36430) 3460150 ns/iter (± 496947) 0.80
visit_mut_span_panic 2818213 ns/iter (± 37545) 3485620 ns/iter (± 630500) 0.81
ast_clone 16951 ns/iter (± 189) 25299 ns/iter (± 2927) 0.67
ast_clone_to_stable 51518 ns/iter (± 437) 80618 ns/iter (± 19644) 0.64
ast_clone_to_stable_then_to_unstable 93604 ns/iter (± 557) 141903 ns/iter (± 27614) 0.66
json_deserialize 1945558 ns/iter (± 21003) 2706702 ns/iter (± 269160) 0.72
json_serialize 84492 ns/iter (± 376) 116630 ns/iter (± 35146) 0.72
boxing_boxed 143 ns/iter (± 0) 190 ns/iter (± 33) 0.75
boxing_boxed_clone 67 ns/iter (± 0) 88 ns/iter (± 16) 0.76
boxing_unboxed 143 ns/iter (± 1) 179 ns/iter (± 23) 0.80
boxing_unboxed_clone 64 ns/iter (± 0) 85 ns/iter (± 11) 0.75
time_10 310 ns/iter (± 2) 382 ns/iter (± 72) 0.81
time_15 645 ns/iter (± 6) 812 ns/iter (± 174) 0.79
time_20 1274 ns/iter (± 2) 1385 ns/iter (± 369) 0.92
time_40 6981 ns/iter (± 18) 5500 ns/iter (± 549) 1.27
time_5 105 ns/iter (± 0) 127 ns/iter (± 19) 0.83
time_60 16622 ns/iter (± 30) 11401 ns/iter (± 954) 1.46

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.