mirror of
https://github.com/dart-lang/sdk
synced 2024-10-02 23:59:16 +00:00
[vm/aot] Eliminate unnecessary try/catch and try/finally
This change adds an ability to replace try { <body> } catch (...) { throw; } and try { <body> } finally { } with <body> into unreachable code elimination kernel transformation, which is used in AOT. These constructs can appear after assert code is removed. Issue: https://github.com/dart-lang/sdk/issues/40925 Change-Id: I7940aab316aac3a9aeadb9b506b9c0ef3f79610d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138890 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
ace1d9b921
commit
2397862762
|
@ -136,6 +136,37 @@ class SimpleUnreachableCodeElimination extends Transformer {
|
|||
return super.visitAssertInitializer(node);
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitTryFinally(TryFinally node) {
|
||||
node.transformChildren(this);
|
||||
final fin = node.finalizer;
|
||||
if (fin == null || (fin is Block && fin.statements.isEmpty)) {
|
||||
return node.body;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
bool _isRethrow(Statement body) {
|
||||
if (body is ExpressionStatement && body.expression is Rethrow) {
|
||||
return true;
|
||||
} else if (body is Block && body.statements.length == 1) {
|
||||
return _isRethrow(body.statements.single);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitTryCatch(TryCatch node) {
|
||||
node.transformChildren(this);
|
||||
// Can replace try/catch with its body if all catches are just rethow.
|
||||
for (Catch catchClause in node.catches) {
|
||||
if (!_isRethrow(catchClause.body)) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return node.body;
|
||||
}
|
||||
|
||||
// Make sure we're not generating `null` bodies.
|
||||
// Try/catch, try/finally and switch/case statements
|
||||
// always have a Block in a body, so there is no
|
||||
|
|
|
@ -96,6 +96,12 @@ testRemovalOfStatementBodies() {
|
|||
} catch (e) {
|
||||
assert(foo());
|
||||
}
|
||||
try {
|
||||
assert(foo());
|
||||
} catch (e) {
|
||||
assert(foo());
|
||||
rethrow;
|
||||
}
|
||||
switch (42) {
|
||||
case 10:
|
||||
assert(foo());
|
||||
|
|
|
@ -63,14 +63,12 @@ static method testRemovalOfStatementBodies() → dynamic {
|
|||
core::int* i = :sync-for-iterator.{core::Iterator::current};
|
||||
}
|
||||
}
|
||||
try {
|
||||
}
|
||||
finally {
|
||||
}
|
||||
{}
|
||||
try {
|
||||
}
|
||||
on dynamic catch(final dynamic e) {
|
||||
}
|
||||
{}
|
||||
switch(42) {
|
||||
#L1:
|
||||
case #C3:
|
||||
|
|
Loading…
Reference in a new issue