Remove empty try catch nodes from inlined code

This commit is contained in:
Michael Bogdanov
2014-10-22 15:03:23 +04:00
parent f50d8c0731
commit b212fbd0b5
5 changed files with 54 additions and 8 deletions
@@ -356,7 +356,6 @@ public class MethodInliner {
AbstractInsnNode cur = node.instructions.getFirst();
int index = 0;
Set<LabelNode> possibleDeadLabels = new HashSet<LabelNode>();
while (cur != null) {
Frame<SourceValue> frame = sources[index];
@@ -416,15 +415,12 @@ public class MethodInliner {
if (frame == null) {
//clean dead code otherwise there is problems in unreachable finally block, don't touch label it cause try/catch/finally problems
if (prevNode.getType() == AbstractInsnNode.LABEL) {
possibleDeadLabels.add((LabelNode) prevNode);
//NB: Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression)
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
//but as result all this labels will be merged into one (see KT-5863)
} else {
node.instructions.remove(prevNode);
}
} else {
//Cause we generate exception table for default handler using gaps (see ExpressionCodegen.visitTryExpression)
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
//but as result all this labels will be merged into one (see KT-5863)
possibleDeadLabels.remove(prevNode.getPrevious());
}
}
@@ -432,7 +428,7 @@ public class MethodInliner {
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
TryCatchBlockNode block = iterator.next();
if (possibleDeadLabels.contains(block.start) && possibleDeadLabels.contains(block.end)) {
if (isEmptyTryInterval(block)) {
iterator.remove();
}
}
@@ -440,6 +436,15 @@ public class MethodInliner {
return node;
}
private static boolean isEmptyTryInterval(@NotNull TryCatchBlockNode tryCatchBlockNode) {
LabelNode start = tryCatchBlockNode.start;
AbstractInsnNode end = tryCatchBlockNode.end;
while (end != start && end instanceof LabelNode) {
end = end.getPrevious();
}
return start == end;
}
public LambdaInfo getLambdaIfExists(AbstractInsnNode insnNode) {
if (insnNode.getOpcode() == Opcodes.ALOAD) {
int varIndex = ((VarInsnNode) insnNode).var;
@@ -0,0 +1,18 @@
import test.*
fun call(): String {
return nonLocal()
}
inline fun nonLocal(): String {
mysynchronized(Object()) {
return "nonLocal"
}
return "local"
}
fun box(): String {
val call = call()
if (call != "nonLocal") return "fail $call"
return "OK"
}
@@ -0,0 +1,11 @@
package test
public inline fun <R> mysynchronized(lock: Any, block: () -> R): R {
try {
return block()
}
finally {
//do nothing
1
}
}
@@ -567,6 +567,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("synchonized.1.kt")
public void testSynchonized() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("throwInFinally.1.kt")
public void testThrowInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt");
@@ -567,6 +567,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("synchonized.1.kt")
public void testSynchonized() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/synchonized.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("throwInFinally.1.kt")
public void testThrowInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt");