diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 7d92295fc77..9fb2d608c2f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1197,16 +1197,20 @@ public class ExpressionCodegen extends JetVisitor implem @Override public StackValue visitBreakExpression(@NotNull JetBreakExpression expression, StackValue receiver) { - return generateBreakOrContinueExpression(expression, true); + return generateBreakOrContinueExpression(expression, true, new Label()); } @Override public StackValue visitContinueExpression(@NotNull JetContinueExpression expression, StackValue receiver) { - return generateBreakOrContinueExpression(expression, false); + return generateBreakOrContinueExpression(expression, false, new Label()); } @NotNull - private StackValue generateBreakOrContinueExpression(@NotNull JetExpressionWithLabel expression, boolean isBreak) { + private StackValue generateBreakOrContinueExpression( + @NotNull JetExpressionWithLabel expression, + boolean isBreak, + @NotNull Label afterBreakContinueLabel + ) { assert expression instanceof JetContinueExpression || expression instanceof JetBreakExpression; if (!blockStackElements.isEmpty()) { @@ -1215,7 +1219,7 @@ public class ExpressionCodegen extends JetVisitor implem if (stackElement instanceof FinallyBlockStackElement) { FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; //noinspection ConstantConditions - genFinallyBlockOrGoto(finallyBlockStackElement, null); + genFinallyBlockOrGoto(finallyBlockStackElement, null, afterBreakContinueLabel); } else if (stackElement instanceof LoopBlockStackElement) { LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; @@ -1225,6 +1229,7 @@ public class ExpressionCodegen extends JetVisitor implem loopBlockStackElement.targetLabel != null && labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { v.goTo(isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel); + v.mark(afterBreakContinueLabel); return StackValue.none(); } } @@ -1233,7 +1238,7 @@ public class ExpressionCodegen extends JetVisitor implem } blockStackElements.pop(); - StackValue result = generateBreakOrContinueExpression(expression, isBreak); + StackValue result = generateBreakOrContinueExpression(expression, isBreak, afterBreakContinueLabel); blockStackElements.push(stackElement); return result; } @@ -1754,12 +1759,12 @@ public class ExpressionCodegen extends JetVisitor implem } } - private void doFinallyOnReturn() { + private void doFinallyOnReturn(Label afterReturnLabel) { if(!blockStackElements.isEmpty()) { BlockStackElement stackElement = blockStackElements.peek(); if (stackElement instanceof FinallyBlockStackElement) { FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; - genFinallyBlockOrGoto(finallyBlockStackElement, null); + genFinallyBlockOrGoto(finallyBlockStackElement, null, afterReturnLabel); } else if (stackElement instanceof LoopBlockStackElement) { @@ -1768,7 +1773,7 @@ public class ExpressionCodegen extends JetVisitor implem } blockStackElements.pop(); - doFinallyOnReturn(); + doFinallyOnReturn(afterReturnLabel); blockStackElements.push(stackElement); } } @@ -1784,7 +1789,8 @@ public class ExpressionCodegen extends JetVisitor implem private void genFinallyBlockOrGoto( @Nullable FinallyBlockStackElement finallyBlockStackElement, - @Nullable Label tryCatchBlockEnd + @Nullable Label tryCatchBlockEnd, + @Nullable Label afterReturnLabel ) { if (finallyBlockStackElement != null) { assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; @@ -1809,8 +1815,10 @@ public class ExpressionCodegen extends JetVisitor implem } if (finallyBlockStackElement != null) { - Label finallyEnd = new Label(); - v.mark(finallyEnd); + Label finallyEnd = afterReturnLabel != null ? afterReturnLabel : new Label(); + if (afterReturnLabel == null) { + v.mark(finallyEnd); + } finallyBlockStackElement.addGapLabel(finallyEnd); blockStackElements.push(finallyBlockStackElement); @@ -1835,28 +1843,30 @@ public class ExpressionCodegen extends JetVisitor implem gen(returnedExpression, returnType); } - generateFinallyBlocksIfNeeded(returnType); + Label afterReturnLabel = new Label(); + generateFinallyBlocksIfNeeded(returnType, afterReturnLabel); if (isNonLocalReturn) { InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName); } v.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); + v.mark(afterReturnLabel); return StackValue.none(); } - public void generateFinallyBlocksIfNeeded(Type returnType) { + public void generateFinallyBlocksIfNeeded(Type returnType, @NotNull Label afterReturnLabel) { if (hasFinallyBlocks()) { if (!Type.VOID_TYPE.equals(returnType)) { int returnValIndex = myFrameMap.enterTemp(returnType); StackValue.Local localForReturnValue = StackValue.local(returnValIndex, returnType); localForReturnValue.store(StackValue.onStack(returnType), v); - doFinallyOnReturn(); + doFinallyOnReturn(afterReturnLabel); localForReturnValue.put(returnType, v); myFrameMap.leaveTemp(returnType); } else { - doFinallyOnReturn(); + doFinallyOnReturn(afterReturnLabel); } } } @@ -3571,7 +3581,7 @@ The "returned" value of try expression with no finally is either the last expres Label end = new Label(); - genFinallyBlockOrGoto(finallyBlockStackElement, end); + genFinallyBlockOrGoto(finallyBlockStackElement, end, null); List clauses = expression.getCatchClauses(); for (int i = 0, size = clauses.size(); i < size; i++) { @@ -3601,7 +3611,7 @@ The "returned" value of try expression with no finally is either the last expres v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, index); - genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); + genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null, null); generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); } @@ -3621,7 +3631,7 @@ The "returned" value of try expression with no finally is either the last expres List