[JVM_IR] Generate line numbers and nops for init blocks.
This seems to be what JVM does and it allows you to set a breakpoint on the init line.
This commit is contained in:
+12
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER
|
import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.SYNTHESIZED_INIT_BLOCK
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
||||||
@@ -324,15 +325,25 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, data: BlockInfo): PromisedValue {
|
override fun visitBlock(expression: IrBlock, data: BlockInfo): PromisedValue {
|
||||||
assert(expression !is IrReturnableBlock) { "unlowered returnable block: ${expression.dump()}" }
|
assert(expression !is IrReturnableBlock) { "unlowered returnable block: ${expression.dump()}" }
|
||||||
|
val isSynthesizedInitBlock = expression.origin == SYNTHESIZED_INIT_BLOCK
|
||||||
|
if (isSynthesizedInitBlock) {
|
||||||
|
expression.markLineNumber(startOffset = true)
|
||||||
|
mv.nop()
|
||||||
|
}
|
||||||
if (expression.isTransparentScope)
|
if (expression.isTransparentScope)
|
||||||
return super.visitBlock(expression, data)
|
return super.visitBlock(expression, data)
|
||||||
val info = BlockInfo(data)
|
val info = BlockInfo(data)
|
||||||
// Force materialization to avoid reading from out-of-scope variables.
|
// Force materialization to avoid reading from out-of-scope variables.
|
||||||
return super.visitBlock(expression, info).materialized().also {
|
val value = super.visitBlock(expression, info).materialized().also {
|
||||||
if (info.variables.isNotEmpty()) {
|
if (info.variables.isNotEmpty()) {
|
||||||
writeLocalVariablesInTable(info, markNewLabel())
|
writeLocalVariablesInTable(info, markNewLabel())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isSynthesizedInitBlock) {
|
||||||
|
expression.markLineNumber(startOffset = false)
|
||||||
|
mv.nop()
|
||||||
|
}
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrVariable.isVisibleInLVT: Boolean
|
private val IrVariable.isVisibleInLVT: Boolean
|
||||||
|
|||||||
+14
-4
@@ -51,10 +51,8 @@ fun box() {
|
|||||||
Zoo()
|
Zoo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
// JVM_IR has an extra step back to the line of the class
|
||||||
// The JVM_IR does not generate code that will break on the line
|
// declaration for the return in the constructor.
|
||||||
// containing the `init`, nor the exit from the `init`. It only
|
|
||||||
// contains lines for the contents of the init blocks.
|
|
||||||
|
|
||||||
// LINENUMBERS
|
// LINENUMBERS
|
||||||
// test.kt:48 box
|
// test.kt:48 box
|
||||||
@@ -64,6 +62,9 @@ fun box() {
|
|||||||
// test.kt:45 x
|
// test.kt:45 x
|
||||||
// test.kt:7 <init>
|
// test.kt:7 <init>
|
||||||
// test.kt:8 <init>
|
// test.kt:8 <init>
|
||||||
|
// LINENUMBERS JVM_IR
|
||||||
|
// test.kt:3 <init>
|
||||||
|
// LINENUMBERS
|
||||||
// test.kt:48 box
|
// test.kt:48 box
|
||||||
// test.kt:49 box
|
// test.kt:49 box
|
||||||
// test.kt:11 <init>
|
// test.kt:11 <init>
|
||||||
@@ -73,6 +74,9 @@ fun box() {
|
|||||||
// test.kt:16 <init>
|
// test.kt:16 <init>
|
||||||
// test.kt:17 <init>
|
// test.kt:17 <init>
|
||||||
// test.kt:18 <init>
|
// test.kt:18 <init>
|
||||||
|
// LINENUMBERS JVM_IR
|
||||||
|
// test.kt:11 <init>
|
||||||
|
// LINENUMBERS
|
||||||
// test.kt:49 box
|
// test.kt:49 box
|
||||||
// test.kt:50 box
|
// test.kt:50 box
|
||||||
// test.kt:21 <init>
|
// test.kt:21 <init>
|
||||||
@@ -85,6 +89,9 @@ fun box() {
|
|||||||
// test.kt:28 <init>
|
// test.kt:28 <init>
|
||||||
// test.kt:29 <init>
|
// test.kt:29 <init>
|
||||||
// test.kt:30 <init>
|
// test.kt:30 <init>
|
||||||
|
// LINENUMBERS JVM_IR
|
||||||
|
// test.kt:21 <init>
|
||||||
|
// LINENUMBERS
|
||||||
// test.kt:50 box
|
// test.kt:50 box
|
||||||
// test.kt:51 box
|
// test.kt:51 box
|
||||||
// test.kt:33 <init>
|
// test.kt:33 <init>
|
||||||
@@ -94,5 +101,8 @@ fun box() {
|
|||||||
// test.kt:39 <init>
|
// test.kt:39 <init>
|
||||||
// test.kt:40 <init>
|
// test.kt:40 <init>
|
||||||
// test.kt:42 <init>
|
// test.kt:42 <init>
|
||||||
|
// LINENUMBERS JVM_IR
|
||||||
|
// test.kt:33 <init>
|
||||||
|
// LINENUMBERS
|
||||||
// test.kt:51 box
|
// test.kt:51 box
|
||||||
// test.kt:52 box
|
// test.kt:52 box
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
class A {
|
||||||
|
companion object {
|
||||||
|
val s: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
s = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
val x = x()
|
||||||
|
|
||||||
|
init { val a = 32 }
|
||||||
|
|
||||||
|
init {
|
||||||
|
val b = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
init
|
||||||
|
{
|
||||||
|
val c = 43
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun x() = ""
|
||||||
|
|
||||||
|
fun box() {
|
||||||
|
A.x
|
||||||
|
A.s
|
||||||
|
}
|
||||||
|
|
||||||
|
// JVM backend has extra steps for getX and getS.
|
||||||
|
|
||||||
|
// TODO: since these tests operate as step-into, we do not get any steps
|
||||||
|
// in the <clinit> for the companion object. Maybe extend the test infrastructure
|
||||||
|
// with directives to set break points in order to test this.
|
||||||
|
|
||||||
|
// LINENUMBERS
|
||||||
|
// test.kt:29 box
|
||||||
|
// test.kt:11 getX
|
||||||
|
// LINENUMBERS JVM
|
||||||
|
// test.kt:11 getX
|
||||||
|
// LINENUMBERS
|
||||||
|
// test.kt:29 box
|
||||||
|
// test.kt:30 box
|
||||||
|
// test.kt:5 getS
|
||||||
|
// LINENUMBERS JVM
|
||||||
|
// test.kt:5 getS
|
||||||
|
// LINENUMBERS
|
||||||
|
// test.kt:30 box
|
||||||
|
// test.kt:31 box
|
||||||
+6
@@ -193,6 +193,12 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
|
|||||||
runTest("compiler/testData/debug/stepping/initBlocks.kt");
|
runTest("compiler/testData/debug/stepping/initBlocks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("initBlocksCompanion.kt")
|
||||||
|
public void testInitBlocksCompanion() throws Exception {
|
||||||
|
runTest("compiler/testData/debug/stepping/initBlocksCompanion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inlineCallableReference.kt")
|
@TestMetadata("inlineCallableReference.kt")
|
||||||
public void testInlineCallableReference() throws Exception {
|
public void testInlineCallableReference() throws Exception {
|
||||||
|
|||||||
+6
@@ -193,6 +193,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
|
|||||||
runTest("compiler/testData/debug/stepping/initBlocks.kt");
|
runTest("compiler/testData/debug/stepping/initBlocks.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("initBlocksCompanion.kt")
|
||||||
|
public void testInitBlocksCompanion() throws Exception {
|
||||||
|
runTest("compiler/testData/debug/stepping/initBlocksCompanion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("inlineCallableReference.kt")
|
@TestMetadata("inlineCallableReference.kt")
|
||||||
public void testInlineCallableReference() throws Exception {
|
public void testInlineCallableReference() throws Exception {
|
||||||
|
|||||||
+6
@@ -25,6 +25,8 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa
|
|||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
CHECKCAST
|
CHECKCAST
|
||||||
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
||||||
|
LABEL (L1)
|
||||||
|
LINENUMBER (13)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,6 +334,8 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ
|
|||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
CHECKCAST
|
CHECKCAST
|
||||||
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
||||||
|
LABEL (L1)
|
||||||
|
LINENUMBER (10)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,6 +691,8 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in
|
|||||||
ALOAD (0)
|
ALOAD (0)
|
||||||
CHECKCAST
|
CHECKCAST
|
||||||
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
PUTSTATIC (descriptor, Lkotlinx/serialization/SerialDescriptor;)
|
||||||
|
LABEL (L1)
|
||||||
|
LINENUMBER (7)
|
||||||
RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user