Fixes for inline fun finally block generation before lambda non-local returns

This commit is contained in:
Michael Bogdanov
2014-10-23 11:27:53 +04:00
parent 25d7c9f20a
commit dd8c3f0e49
10 changed files with 462 additions and 40 deletions
@@ -26,7 +26,11 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.org.objectweb.asm.*;
import org.jetbrains.org.objectweb.asm.tree.*;
import org.jetbrains.org.objectweb.asm.util.Textifier;
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import static org.jetbrains.jet.codegen.inline.InlineCodegenUtil.*;
@@ -43,6 +47,18 @@ public class InternalFinallyBlockInliner {
startIns = inclusiveStart;
endInsExclusive = exclusiveEnd;
}
public boolean isEmpty() {
if (!(startIns instanceof LabelNode)) {
return false;
}
AbstractInsnNode end = endInsExclusive;
while (end != startIns && end instanceof LabelNode) {
end = end.getPrevious();
}
return startIns == end;
}
}
public static void processInlineFunFinallyBlocks(@NotNull MethodNode inlineFun, int lambdaTryCatchBlockNodes) {
@@ -99,7 +115,10 @@ public class InternalFinallyBlockInliner {
updateCoveringTryBlocks(coveringTryCatchBlocks, curIns);
//At this point only global return is possible, local one already substituted with: goto endLabel
if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) || !InlineCodegenUtil.isMarkedReturn(curIns)) {
if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) ||
!InlineCodegenUtil.isMarkedReturn(curIns) ||
coveringTryCatchBlocks.isEmpty() ||
coveringTryCatchBlocks.get(0).getOnlyCopyNotProcess()) {
curIns = curIns.getPrevious();
continue;
}
@@ -115,15 +134,26 @@ public class InternalFinallyBlockInliner {
// So we split all try blocks on current instructions to groups and process them independently
List<TryBlockCluster<TryCatchBlockNodeInfo>> clusters = InlinePackage.doClustering(coveringTryCatchBlocks);
ListIterator<TryBlockCluster<TryCatchBlockNodeInfo>> tryCatchBlockIterator = clusters.listIterator(clusters.size());
//Reverse visiting cause innermost tryCatchBlocks in the end
while (tryCatchBlockIterator.hasPrevious()) {
TryBlockCluster originalFinallyCluster = tryCatchBlockIterator.previous();
List<TryCatchBlockNodeInfo> clusterBlocks = originalFinallyCluster.getBlocks();
TryCatchBlockNodeInfo originalFinallyBlock = clusterBlocks.get(0);
FinallyBlockInfo finallyInfo = findFinallyBlockBody(originalFinallyBlock, inlineFunTryBlockInfo);
checkClusterInvariant(clusters);
//Reverse visiting cause innermost tryCatchBlocks in the end
List<TryCatchBlockNodeInfo> patched = new ArrayList<TryCatchBlockNodeInfo>();
while (tryCatchBlockIterator.hasPrevious()) {
TryBlockCluster clusterToFindFinally = tryCatchBlockIterator.previous();
List<TryCatchBlockNodeInfo> clusterBlocks = clusterToFindFinally.getBlocks();
TryCatchBlockNodeInfo originalTryCatchBlock = clusterBlocks.get(0);
FinallyBlockInfo finallyInfo = findFinallyBlockBody(originalTryCatchBlock, inlineFunTryBlockInfo);
if (finallyInfo == null) continue;
if (originalTryCatchBlock.getOnlyCopyNotProcess()) {
patched.addAll(clusterBlocks);
continue;
}
instructions.resetLabels();
List<TryCatchBlockNodePosition> tryCatchBlockInlinedInFinally = findTryCatchBlocksInlinedInFinally(finallyInfo);
@@ -138,7 +168,7 @@ public class InternalFinallyBlockInliner {
Label newFinallyEnd = new Label();
Label insertedBlockEnd = new Label();
if (nonLocalReturnType != Type.VOID_TYPE) {
if (nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty()) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ISTORE), nextTempNonLocalVarIndex);
}
finallyBlockCopy.visitLabel(newFinallyStart);
@@ -175,7 +205,7 @@ public class InternalFinallyBlockInliner {
}
finallyBlockCopy.visitLabel(newFinallyEnd);
if (nonLocalReturnType != Type.VOID_TYPE) {
if (nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty()) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ILOAD), nextTempNonLocalVarIndex);
nextTempNonLocalVarIndex += nonLocalReturnType.getSize(); //TODO: do more wise indexing
}
@@ -185,15 +215,44 @@ public class InternalFinallyBlockInliner {
//Copying finally body before non-local return instruction
InlineCodegenUtil.insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
nextPrev = updateExceptionTable(coveringTryCatchBlocks, nextPrev, clusterBlocks, newFinallyStart, newFinallyEnd,
tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info);
updateExceptionTable(clusterBlocks, newFinallyStart, newFinallyEnd,
tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info, patched);
}
curIns = nextPrev;
}
curIns = curIns.getPrevious();
while (curIns != null && curIns != nextPrev) {
updateCoveringTryBlocks(coveringTryCatchBlocks, curIns);
curIns = curIns.getPrevious();
}
//curIns = nextPrev;
}
inlineFun.tryCatchBlocks.clear();
for (TryCatchBlockNodeInfo info : inlineFunTryBlockInfo) {
inlineFun.tryCatchBlocks.add(info.getNode());
substitureTryBlockNodes();
}
private void checkCoveringBlocksInvariant(Stack<TryCatchBlockNodeInfo> coveringTryCatchBlocks) {
boolean isWasOnlyLocal = false;
for (TryCatchBlockNodeInfo info : coveringTryCatchBlocks) {
assert !isWasOnlyLocal || info.getOnlyCopyNotProcess();
if (info.getOnlyCopyNotProcess()) {
isWasOnlyLocal = true;
}
}
}
private void checkClusterInvariant(List<TryBlockCluster<TryCatchBlockNodeInfo>> clusters) {
boolean isWasOnlyLocal;
isWasOnlyLocal = false;
for (TryBlockCluster<TryCatchBlockNodeInfo> cluster : clusters) {
TryCatchBlockNodeInfo info = cluster.getBlocks().get(0);
assert !isWasOnlyLocal || info.getOnlyCopyNotProcess();
if (info.getOnlyCopyNotProcess()) {
isWasOnlyLocal = true;
}
}
}
@@ -209,16 +268,14 @@ public class InternalFinallyBlockInliner {
}
@Nullable
private AbstractInsnNode updateExceptionTable(
@NotNull Stack<TryCatchBlockNodeInfo> coveringTryBlocks,
@Nullable AbstractInsnNode nextPrev,
private void updateExceptionTable(
@NotNull List<TryCatchBlockNodeInfo> updatingClusterBlocks,
@NotNull Label newFinallyStart,
@NotNull Label newFinallyEnd,
@NotNull List<TryCatchBlockNodePosition> tryCatchBlockPresentInFinally,
@NotNull Set<LabelNode> labelsInsideFinally,
@NotNull LabelNode insertedBlockEnd
@NotNull LabelNode insertedBlockEnd,
@NotNull List<TryCatchBlockNodeInfo> patched
) {
//copy tryCatchFinallies that totally in finally block
@@ -272,7 +329,7 @@ public class InternalFinallyBlockInliner {
assert Objects.equal(startNode.getType(), endNode.getType()) : "Different handler types : " + startNode.getType() + " " + endNode.getType();
patchTryBlocks((LabelNode) startNode.getStartLabel().getLabel().info, endNode, false);
patchTryBlocks((LabelNode) startNode.getStartLabel().getLabel().info, endNode);
}
}
}
@@ -284,7 +341,7 @@ public class InternalFinallyBlockInliner {
//TODO rewrite to clusters
for (TryCatchBlockNodePosition endBlockPosition : singleCluster.getBlocks()) {
TryCatchBlockNodeInfo endNode = endBlockPosition.getNodeInfo();
patchTryBlocks((LabelNode) insertedBlockEnd.getLabel().info, endNode, true);
patchTryBlocks((LabelNode) insertedBlockEnd.getLabel().info, endNode);
//nextPrev = (AbstractInsnNode) insertedBlockEnd.getLabel().info;
}
@@ -293,33 +350,38 @@ public class InternalFinallyBlockInliner {
}
assert handler2Cluster.isEmpty() : "Unmatched clusters " + handler2Cluster.size();
List<TryCatchBlockNodeInfo > toProcess = new ArrayList<TryCatchBlockNodeInfo >();
toProcess.addAll(patched);
toProcess.addAll(updatingClusterBlocks);
patched.clear();
// Inserted finally shouldn't be handled by corresponding catches,
// so we should split original interval by inserted finally one
for (TryCatchBlockNodeInfo block : updatingClusterBlocks) {
for (TryCatchBlockNodeInfo block : toProcess) {
//update exception mapping
LabelNode oldStartNode = block.getNode().start;
tryBlockStarts.remove(oldStartNode, block);
block.getNode().start = (LabelNode) newFinallyEnd.info;
//tryBlockStarts.put(block.getStartLabel(), block);
tryBlockStarts.remove(oldStartNode, block);
tryBlockStarts.put(block.getStartLabel(), block);
//if (!block.getOnlyCopyNotProcess()) {
patched.add(block);
//}
TryCatchBlockNode additionalTryCatchBlock =
new TryCatchBlockNode(oldStartNode, (LabelNode) newFinallyStart.info, block.getNode().handler, block.getNode().type);
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, false);
TryCatchBlockNodeInfo newInfo = new TryCatchBlockNodeInfo(additionalTryCatchBlock, block.getOnlyCopyNotProcess());
tryBlockStarts.put(additionalTryCatchBlock.start, newInfo);
tryBlockEnds.put(additionalTryCatchBlock.end, newInfo);
inlineFunTryBlockInfo.add(newInfo);
//TODO add assert
nextPrev = additionalTryCatchBlock.end;
coveringTryBlocks.pop();
}
sortTryCatchBlocks(inlineFunTryBlockInfo);
return nextPrev;
}
private void patchTryBlocks(@NotNull LabelNode newStartLabelNode, @NotNull TryCatchBlockNodeInfo endNode, boolean sort) {
private void patchTryBlocks(@NotNull LabelNode newStartLabelNode, @NotNull TryCatchBlockNodeInfo endNode) {
LabelNode oldStart = endNode.getStartLabel();
endNode.getNode().start = newStartLabelNode;
tryBlockStarts.remove(oldStart, endNode);
@@ -355,20 +417,18 @@ public class InternalFinallyBlockInliner {
List<TryCatchBlockNodeInfo> infos = tryBlockStarts.get((LabelNode) curIns);
for (TryCatchBlockNodeInfo startNode : infos) {
if (!startNode.getOnlyCopyNotProcess()) {
TryCatchBlockNodeInfo pop = coveringTryBlocks.pop();
//Temporary disabled cause during patched structure of exceptions changed
//assert startNode == pop : "Wrong try-catch structure " + startNode + " " + pop + " " + infos.size();
}
TryCatchBlockNodeInfo pop = coveringTryBlocks.pop();
//Temporary disabled cause during patched structure of exceptions changed
//assert startNode == pop : "Wrong try-catch structure " + startNode + " " + pop + " " + infos.size();
}
//Reversing list order cause we should pop external block before internal one
// (originally internal blocks goes before external one, such invariant preserved via sortTryCatchBlocks method)
for (TryCatchBlockNodeInfo info : Lists.reverse(tryBlockEnds.get((LabelNode) curIns))) {
if (!info.getOnlyCopyNotProcess()) {
coveringTryBlocks.add(info);
}
coveringTryBlocks.add(info);
}
checkCoveringBlocksInvariant(coveringTryBlocks);
}
private static boolean hasFinallyBlocks(List<TryCatchBlockNodeInfo> inlineFunTryBlockInfo) {
@@ -396,6 +456,15 @@ public class InternalFinallyBlockInliner {
@NotNull TryCatchBlockNodeInfo tryCatchBlock,
@NotNull List<TryCatchBlockNodeInfo> tryCatchBlocks
) {
if (tryCatchBlock.getOnlyCopyNotProcess()) {
AbstractInsnNode start = new LabelNode();
AbstractInsnNode end = new LabelNode();
InsnList insnList = new InsnList();
insnList.add(start);
insnList.add(end);
return new FinallyBlockInfo(start, end);
}
List<TryCatchBlockNodeInfo> sameDefaultHandler = new ArrayList<TryCatchBlockNodeInfo>();
LabelNode defaultHandler = null;
boolean afterStartBlock = false;
@@ -427,7 +496,16 @@ public class InternalFinallyBlockInliner {
AbstractInsnNode endFinallyChainExclusive = skipLastGotoIfNeeded(nextIntervalWithSameDefaultHandler.getNode().handler,
nextIntervalWithSameDefaultHandler.getNode().start);
return new FinallyBlockInfo(startFinallyChain.getNext(), endFinallyChainExclusive);
FinallyBlockInfo finallyInfo = new FinallyBlockInfo(startFinallyChain.getNext(), endFinallyChainExclusive);
if (inlineFun.instructions.indexOf(finallyInfo.startIns) > inlineFun.instructions.indexOf(finallyInfo.endInsExclusive)) {
AbstractInsnNode startNode = finallyInfo.endInsExclusive;
AbstractInsnNode stopNode = finallyInfo.startIns;
writeNodes(startNode, stopNode);
throw new AssertionError();
}
return finallyInfo;
}
@NotNull
@@ -470,6 +548,7 @@ public class InternalFinallyBlockInliner {
private List<TryCatchBlockNodePosition> findTryCatchBlocksInlinedInFinally(@NotNull FinallyBlockInfo finallyInfo) {
List<TryCatchBlockNodePosition> result = new ArrayList<TryCatchBlockNodePosition>();
Map<TryCatchBlockNodeInfo, TryCatchBlockNodePosition> processedBlocks = new HashMap<TryCatchBlockNodeInfo, TryCatchBlockNodePosition>();
for (AbstractInsnNode curInstr = finallyInfo.startIns; curInstr != finallyInfo.endInsExclusive; curInstr = curInstr.getNext()) {
if (!(curInstr instanceof LabelNode)) continue;
@@ -503,6 +582,19 @@ public class InternalFinallyBlockInliner {
return result;
}
private void writeNodes(AbstractInsnNode startNode, AbstractInsnNode stopNode) {
Textifier p = new Textifier();
TraceMethodVisitor visitor = new TraceMethodVisitor(p);
while (startNode != stopNode) {
startNode.accept(visitor);
startNode = startNode.getNext();
}
startNode.accept(visitor);
StringWriter out = new StringWriter();
p.print(new PrintWriter(out));
System.out.println(out.toString());
}
private static void substituteReturnValueInFinally(
int nonLocalVarIndex,
@NotNull Type nonLocalReturnType,
@@ -543,5 +635,43 @@ public class InternalFinallyBlockInliner {
}
};
Collections.sort(inlineFunTryBlockInfo, comp);
for (TryCatchBlockNodeInfo info : inlineFunTryBlockInfo) {
TryCatchBlockNode node = info.getNode();
assertNotEmptyTryNode(node);
}
}
private void assertNotEmptyTryNode(TryCatchBlockNode node) {
LabelNode start = node.start;
AbstractInsnNode end = node.end;
while (end != start && end instanceof LabelNode) {
end = end.getPrevious();
}
assert start != end;
}
private static int counter = 0;
private void flushCurrentState(@NotNull AbstractInsnNode curNonLocal) {
substitureTryBlockNodes();
System.out.println( );
System.out.println();
System.out.println("Iteration: " + counter++);
System.out.println("Will process instruction at : " + inlineFun.instructions.indexOf(curNonLocal) + " " + curNonLocal.toString());
String text = getNodeText(inlineFun);
System.out.println(text);
}
private void substitureTryBlockNodes() {
inlineFun.tryCatchBlocks.clear();
for (TryCatchBlockNodeInfo info : inlineFunTryBlockInfo) {
inlineFun.tryCatchBlocks.add(info.getNode());
}
}
private int indexOf(AbstractInsnNode node) {
return inlineFun.instructions.indexOf(node) + 1;
}
}
@@ -0,0 +1,64 @@
import test.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class MyException(message: String) : Exception(message)
class Holder(var value: String) {
public fun plusAssign(s: String?) {
value += s
if (s != "closed") {
value += "->"
}
}
}
class Test() : MCloseable {
val status = Holder("")
private fun jobFun() {
status += "called"
}
fun nonLocalWithExceptionAndFinally(): Holder {
muse {
try {
jobFun()
throw MyException("exception")
}
catch (e: MyException) {
status += e.getMessage()
return status
}
finally {
status += "finally"
}
}
return Holder("fail")
}
override fun close() {
status += "closed"
throw MyException("error")
}
}
fun box() : String {
assertError(1, "called->exception->finally->closed") {
nonLocalWithExceptionAndFinally()
}
return "OK"
}
public fun assertError(index: Int, expected: String, l: Test.()->Unit) {
val testLocal = Test()
try {
testLocal.l()
fail("fail $index: no error")
} catch (e: Exception) {
assertEquals(expected, testLocal.status.value, "failed on $index")
}
}
@@ -0,0 +1,15 @@
package test
public trait MCloseable {
public open fun close()
}
public inline fun <T : MCloseable, R> T.muse(block: (T) -> R): R {
try {
return block(this)
} finally {
this.close()
}
}
@@ -0,0 +1,49 @@
import test.*
fun test0(
h: Holder,
throwExternalFinEx1: Boolean = false,
res: String = "Fail"
): String {
try {
val localResult = doCall (
{
h += "OK_NON_LOCAL"
return "OK_NON_LOCAL"
},
{
h += "OK_FINALLY1"
"OK_FINALLY1"
},
{
h += "innerTryBlock"
if (throwExternalFinEx1) {
throw Exception1("EXCEPTION_IN_EXTERNAL_FINALLY")
}
"innerTryBlock"
},
{
h += "CATCHBLOCK"
"CATCHBLOCK"
},
res)
return localResult;
} catch(e: Exception1) {
return e.getMessage()!!
} catch(e: Exception2) {
return e.getMessage()!!
}
}
fun box(): String {
var h = Holder()
var test0 = test0(h, res = "OK")
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock") return "test0_1: ${test0}, holder: ${h.value}"
h = Holder()
test0 = test0(h, throwExternalFinEx1 = true, res = "OK")
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock -> CATCHBLOCK") return "test0_2: ${test0}, holder: ${h.value}"
return "OK"
}
@@ -0,0 +1,36 @@
package test
public class Holder(var value: String = "") {
public fun plusAssign(s: String?) {
if (value.length != 0) {
value += " -> "
}
value += s
}
override fun toString(): String {
return value
}
}
public class Exception1(message: String) : java.lang.RuntimeException(message)
public class Exception2(message: String) : java.lang.RuntimeException(message)
public inline fun doCall(block: ()-> String, finallyBlock: ()-> String,
tryBlock2: ()-> String, catchBlock2: ()-> String, res: String = "Fail") : String {
try {
block()
}
finally {
finallyBlock()
try {
tryBlock2()
} catch (e: Exception) {
catchBlock2()
}
}
return res
}
@@ -0,0 +1,28 @@
inline fun test(s: ()->Int): Int {
var i = 0;
i = s()
try {
i = i + 10
} finally {
return i
}
}
fun box() : String {
var p: Int = 1
test {
try {
p = 1
return "OK" //finally from inline fun doen't split this try
} catch(e: Exception) {
p = -1;
p
} finally {
p++
}
}
return "fail"
}
// 10 TRYCATCHBLOCK
@@ -0,0 +1,55 @@
inline fun test(s: ()->Int): Int {
var i = 0;
try {
i = s()
i = i + 10
} finally {
return i
}
}
fun box() : String {
var p: Int = 1
test {
try {
p = 1
return "OK" //finally from inline fun doen't split this try
} catch(e: Exception) {
p = -1;
p
} finally {
p++
}
}
return "fail"
}
// maybe we shouldinline fun test(s: ()->Int): Int {
var i = 0;
try {
i = s()
i = i + 10
} finally {
return i
}
}
fun box() : String {
var p: Int = 1
test {
try {
p = 1
return "OK" //finally from inline fun doen't split this try
} catch(e: Exception) {
p = -1;
p
} finally {
p++
}
}
return "fail"
}
check test data
// 13 TRYCATCHBLOCK
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/bytecodeText")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.StoreStackBeforeInline.class, BytecodeTextTestGenerated.When.class, BytecodeTextTestGenerated.WhenEnumOptimization.class, BytecodeTextTestGenerated.WhenStringOptimization.class})
@InnerTestClasses({BytecodeTextTestGenerated.BoxingOptimization.class, BytecodeTextTestGenerated.Constants.class, BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Inline.class, BytecodeTextTestGenerated.Statements.class, BytecodeTextTestGenerated.StoreStackBeforeInline.class, BytecodeTextTestGenerated.When.class, BytecodeTextTestGenerated.WhenEnumOptimization.class, BytecodeTextTestGenerated.WhenStringOptimization.class})
@RunWith(JUnit3RunnerWithInners.class)
public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
@TestMetadata("accessorForProtected.kt")
@@ -322,6 +322,27 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractBytecodeTextTest {
public void testAllFilesPresentInInline() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("notSplitedExceptionTable.kt")
public void testNotSplitedExceptionTable() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/notSplitedExceptionTable.kt");
doTest(fileName);
}
@TestMetadata("splitedExceptionTable.kt")
public void testSplitedExceptionTable() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/splitedExceptionTable.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/statements")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -507,6 +507,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("exceptionInFinally.1.kt")
public void testExceptionInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/exceptionInFinally.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("forInFinally.1.kt")
public void testForInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/forInFinally.1.kt");
@@ -578,6 +584,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("tryCatchInFinally.1.kt")
public void testTryCatchInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/tryCatchInFinally.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
}
}
}
@@ -507,6 +507,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("exceptionInFinally.1.kt")
public void testExceptionInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/exceptionInFinally.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("forInFinally.1.kt")
public void testForInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/forInFinally.1.kt");
@@ -578,6 +584,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/throwInFinally.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("tryCatchInFinally.1.kt")
public void testTryCatchInFinally() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/exceptionTable/tryCatchInFinally.1.kt");
doBoxTestWithInlineCheck(fileName);
}
}
}
}