Remove external finally block interval on splitting during inline
#KT-20433 Fixed
This commit is contained in:
+10
-3
@@ -22,8 +22,8 @@ import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import java.util.*
|
||||
|
||||
abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
||||
val tryBlocksMetaInfo: IntervalMetaInfo<TryCatchBlockNodeInfo> = IntervalMetaInfo()
|
||||
val localVarsMetaInfo: IntervalMetaInfo<LocalVarNodeWrapper> = IntervalMetaInfo()
|
||||
val tryBlocksMetaInfo: IntervalMetaInfo<TryCatchBlockNodeInfo> = IntervalMetaInfo(this)
|
||||
val localVarsMetaInfo: IntervalMetaInfo<LocalVarNodeWrapper> = IntervalMetaInfo(this)
|
||||
|
||||
var nextFreeLocalIndex: Int = parameterSize
|
||||
private set
|
||||
@@ -84,24 +84,27 @@ abstract class CoveringTryCatchNodeProcessor(parameterSize: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
class IntervalMetaInfo<T : SplittableInterval<T>> {
|
||||
class IntervalMetaInfo<T : SplittableInterval<T>>(private val processor: CoveringTryCatchNodeProcessor) {
|
||||
val intervalStarts = LinkedListMultimap.create<LabelNode, T>()
|
||||
val intervalEnds = LinkedListMultimap.create<LabelNode, T>()
|
||||
val allIntervals: ArrayList<T> = arrayListOf()
|
||||
val currentIntervals: MutableSet<T> = linkedSetOf()
|
||||
|
||||
fun addNewInterval(newInfo: T) {
|
||||
newInfo.verify(processor)
|
||||
intervalStarts.put(newInfo.startLabel, newInfo)
|
||||
intervalEnds.put(newInfo.endLabel, newInfo)
|
||||
allIntervals.add(newInfo)
|
||||
}
|
||||
|
||||
private fun remapStartLabel(oldStart: LabelNode, remapped: T) {
|
||||
remapped.verify(processor)
|
||||
intervalStarts.remove(oldStart, remapped)
|
||||
intervalStarts.put(remapped.startLabel, remapped)
|
||||
}
|
||||
|
||||
private fun remapEndLabel(oldEnd: LabelNode, remapped: T) {
|
||||
remapped.verify(processor)
|
||||
intervalEnds.remove(oldEnd, remapped)
|
||||
intervalEnds.put(remapped.endLabel, remapped)
|
||||
}
|
||||
@@ -110,6 +113,10 @@ class IntervalMetaInfo<T : SplittableInterval<T>> {
|
||||
return currentIntervals.map { split(it, by, keepStart) }
|
||||
}
|
||||
|
||||
fun splitAndRemoveCurrentIntervals(by: Interval, keepStart: Boolean) {
|
||||
currentIntervals.map { splitAndRemoveInterval(it, by, keepStart) }
|
||||
}
|
||||
|
||||
fun processCurrent(curIns: LabelNode, directOrder: Boolean) {
|
||||
getInterval(curIns, directOrder).forEach {
|
||||
val added = currentIntervals.add(it)
|
||||
|
||||
@@ -366,7 +366,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
insertNodeBefore(finallyNode, intoNode, curInstr)
|
||||
|
||||
val splitBy = SimpleInterval(start.info as LabelNode, extension.finallyIntervalEnd)
|
||||
processor.tryBlocksMetaInfo.splitCurrentIntervals(splitBy, true)
|
||||
processor.tryBlocksMetaInfo.splitAndRemoveCurrentIntervals(splitBy, true)
|
||||
|
||||
//processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode
|
||||
|
||||
@@ -35,6 +36,12 @@ interface Interval {
|
||||
|
||||
/*note that some intervals are mutable */
|
||||
fun isEmpty(): Boolean = startLabel == endLabel
|
||||
|
||||
fun verify(processor: CoveringTryCatchNodeProcessor) {
|
||||
assert (processor.instructionIndex(startLabel) <= processor.instructionIndex(endLabel)) {
|
||||
"Try block body starts after body end: ${processor.instructionIndex(startLabel)} > ${processor.instructionIndex(endLabel)}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface SplittableInterval<out T : Interval> : Interval {
|
||||
@@ -77,6 +84,9 @@ class TryCatchBlockNodeInfo(
|
||||
}
|
||||
}
|
||||
|
||||
val TryCatchBlockNodeInfo.bodyInstuctions
|
||||
get() = InsnSequence(startLabel, endLabel)
|
||||
|
||||
class TryCatchBlockNodePosition(
|
||||
val nodeInfo: TryCatchBlockNodeInfo,
|
||||
var position: TryCatchPosition
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// FILE: 1.kt
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
public inline fun <T, R> T.mylet(block: (T) -> R): R {
|
||||
return block(this)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
var message = ""
|
||||
|
||||
fun foo(root: String): String {
|
||||
try {
|
||||
return root.let { _ ->
|
||||
try {
|
||||
if (!random()) {
|
||||
return root
|
||||
}
|
||||
return "fail $root"
|
||||
} catch (e: Exception) {
|
||||
message += "${e.message} "
|
||||
}
|
||||
"fail"
|
||||
}
|
||||
} finally {
|
||||
message += "Finally block"
|
||||
}
|
||||
}
|
||||
|
||||
var exception = false
|
||||
|
||||
fun random() = if (exception) error("Exception") else false
|
||||
|
||||
fun box(): String {
|
||||
var okResult = foo("OK")
|
||||
if (okResult != "OK") return "fail 1: $okResult"
|
||||
if (message != "Finally block") return "fail 2: $message"
|
||||
|
||||
message = ""
|
||||
exception = true
|
||||
if (foo("OK") != "fail") return "fail 3: ${foo("OK")}"
|
||||
if (message != "Exception Finally block" ) return "fail 4: $message"
|
||||
|
||||
return okResult
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// FILE: 1.kt
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
public inline fun <T, R> T.mylet(block: (T) -> R): R {
|
||||
return block(this)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
var message = ""
|
||||
|
||||
fun foo(root: String): String {
|
||||
try {
|
||||
return root.let { _ ->
|
||||
try {
|
||||
if (!random()) {
|
||||
return root
|
||||
}
|
||||
return "fail $root"
|
||||
} catch (e: Exception) {
|
||||
message += "Exception $e"
|
||||
}
|
||||
"fail"
|
||||
}
|
||||
} finally {
|
||||
message += "Finally block"
|
||||
}
|
||||
}
|
||||
|
||||
var fail = false
|
||||
|
||||
fun random() = fail
|
||||
|
||||
fun box(): String {
|
||||
var okResult = foo("OK")
|
||||
if (okResult != "OK") return "fail 1: $okResult"
|
||||
if (message != "Finally block") return "fail 2: $message"
|
||||
|
||||
message = ""
|
||||
fail = true
|
||||
if (foo("OK") != "fail OK") return "fail 3: ${foo("OK")}"
|
||||
if (message != "Finally block" ) return "fail 4: $message"
|
||||
|
||||
return okResult
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// FILE: 1.kt
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
public inline fun <T, R> T.mylet(block: (T) -> R): R {
|
||||
return block(this)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
var message = ""
|
||||
|
||||
fun foo(root: String) {
|
||||
try {
|
||||
return root.let { _ ->
|
||||
try {
|
||||
if (!random()) {
|
||||
message += root
|
||||
return
|
||||
}
|
||||
message += "fail $root"
|
||||
} catch (e: Exception) {
|
||||
message += "Exception $e"
|
||||
}
|
||||
"fail"
|
||||
}
|
||||
} finally {
|
||||
message += " Finally block"
|
||||
}
|
||||
}
|
||||
|
||||
var fail = false
|
||||
|
||||
fun random() = fail
|
||||
|
||||
fun box(): String {
|
||||
foo("OK")
|
||||
if (message != "OK Finally block") return "fail 1: $message"
|
||||
|
||||
message = ""
|
||||
fail = true
|
||||
foo("OK")
|
||||
if (message != "fail OK Finally block" ) return "fail 2: $message"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// FILE: 1.kt
|
||||
//WITH_RUNTIME
|
||||
package test
|
||||
|
||||
public inline fun <T, R> T.mylet(block: (T) -> R): R {
|
||||
return block(this)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
var message = ""
|
||||
|
||||
fun foo(root: String) {
|
||||
try {
|
||||
root.let { _ ->
|
||||
try {
|
||||
if (!random()) {
|
||||
message += root
|
||||
return
|
||||
}
|
||||
message += "fail $root"
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
message += "${e.message}"
|
||||
}
|
||||
"fail"
|
||||
}
|
||||
} finally {
|
||||
message += " Finally block"
|
||||
}
|
||||
}
|
||||
|
||||
var exception = false
|
||||
|
||||
fun random() = if (exception) error("Exception") else false
|
||||
|
||||
fun box(): String {
|
||||
foo("OK")
|
||||
if (message != "OK Finally block") return "fail 1: $message"
|
||||
|
||||
message = ""
|
||||
exception = true
|
||||
foo("OK")
|
||||
if (message != "Exception Finally block" ) return "fail 2: $message"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+24
@@ -1876,6 +1876,30 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433.kt")
|
||||
public void testKt20433() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2.kt")
|
||||
public void testKt20433_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2_void.kt")
|
||||
public void testKt20433_2_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_void.kt")
|
||||
public void testKt20433_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6956.kt")
|
||||
public void testKt6956() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");
|
||||
|
||||
+24
@@ -1876,6 +1876,30 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433.kt")
|
||||
public void testKt20433() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2.kt")
|
||||
public void testKt20433_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2_void.kt")
|
||||
public void testKt20433_2_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_void.kt")
|
||||
public void testKt20433_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6956.kt")
|
||||
public void testKt6956() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");
|
||||
|
||||
@@ -1876,6 +1876,30 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433.kt")
|
||||
public void testKt20433() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2.kt")
|
||||
public void testKt20433_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2_void.kt")
|
||||
public void testKt20433_2_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_void.kt")
|
||||
public void testKt20433_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6956.kt")
|
||||
public void testKt6956() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");
|
||||
|
||||
+24
@@ -1876,6 +1876,30 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433.kt")
|
||||
public void testKt20433() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2.kt")
|
||||
public void testKt20433_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2_void.kt")
|
||||
public void testKt20433_2_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_void.kt")
|
||||
public void testKt20433_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6956.kt")
|
||||
public void testKt6956() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");
|
||||
|
||||
+24
@@ -143,6 +143,30 @@ public class NonLocalReturnsTestGenerated extends AbstractNonLocalReturnsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433.kt")
|
||||
public void testKt20433() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2.kt")
|
||||
public void testKt20433_2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_2_void.kt")
|
||||
public void testKt20433_2_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_2_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt20433_void.kt")
|
||||
public void testKt20433_void() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt20433_void.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6956.kt")
|
||||
public void testKt6956() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt6956.kt");
|
||||
|
||||
Reference in New Issue
Block a user