Skip to content

Commit

Permalink
Skip unreachable code when early return can be statically analysed (v…
Browse files Browse the repository at this point in the history
…ercel/turborepo#8890)

### Description

* tracks early returns and their conditions
* replaces unreachable code with `"TURBOPACK unreachable"`
* finds hoisted declarations in unreachable code and keeps them

### Testing Instructions

<!--
  Give a quick description of steps to test your changes.
-->
  • Loading branch information
sokra authored Aug 1, 2024
1 parent 6947e3e commit fb033c4
Show file tree
Hide file tree
Showing 64 changed files with 34,904 additions and 19,864 deletions.
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

0 comments on commit fb033c4

Please sign in to comment.