Merge two consequent records in LVT
Otherwise, atomicfu will be unable to transform atomic variable usages.
This commit is contained in:
+20
-5
@@ -1239,11 +1239,26 @@ private fun updateLvtAccordingToLiveness(method: MethodNode, isForNamedFunction:
|
|||||||
val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue
|
val endLabel = insn as? LabelNode ?: insn.findNextOrNull { it is LabelNode } as? LabelNode ?: continue
|
||||||
// startLabel can be null in case of parameters
|
// startLabel can be null in case of parameters
|
||||||
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
|
@Suppress("NAME_SHADOWING") val startLabel = startLabel ?: lvtRecord.start
|
||||||
// No LINENUMBER in range -> no way to put a breakpoint -> do not bother adding a record
|
var recordToExtend: LocalVariableNode? = null
|
||||||
if (InsnSequence(startLabel, endLabel).none { it is LineNumberNode }) continue
|
for (record in method.localVariables) {
|
||||||
method.localVariables.add(
|
if (record.name == lvtRecord.name &&
|
||||||
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
record.desc == lvtRecord.desc &&
|
||||||
)
|
record.signature == lvtRecord.signature &&
|
||||||
|
record.index == lvtRecord.index
|
||||||
|
) {
|
||||||
|
if (InsnSequence(record.end, startLabel).none { isBeforeSuspendMarker(it) }) {
|
||||||
|
recordToExtend = record
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (recordToExtend != null) {
|
||||||
|
recordToExtend.end = endLabel
|
||||||
|
} else {
|
||||||
|
method.localVariables.add(
|
||||||
|
LocalVariableNode(lvtRecord.name, lvtRecord.desc, lvtRecord.signature, startLabel, endLabel, lvtRecord.index)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+5
@@ -1431,6 +1431,11 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("mergeLvt.kt")
|
||||||
|
public void testMergeLvt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nonLocalReturn.kt")
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
public void testNonLocalReturn() throws Exception {
|
public void testNonLocalReturn() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
||||||
|
|||||||
+1
@@ -18,6 +18,7 @@ suspend fun foo(data: Data, body: suspend (Data) -> Unit) {
|
|||||||
// METHOD : DataClassKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
// METHOD : DataClassKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
|
// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LData; INDEX=2
|
||||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
||||||
// VARIABLE : NAME=y_param TYPE=I INDEX=4
|
// VARIABLE : NAME=y_param TYPE=I INDEX=4
|
||||||
// VARIABLE : NAME=this TYPE=LDataClassKt$test$2; INDEX=0
|
// VARIABLE : NAME=this TYPE=LDataClassKt$test$2; INDEX=0
|
||||||
|
|||||||
Vendored
+1
@@ -28,6 +28,7 @@ suspend fun test() = B.bar()
|
|||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// METHOD : ExtensionComponentsKt$bar$3.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
// METHOD : ExtensionComponentsKt$bar$3.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
// VARIABLE : NAME=$dstr$x_param$y_param$z_param TYPE=LA; INDEX=2
|
||||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
||||||
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4
|
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4
|
||||||
// VARIABLE : NAME=z_param TYPE=I INDEX=5
|
// VARIABLE : NAME=z_param TYPE=I INDEX=5
|
||||||
|
|||||||
+1
@@ -15,6 +15,7 @@ suspend fun test() = foo(A("OK", 1)) { (x_param, y_param) ->
|
|||||||
// METHOD : GenericKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
// METHOD : GenericKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
|
// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=2
|
||||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
||||||
// VARIABLE : NAME=y_param TYPE=I INDEX=4
|
// VARIABLE : NAME=y_param TYPE=I INDEX=4
|
||||||
// VARIABLE : NAME=this TYPE=LGenericKt$test$2; INDEX=0
|
// VARIABLE : NAME=this TYPE=LGenericKt$test$2; INDEX=0
|
||||||
|
|||||||
+1
@@ -15,6 +15,7 @@ suspend fun test() = foo(A("O", "K")) { i_param, (x_param, y_param), v_param ->
|
|||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// VARIABLE : NAME=i_param TYPE=I INDEX=2
|
// VARIABLE : NAME=i_param TYPE=I INDEX=2
|
||||||
|
// VARIABLE : NAME=$dstr$x_param$y_param TYPE=LA; INDEX=3
|
||||||
// VARIABLE : NAME=v_param TYPE=Ljava/lang/String; INDEX=4
|
// VARIABLE : NAME=v_param TYPE=Ljava/lang/String; INDEX=4
|
||||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=5
|
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=5
|
||||||
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=6
|
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=6
|
||||||
|
|||||||
+1
@@ -20,6 +20,7 @@ suspend fun foo(data: Data, body: suspend Long.(String, Data, Int) -> Unit) {
|
|||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
// VARIABLE : NAME=$this$foo TYPE=J INDEX=2
|
// VARIABLE : NAME=$this$foo TYPE=J INDEX=2
|
||||||
// VARIABLE : NAME=str TYPE=Ljava/lang/String; INDEX=4
|
// VARIABLE : NAME=str TYPE=Ljava/lang/String; INDEX=4
|
||||||
|
// VARIABLE : NAME=$dstr$x$_u24__u24$z TYPE=LData; INDEX=5
|
||||||
// VARIABLE : NAME=i TYPE=I INDEX=6
|
// VARIABLE : NAME=i TYPE=I INDEX=6
|
||||||
// VARIABLE : NAME=x TYPE=Ljava/lang/String; INDEX=7
|
// VARIABLE : NAME=x TYPE=Ljava/lang/String; INDEX=7
|
||||||
// VARIABLE : NAME=z TYPE=I INDEX=8
|
// VARIABLE : NAME=z TYPE=I INDEX=8
|
||||||
|
|||||||
+1
@@ -18,6 +18,7 @@ suspend fun test() = foo(A()) { (x_param, _, y_param) ->
|
|||||||
// METHOD : UnderscoreNamesKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
// METHOD : UnderscoreNamesKt$test$2.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
|
|
||||||
// JVM_TEMPLATES
|
// JVM_TEMPLATES
|
||||||
|
// VARIABLE : NAME=$dstr$x_param$_u24__u24$y_param TYPE=LA; INDEX=2
|
||||||
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
// VARIABLE : NAME=x_param TYPE=Ljava/lang/String; INDEX=3
|
||||||
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4
|
// VARIABLE : NAME=y_param TYPE=Ljava/lang/String; INDEX=4
|
||||||
// VARIABLE : NAME=this TYPE=LUnderscoreNamesKt$test$2; INDEX=0
|
// VARIABLE : NAME=this TYPE=LUnderscoreNamesKt$test$2; INDEX=0
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
class AtomicInt(val value: Int)
|
||||||
|
|
||||||
|
fun atomic(i: Int) = AtomicInt(i)
|
||||||
|
|
||||||
|
class MyBlockingAdapter() {
|
||||||
|
private val state = atomic(0)
|
||||||
|
private val a = 77
|
||||||
|
suspend fun foo() {
|
||||||
|
val a = suspendBar()
|
||||||
|
}
|
||||||
|
private inline fun AtomicInt.extensionFun() {
|
||||||
|
if (a == 77) throw IllegalStateException("AAAAAAAAAAAA")
|
||||||
|
value
|
||||||
|
}
|
||||||
|
private suspend inline fun suspendBar() {
|
||||||
|
state.extensionFun()
|
||||||
|
suspendCoroutineUninterceptedOrReturn<Any?> { ucont ->
|
||||||
|
COROUTINE_SUSPENDED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 LOCALVARIABLE \$this\$extensionFun\$iv\$iv LAtomicInt;
|
||||||
+2
-2
@@ -42,8 +42,8 @@ fun box(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1 LOCALVARIABLE i Ljava/lang/String; L.* 3
|
// 1 LOCALVARIABLE i Ljava/lang/String; L.* 3
|
||||||
// From liveness point of view, 's' is dead between 'println' and 's == "OK"', thus the range is split
|
// We merge LVT records for two consequent branches.
|
||||||
// 2 LOCALVARIABLE s Ljava/lang/String; L.* 3
|
// 1 LOCALVARIABLE s Ljava/lang/String; L.* 3
|
||||||
// 1 PUTFIELD VarValueConflictsWithTableSameSortKt\$box\$1.L\$0 : Ljava/lang/Object;
|
// 1 PUTFIELD VarValueConflictsWithTableSameSortKt\$box\$1.L\$0 : Ljava/lang/Object;
|
||||||
/* 1 load in the catch (e: Throwable) { throw e } block which is implicitly wrapped around try/finally */
|
/* 1 load in the catch (e: Throwable) { throw e } block which is implicitly wrapped around try/finally */
|
||||||
// 1 ALOAD 3\s+ATHROW
|
// 1 ALOAD 3\s+ATHROW
|
||||||
|
|||||||
@@ -1421,6 +1421,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("mergeLvt.kt")
|
||||||
|
public void testMergeLvt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nonLocalReturn.kt")
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
public void testNonLocalReturn() throws Exception {
|
public void testNonLocalReturn() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
||||||
|
|||||||
+5
@@ -1431,6 +1431,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/effectivelyInlineOnly.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("mergeLvt.kt")
|
||||||
|
public void testMergeLvt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/mergeLvt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nonLocalReturn.kt")
|
@TestMetadata("nonLocalReturn.kt")
|
||||||
public void testNonLocalReturn() throws Exception {
|
public void testNonLocalReturn() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
runTest("compiler/testData/codegen/bytecodeText/coroutines/nonLocalReturn.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user