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

Skip unreachable code when early return can be statically analysed #8890

Merged
merged 15 commits into from
Aug 1, 2024
410 changes: 362 additions & 48 deletions crates/turbopack-ecmascript/src/analyzer/graph.rs

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions crates/turbopack-ecmascript/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3866,6 +3866,11 @@ mod tests {
queue
.extend(then.effects.into_iter().rev().map(|e| (i, e)));
}
ConditionalKind::Else { r#else } => {
queue.extend(
r#else.effects.into_iter().rev().map(|e| (i, e)),
);
}
ConditionalKind::IfElse { then, r#else }
| ConditionalKind::Ternary { then, r#else } => {
queue.extend(
Expand All @@ -3874,6 +3879,18 @@ mod tests {
queue
.extend(then.effects.into_iter().rev().map(|e| (i, e)));
}
ConditionalKind::IfElseMultiple { then, r#else } => {
for then in then {
queue.extend(
then.effects.into_iter().rev().map(|e| (i, e)),
);
}
for r#else in r#else {
queue.extend(
r#else.effects.into_iter().rev().map(|e| (i, e)),
);
}
}
ConditionalKind::And { expr }
| ConditionalKind::Or { expr }
| ConditionalKind::NullishCoalescing { expr } => {
Expand Down Expand Up @@ -3904,6 +3921,12 @@ mod tests {
JsValue::member_call(Box::new(obj), Box::new(prop), new_args),
));
}
Effect::Unreachable { .. } => {
resolved.push((
format!("{parent} -> {i} unreachable"),
JsValue::unknown_empty(true, "unreachable"),
));
}
_ => {}
}
let time = start.elapsed();
Expand Down
2 changes: 2 additions & 0 deletions crates/turbopack-ecmascript/src/path_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ impl VisitMutAstPath for ApplyVisitors<'_, '_> {
method!(visit_mut_call_expr, CallExpr);
method!(visit_mut_lit, Lit);
method!(visit_mut_str, Str);
method!(visit_mut_block_stmt, BlockStmt);
method!(visit_mut_switch_case, SwitchCase);
}

#[cfg(test)]
Expand Down
50 changes: 49 additions & 1 deletion crates/turbopack-ecmascript/src/references/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ use crate::{
type_issue::SpecifiedModuleTypeIssue,
},
tree_shake::{find_turbopack_part_id_in_asserts, part_of_module, split},
utils::AstPathRange,
EcmascriptInputTransforms, EcmascriptModuleAsset, SpecifiedModuleType, TreeShakingMode,
};

Expand Down Expand Up @@ -861,6 +862,11 @@ pub(crate) async fn analyse_ecmascript_module_internal(
};

match effect {
Effect::Unreachable { start_ast_path } => {
analysis.add_code_gen(Unreachable::new(
AstPathRange::StartAfter(start_ast_path.to_vec()).cell(),
));
}
Effect::Conditional {
condition,
kind,
Expand All @@ -872,7 +878,7 @@ pub(crate) async fn analyse_ecmascript_module_internal(

macro_rules! inactive {
($block:ident) => {
analysis.add_code_gen(Unreachable::new(Vc::cell($block.ast_path.to_vec())));
analysis.add_code_gen(Unreachable::new($block.range.clone().cell()));
};
}
macro_rules! condition {
Expand Down Expand Up @@ -904,6 +910,19 @@ pub(crate) async fn analyse_ecmascript_module_internal(
active!(then);
}
},
ConditionalKind::Else { r#else } => match condition.is_truthy() {
Some(true) => {
condition!(ConstantConditionValue::Truthy);
inactive!(r#else);
}
Some(false) => {
condition!(ConstantConditionValue::Falsy);
active!(r#else);
}
None => {
active!(r#else);
}
},
ConditionalKind::IfElse { then, r#else }
| ConditionalKind::Ternary { then, r#else } => match condition.is_truthy() {
Some(true) => {
Expand All @@ -921,6 +940,35 @@ pub(crate) async fn analyse_ecmascript_module_internal(
active!(r#else);
}
},
ConditionalKind::IfElseMultiple { then, r#else } => match condition.is_truthy()
{
Some(true) => {
condition!(ConstantConditionValue::Truthy);
for then in then {
active!(then);
}
for r#else in r#else {
inactive!(r#else);
}
}
Some(false) => {
condition!(ConstantConditionValue::Falsy);
for then in then {
inactive!(then);
}
for r#else in r#else {
active!(r#else);
}
}
None => {
for then in then {
active!(then);
}
for r#else in r#else {
active!(r#else);
}
}
},
ConditionalKind::And { expr } => match condition.is_truthy() {
Some(true) => {
condition!(ConstantConditionValue::Truthy);
Expand Down
Loading
Loading