Skip to content

Commit

Permalink
perf(turbopack): Reduce size of Effect (#74969)
Browse files Browse the repository at this point in the history
### What?

Reduce the size of frequently created types by boxing server fields.

### Why?
  • Loading branch information
kdy1 authored Jan 16, 2025
1 parent 30b4a11 commit 5c2a39f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 66 deletions.
103 changes: 53 additions & 50 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,31 @@ impl EffectsBlock {
#[derive(Debug, Clone)]
pub enum ConditionalKind {
/// The blocks of an `if` statement without an `else` block.
If { then: EffectsBlock },
If { then: Box<EffectsBlock> },
/// The blocks of an `if ... else` or `if { ... return ... } ...` statement.
IfElse {
then: EffectsBlock,
r#else: EffectsBlock,
then: Box<EffectsBlock>,
r#else: Box<EffectsBlock>,
},
/// The blocks of an `if ... else` statement.
Else { r#else: EffectsBlock },
Else { r#else: Box<EffectsBlock> },
/// The blocks of an `if { ... return ... } else { ... } ...` or `if { ... }
/// else { ... return ... } ...` statement.
IfElseMultiple {
then: Vec<EffectsBlock>,
r#else: Vec<EffectsBlock>,
then: Vec<Box<EffectsBlock>>,
r#else: Vec<Box<EffectsBlock>>,
},
/// The expressions on the right side of the `?:` operator.
Ternary {
then: EffectsBlock,
r#else: EffectsBlock,
then: Box<EffectsBlock>,
r#else: Box<EffectsBlock>,
},
/// The expression on the right side of the `&&` operator.
And { expr: EffectsBlock },
And { expr: Box<EffectsBlock> },
/// The expression on the right side of the `||` operator.
Or { expr: EffectsBlock },
Or { expr: Box<EffectsBlock> },
/// The expression on the right side of the `??` operator.
NullishCoalescing { expr: EffectsBlock },
NullishCoalescing { expr: Box<EffectsBlock> },
}

impl ConditionalKind {
Expand Down Expand Up @@ -132,7 +132,7 @@ pub enum Effect {
/// condition evaluates to some compile-time constant, we can use that
/// to determine which effects are executed and remove the others.
Conditional {
condition: JsValue,
condition: Box<JsValue>,
kind: Box<ConditionalKind>,
/// The ast path to the condition.
ast_path: Vec<AstParentKind>,
Expand All @@ -141,7 +141,7 @@ pub enum Effect {
},
/// A function call or a new call of a function.
Call {
func: JsValue,
func: Box<JsValue>,
args: Vec<EffectArg>,
ast_path: Vec<AstParentKind>,
span: Span,
Expand All @@ -150,8 +150,8 @@ pub enum Effect {
},
/// A function call or a new call of a property of an object.
MemberCall {
obj: JsValue,
prop: JsValue,
obj: Box<JsValue>,
prop: Box<JsValue>,
args: Vec<EffectArg>,
ast_path: Vec<AstParentKind>,
span: Span,
Expand All @@ -160,8 +160,8 @@ pub enum Effect {
},
/// A property access.
Member {
obj: JsValue,
prop: JsValue,
obj: Box<JsValue>,
prop: Box<JsValue>,
ast_path: Vec<AstParentKind>,
span: Span,
in_try: bool,
Expand All @@ -176,14 +176,14 @@ pub enum Effect {
},
/// A reference to a free var access.
FreeVar {
var: JsValue,
var: Box<JsValue>,
ast_path: Vec<AstParentKind>,
span: Span,
in_try: bool,
},
/// A typeof expression
TypeOf {
arg: JsValue,
arg: Box<JsValue>,
ast_path: Vec<AstParentKind>,
span: Span,
},
Expand Down Expand Up @@ -720,9 +720,9 @@ enum EarlyReturn {
prev_effects: Vec<Effect>,
start_ast_path: Vec<AstParentKind>,

condition: JsValue,
then: Option<EffectsBlock>,
r#else: Option<EffectsBlock>,
condition: Box<JsValue>,
then: Option<Box<EffectsBlock>>,
r#else: Option<Box<EffectsBlock>>,
/// The ast path to the condition.
condition_ast_path: Vec<AstParentKind>,
span: Span,
Expand Down Expand Up @@ -1127,7 +1127,7 @@ impl Analyzer<'_> {
match callee {
Callee::Import(_) => {
self.add_effect(Effect::Call {
func: JsValue::FreeVar(js_word!("import")),
func: Box::new(JsValue::FreeVar(js_word!("import"))),
args,
ast_path: as_parent_path(ast_path),
span,
Expand All @@ -1137,15 +1137,15 @@ impl Analyzer<'_> {
}
Callee::Expr(box expr) => {
if let Expr::Member(MemberExpr { obj, prop, .. }) = unparen(expr) {
let obj_value = self.eval_context.eval(obj);
let obj_value = Box::new(self.eval_context.eval(obj));
let prop_value = match prop {
// TODO avoid clone
MemberProp::Ident(i) => i.sym.clone().into(),
MemberProp::Ident(i) => Box::new(i.sym.clone().into()),
MemberProp::PrivateName(_) => {
return;
}
MemberProp::Computed(ComputedPropName { expr, .. }) => {
self.eval_context.eval(expr)
Box::new(self.eval_context.eval(expr))
}
};
self.add_effect(Effect::MemberCall {
Expand All @@ -1158,7 +1158,7 @@ impl Analyzer<'_> {
new,
});
} else {
let fn_value = self.eval_context.eval(expr);
let fn_value = Box::new(self.eval_context.eval(expr));
self.add_effect(Effect::Call {
func: fn_value,
args,
Expand All @@ -1170,10 +1170,11 @@ impl Analyzer<'_> {
}
}
Callee::Super(_) => self.add_effect(Effect::Call {
func: self
.eval_context
// Unwrap because `new super(..)` isn't valid anyway
.eval(&Expr::Call(n.as_call().unwrap().clone())),
func: Box::new(
self.eval_context
// Unwrap because `new super(..)` isn't valid anyway
.eval(&Expr::Call(n.as_call().unwrap().clone())),
),
args,
ast_path: as_parent_path(ast_path),
span,
Expand All @@ -1188,14 +1189,16 @@ impl Analyzer<'_> {
member_expr: &'ast MemberExpr,
ast_path: &AstNodePath<AstParentNodeRef<'r>>,
) {
let obj_value = self.eval_context.eval(&member_expr.obj);
let obj_value = Box::new(self.eval_context.eval(&member_expr.obj));
let prop_value = match &member_expr.prop {
// TODO avoid clone
MemberProp::Ident(i) => i.sym.clone().into(),
MemberProp::Ident(i) => Box::new(i.sym.clone().into()),
MemberProp::PrivateName(_) => {
return;
}
MemberProp::Computed(ComputedPropName { expr, .. }) => self.eval_context.eval(expr),
MemberProp::Computed(ComputedPropName { expr, .. }) => {
Box::new(self.eval_context.eval(expr))
}
};
self.add_effect(Effect::Member {
obj: obj_value,
Expand Down Expand Up @@ -1241,10 +1244,10 @@ impl Analyzer<'_> {
in_try,
early_return_condition_value,
} => {
let block = EffectsBlock {
let block = Box::new(EffectsBlock {
effects: take(&mut self.effects),
range: AstPathRange::StartAfter(start_ast_path),
};
});
self.effects = prev_effects;
let kind = match (then, r#else, early_return_condition_value) {
(None, None, false) => ConditionalKind::If { then: block },
Expand Down Expand Up @@ -1873,7 +1876,7 @@ impl VisitAstPath for Analyzer<'_> {
})
} else if is_unresolved(ident, self.eval_context.unresolved_mark) {
self.add_effect(Effect::FreeVar {
var: JsValue::FreeVar(ident.sym.clone()),
var: Box::new(JsValue::FreeVar(ident.sym.clone())),
ast_path: as_parent_path(ast_path),
span: ident.span(),
in_try: is_in_try(ast_path),
Expand Down Expand Up @@ -1925,19 +1928,19 @@ impl VisitAstPath for Analyzer<'_> {
let mut ast_path =
ast_path.with_guard(AstParentNodeRef::CondExpr(expr, CondExprField::Cons));
expr.cons.visit_with_ast_path(self, &mut ast_path);
EffectsBlock {
Box::new(EffectsBlock {
effects: take(&mut self.effects),
range: AstPathRange::Exact(as_parent_path(&ast_path)),
}
})
};
let r#else = {
let mut ast_path =
ast_path.with_guard(AstParentNodeRef::CondExpr(expr, CondExprField::Alt));
expr.alt.visit_with_ast_path(self, &mut ast_path);
EffectsBlock {
Box::new(EffectsBlock {
effects: take(&mut self.effects),
range: AstPathRange::Exact(as_parent_path(&ast_path)),
}
})
};
self.effects = prev_effects;

Expand Down Expand Up @@ -1968,21 +1971,21 @@ impl VisitAstPath for Analyzer<'_> {
ast_path.with_guard(AstParentNodeRef::IfStmt(stmt, IfStmtField::Cons));
stmt.cons.visit_with_ast_path(self, &mut ast_path);
then_returning = self.end_early_return_block();
EffectsBlock {
Box::new(EffectsBlock {
effects: take(&mut self.effects),
range: AstPathRange::Exact(as_parent_path(&ast_path)),
}
})
};
let mut else_returning = false;
let r#else = stmt.alt.as_ref().map(|alt| {
let mut ast_path =
ast_path.with_guard(AstParentNodeRef::IfStmt(stmt, IfStmtField::Alt));
alt.visit_with_ast_path(self, &mut ast_path);
else_returning = self.end_early_return_block();
EffectsBlock {
Box::new(EffectsBlock {
effects: take(&mut self.effects),
range: AstPathRange::Exact(as_parent_path(&ast_path)),
}
})
});
self.early_return_stack = prev_early_return_stack;
self.effects = prev_effects;
Expand Down Expand Up @@ -2118,7 +2121,7 @@ impl VisitAstPath for Analyzer<'_> {
ast_path: &mut swc_core::ecma::visit::AstNodePath<'r>,
) {
if n.op == UnaryOp::TypeOf {
let arg_value = self.eval_context.eval(&n.arg);
let arg_value = Box::new(self.eval_context.eval(&n.arg));
self.add_effect(Effect::TypeOf {
arg: arg_value,
ast_path: as_parent_path(ast_path),
Expand All @@ -2137,16 +2140,16 @@ impl Analyzer<'_> {
ast_path: &AstNodePath<AstParentNodeRef<'_>>,
condition_ast_kind: AstParentKind,
span: Span,
then: Option<EffectsBlock>,
r#else: Option<EffectsBlock>,
then: Option<Box<EffectsBlock>>,
r#else: Option<Box<EffectsBlock>>,
early_return_when_true: bool,
early_return_when_false: bool,
) {
if then.is_none() && r#else.is_none() && !early_return_when_false && !early_return_when_true
{
return;
}
let condition = self.eval_context.eval(test);
let condition = Box::new(self.eval_context.eval(test));
if condition.is_unknown() {
if let Some(mut then) = then {
self.effects.append(&mut then.effects);
Expand Down Expand Up @@ -2215,7 +2218,7 @@ impl Analyzer<'_> {
span: Span,
mut cond_kind: ConditionalKind,
) {
let condition = self.eval_context.eval(test);
let condition = Box::new(self.eval_context.eval(test));
if condition.is_unknown() {
match &mut cond_kind {
ConditionalKind::If { then } => {
Expand Down
12 changes: 6 additions & 6 deletions turbopack/crates/turbopack-ecmascript/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4178,7 +4178,7 @@ mod tests {
condition, kind, ..
} => {
let condition =
resolve(&var_graph, condition, ImportAttributes::empty_ref())
resolve(&var_graph, *condition, ImportAttributes::empty_ref())
.await;
resolved.push((format!("{parent} -> {i} conditional"), condition));
match *kind {
Expand Down Expand Up @@ -4228,7 +4228,7 @@ mod tests {
} => {
let func = resolve(
&var_graph,
func,
*func,
eval_context.imports.get_attributes(span),
)
.await;
Expand All @@ -4243,11 +4243,11 @@ mod tests {
));
}
Effect::FreeVar { var, .. } => {
resolved.push((format!("{parent} -> {i} free var"), var));
resolved.push((format!("{parent} -> {i} free var"), *var));
}
Effect::TypeOf { arg, .. } => {
let arg =
resolve(&var_graph, arg, ImportAttributes::empty_ref()).await;
resolve(&var_graph, *arg, ImportAttributes::empty_ref()).await;
resolved.push((
format!("{parent} -> {i} typeof"),
JsValue::type_of(Box::new(arg)),
Expand All @@ -4257,9 +4257,9 @@ mod tests {
obj, prop, args, ..
} => {
let obj =
resolve(&var_graph, obj, ImportAttributes::empty_ref()).await;
resolve(&var_graph, *obj, ImportAttributes::empty_ref()).await;
let prop =
resolve(&var_graph, prop, ImportAttributes::empty_ref()).await;
resolve(&var_graph, *prop, ImportAttributes::empty_ref()).await;
let new_args = handle_args(args, &mut queue, &var_graph, i).await;
resolved.push((
format!("{parent} -> {i} member call"),
Expand Down
Loading

0 comments on commit 5c2a39f

Please sign in to comment.