From e5119da97a67d304d96b25093ba8de617a2c0ba3 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 8 Aug 2012 15:09:19 +0400 Subject: [PATCH] Multiple fixes for try-catch-finally codegen #KT-2259 Fixed #KT-2577 Fixed --- .../jet/codegen/ExpressionCodegen.java | 42 ++++++++++++++++--- .../controlStructures/tryCatchFinallyChain.kt | 19 +++++++++ .../testData/codegen/regressions/kt2259.kt | 10 +++++ .../testData/codegen/regressions/kt2577.kt | 12 ++++++ .../jet/codegen/ControlStructuresTest.java | 15 +++++++ 5 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/controlStructures/tryCatchFinallyChain.kt create mode 100644 compiler/testData/codegen/regressions/kt2259.kt create mode 100644 compiler/testData/codegen/regressions/kt2577.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 5f30fb424cc..4e822fca3aa 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2717,25 +2717,38 @@ The "returned" value of try expression with no finally is either the last expres (or blocks). */ JetFinallySection finallyBlock = expression.getFinallyBlock(); + FinallyBlockStackElement finallyBlockStackElement = null; if (finallyBlock != null) { - blockStackElements.push(new FinallyBlockStackElement(expression)); + finallyBlockStackElement = new FinallyBlockStackElement(expression); + blockStackElements.push(finallyBlockStackElement); } JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); Type expectedAsmType = asmType(jetType); - + Label tryStart = new Label(); v.mark(tryStart); v.nop(); // prevent verify error on empty try + gen(expression.getTryBlock(), expectedAsmType); + + int savedValue = myFrameMap.enterTemp(expectedAsmType.getSize()); + v.store(savedValue, expectedAsmType); + Label tryEnd = new Label(); v.mark(tryEnd); if (finallyBlock != null) { + blockStackElements.pop(); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); + blockStackElements.push(finallyBlockStackElement); } Label end = new Label(); - v.goTo(end); // TODO don't generate goto if there's no code following try/catch - for (JetCatchClause clause : expression.getCatchClauses()) { + v.goTo(end); + + List clauses = expression.getCatchClauses(); + for (int i = 0, size = clauses.size(); i < size; i++) { + JetCatchClause clause = clauses.get(i); + Label clauseStart = new Label(); v.mark(clauseStart); @@ -2748,28 +2761,45 @@ The "returned" value of try expression with no finally is either the last expres gen(clause.getCatchBody(), expectedAsmType); + v.store(savedValue, expectedAsmType); + myFrameMap.leave(descriptor); if (finallyBlock != null) { + blockStackElements.pop(); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); + blockStackElements.push(finallyBlockStackElement); } - v.goTo(end); // TODO don't generate goto if there's no code following try/catch + if (i != size - 1 || finallyBlock != null) { + v.goTo(end); + } v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName()); } + if (finallyBlock != null) { Label finallyStart = new Label(); v.mark(finallyStart); + int savedException = myFrameMap.enterTemp(); + v.store(savedException, TYPE_THROWABLE); + + blockStackElements.pop(); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); + blockStackElements.push(finallyBlockStackElement); + + v.load(savedException, TYPE_THROWABLE); + myFrameMap.leaveTemp(); v.athrow(); v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null); } v.mark(end); - v.nop(); + + v.load(savedValue, expectedAsmType); + myFrameMap.leaveTemp(expectedAsmType.getSize()); if (finallyBlock != null) { blockStackElements.pop(); diff --git a/compiler/testData/codegen/controlStructures/tryCatchFinallyChain.kt b/compiler/testData/codegen/controlStructures/tryCatchFinallyChain.kt new file mode 100644 index 00000000000..b0ee1f314dc --- /dev/null +++ b/compiler/testData/codegen/controlStructures/tryCatchFinallyChain.kt @@ -0,0 +1,19 @@ +fun box() : String { + try { + } finally { + try { + try { + } finally { + try { + } finally { + } + } + } catch (e: Exception) { + try { + } catch (f: Exception) { + } finally { + } + } + return "OK" + } +} diff --git a/compiler/testData/codegen/regressions/kt2259.kt b/compiler/testData/codegen/regressions/kt2259.kt new file mode 100644 index 00000000000..7b695efee06 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2259.kt @@ -0,0 +1,10 @@ +fun main(args: Array) { + try { + } finally { + try { + } catch (e: Throwable) { + } + } +} + +fun box() = "OK" diff --git a/compiler/testData/codegen/regressions/kt2577.kt b/compiler/testData/codegen/regressions/kt2577.kt new file mode 100644 index 00000000000..c11ba235411 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2577.kt @@ -0,0 +1,12 @@ +fun foo(): Int { + try { + } finally { + try { + return 1 + } catch (e: Throwable) { + return 2 + } + } +} + +fun box() = if (foo() == 1) "OK" else "Fail" diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 8b656289c87..51f30277962 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -376,4 +376,19 @@ public class ControlStructuresTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("regressions/kt2291.kt"); } + + public void testKt2259() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("regressions/kt2259.kt"); + } + + public void testKt2577() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("regressions/kt2577.kt"); + } + + public void testTryCatchFinallyChain() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("controlStructures/tryCatchFinallyChain.kt"); + } }