From ac742123fd32ae9bc8039d9d58613e1c0c5d2416 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Tue, 15 Sep 2020 11:53:36 +0200 Subject: [PATCH] [JVM_IR] Generate line numbers in synthetic bridges. The current backend does that for some bridges. We do it consistently for all bridges. The line number used differs. For the JVM_IR backend, we use the line number of the class to which the bridge is added. For the JVM backend, that does not appear to be the case for bridges in lambdas. I prefer the line number for a lambda invoke bridge to be the line for the lambda instead os some surrounding class. --- .../backend/jvm/lower/BridgeLowering.kt | 8 +++-- .../jvm/lower/SyntheticAccessorLowering.kt | 26 +++++++++------ .../testData/debug/stepping/classObject.kt | 13 -------- .../debug/stepping/initBlocksCompanion.kt | 6 ---- .../debug/stepping/namedCallableReference.kt | 9 ++++++ .../functionCallStoredToVariable.ir.out | 21 ++++++++++++ .../testData/stepping/stepInto/accessors.out | 1 - .../stepping/stepInto/syntheticMethods.ir.out | 32 +++++++++++++++++++ .../stepping/stepInto/syntheticMethods.out | 1 - .../stepping/stepOut/fwBackingField.ir.out | 1 - 10 files changed, 84 insertions(+), 34 deletions(-) create mode 100644 idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionCallStoredToVariable.ir.out create mode 100644 idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.ir.out diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 233505d1b56..d6d58556413 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -385,6 +385,8 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass private fun IrClass.addBridge(bridge: Bridge, target: IrSimpleFunction): IrSimpleFunction = addFunction { + startOffset = this@addBridge.startOffset + endOffset = this@addBridge.startOffset modality = Modality.OPEN origin = IrDeclarationOrigin.BRIDGE // Internal functions can be overridden by non-internal functions, which changes their names since the names of internal @@ -396,7 +398,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass isSuspend = bridge.overridden.isSuspend }.apply { copyParametersWithErasure(this@addBridge, bridge.overridden) - body = context.createIrBuilder(symbol).run { irExprBody(delegatingCall(this@apply, target)) } + body = context.createIrBuilder(symbol, startOffset, endOffset).run { irExprBody(delegatingCall(this@apply, target)) } // The generated bridge method overrides all of the symbols which were overridden by its overrides. // This is technically wrong, but it's necessary to generate a method which maps to the same signature. @@ -411,6 +413,8 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass private fun IrClass.addSpecialBridge(specialBridge: SpecialBridge, target: IrSimpleFunction): IrSimpleFunction = addFunction { + startOffset = this@addSpecialBridge.startOffset + endOffset = this@addSpecialBridge.startOffset modality = if (specialBridge.isFinal) Modality.FINAL else Modality.OPEN origin = if (specialBridge.isSynthetic) IrDeclarationOrigin.BRIDGE else IrDeclarationOrigin.BRIDGE_SPECIAL name = Name.identifier(specialBridge.signature.name) @@ -423,7 +427,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass specialBridge.substitutedParameterTypes ) - body = context.createIrBuilder(symbol).irBlockBody { + body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody { specialBridge.methodInfo?.let { info -> valueParameters.take(info.argumentsToCheck).forEach { +parameterTypeCheck(it, target.valueParameters[it.index].type, info.defaultValueGenerator(this@apply)) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index e4a1dd4e3da..932db9ad6f4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -15,7 +15,6 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters -import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.Modality @@ -292,6 +291,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle val source = this return factory.buildFun { + startOffset = parent.startOffset + endOffset = parent.startOffset origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = source.accessorName(expression.superQualifierSymbol) visibility = DescriptorVisibilities.PUBLIC @@ -306,7 +307,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle accessor.returnType = source.returnType.remapTypeParameters(source, accessor) accessor.body = IrExpressionBodyImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.startOffset, createSimpleFunctionCall(accessor, source.symbol, expression.superQualifierSymbol) ) } @@ -314,7 +315,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun createSimpleFunctionCall(accessor: IrFunction, targetSymbol: IrSimpleFunctionSymbol, superQualifierSymbol: IrClassSymbol?) = IrCallImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, + accessor.endOffset, accessor.returnType, targetSymbol, targetSymbol.owner.typeParameters.size, superQualifierSymbol = superQualifierSymbol @@ -324,6 +326,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol = context.irFactory.buildFun { + startOffset = parent.startOffset + endOffset = parent.startOffset origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = fieldSymbol.owner.accessorNameForGetter() visibility = DescriptorVisibilities.PUBLIC @@ -346,11 +350,11 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun createAccessorBodyForGetter(targetField: IrField, accessor: IrSimpleFunction): IrBody { val maybeDispatchReceiver = if (targetField.isStatic) null - else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol) + else IrGetValueImpl(accessor.startOffset, accessor.endOffset, accessor.valueParameters[0].symbol) return IrExpressionBodyImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.endOffset, IrGetFieldImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.endOffset, targetField.symbol, targetField.type, maybeDispatchReceiver @@ -360,6 +364,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol = context.irFactory.buildFun { + startOffset = parent.startOffset + endOffset = parent.startOffset origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = fieldSymbol.owner.accessorNameForSetter() visibility = DescriptorVisibilities.PUBLIC @@ -384,15 +390,15 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun createAccessorBodyForSetter(targetField: IrField, accessor: IrSimpleFunction): IrBody { val maybeDispatchReceiver = if (targetField.isStatic) null - else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol) + else IrGetValueImpl(accessor.startOffset, accessor.endOffset, accessor.valueParameters[0].symbol) val value = IrGetValueImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.endOffset, accessor.valueParameters[if (targetField.isStatic) 0 else 1].symbol ) return IrExpressionBodyImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.endOffset, IrSetFieldImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, + accessor.startOffset, accessor.endOffset, targetField.symbol, maybeDispatchReceiver, value, diff --git a/compiler/testData/debug/stepping/classObject.kt b/compiler/testData/debug/stepping/classObject.kt index 3a93dc6653f..fd0cdcbc740 100644 --- a/compiler/testData/debug/stepping/classObject.kt +++ b/compiler/testData/debug/stepping/classObject.kt @@ -16,37 +16,24 @@ fun box() { A.foo() } -// The JVM version hits get getProp line numbers twice. That appears -// to be because the synthetic accessibility bridges (access$getProp0$cp) -// have line numbers (of the start of the surrounding class) in the JVM -// version and they do not have line numbers in the JVM_IR version. - // LINENUMBERS // test.kt:14 box // test.kt:5 // test.kt:6 // test.kt:5 getProp0 -// LINENUMBERS JVM // test.kt:5 getProp0 -// LINENUMBERS // test.kt:14 box // test.kt:15 box // test.kt:6 getProp1 -// LINENUMBERS JVM // test.kt:6 getProp1 -// LINENUMBERS // test.kt:15 box // test.kt:16 box // test.kt:8 foo // test.kt:5 getProp0 -// LINENUMBERS JVM // test.kt:5 getProp0 -// LINENUMBERS // test.kt:8 foo // test.kt:6 getProp1 -// LINENUMBERS JVM // test.kt:6 getProp1 -// LINENUMBERS // test.kt:8 foo // test.kt:16 box // test.kt:17 box diff --git a/compiler/testData/debug/stepping/initBlocksCompanion.kt b/compiler/testData/debug/stepping/initBlocksCompanion.kt index 5ad34211bfb..bf54939f407 100644 --- a/compiler/testData/debug/stepping/initBlocksCompanion.kt +++ b/compiler/testData/debug/stepping/initBlocksCompanion.kt @@ -30,8 +30,6 @@ fun box() { A.s } -// JVM backend has extra steps for getX and getS. - // LINENUMBERS // test.kt:29 box // test.kt:7 @@ -46,14 +44,10 @@ fun box() { // test.kt:21 // test.kt:22 // 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 diff --git a/compiler/testData/debug/stepping/namedCallableReference.kt b/compiler/testData/debug/stepping/namedCallableReference.kt index 2123a6dc996..3cd07a829c0 100644 --- a/compiler/testData/debug/stepping/namedCallableReference.kt +++ b/compiler/testData/debug/stepping/namedCallableReference.kt @@ -10,10 +10,19 @@ fun f(block: () -> Unit) { fun g() {} +// The synthetic invoke bridge method generated for in the callable reference has line numbers +// in the JVM_IR backend (as all bridges). In the JVM backend, only some bridges have line numbers. +// For some reason, when the bridge does not have line numbers, there is no method entry event +// for the invoke method bridged to. Therefore, the entry line number for invoke only shows +// up for JVM_IR. + // LINENUMBERS // test.kt:3 box // test.kt:4 box // test.kt:8 f +// LINENUMBERS JVM_IR +// test.kt:4 invoke +// LINENUMBERS // test.kt:11 g // test.kt:4 invoke // test.kt:8 f diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionCallStoredToVariable.ir.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionCallStoredToVariable.ir.out new file mode 100644 index 00000000000..f71b2e2592d --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/custom/functionCallStoredToVariable.ir.out @@ -0,0 +1,21 @@ +LineBreakpoint created at functionCallStoredToVariable.kt:7 +LineBreakpoint created at functionCallStoredToVariable.kt:14 +LineBreakpoint created at functionCallStoredToVariable.kt:21 +LineBreakpoint created at functionCallStoredToVariable.kt:28 +Run Java +Connected to the target VM +functionCallStoredToVariable.kt:7 +functionCallStoredToVariable.kt:4 +functionCallStoredToVariable.kt:14 +functionCallStoredToVariable.kt:11 +functionCallStoredToVariable.kt:43 +functionCallStoredToVariable.kt:21 +functionCallStoredToVariable.kt:22 +functionCallStoredToVariable.kt:25 +functionCallStoredToVariable.kt:28 +functionCallStoredToVariable.kt:29 +functionCallStoredToVariable.kt:25 +functionCallStoredToVariable.kt:47 +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/accessors.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/accessors.out index 938123b2a05..311824d0f4d 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/accessors.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/accessors.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at accessors.kt:10 Run Java Connected to the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.ir.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.ir.out new file mode 100644 index 00000000000..d71b633bc9b --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.ir.out @@ -0,0 +1,32 @@ +LineBreakpoint created at syntheticMethods.kt:6 +Run Java +Connected to the target VM +syntheticMethods.kt:6 +syntheticMethods.kt:17 +syntheticMethods.kt:19 +syntheticMethods.kt:20 +syntheticMethods.kt:17 +syntheticMethods.kt:7 +syntheticMethods.kt:-1 +syntheticMethods.kt:7 +syntheticMethods.kt:25 +syntheticMethods.kt:31 +syntheticMethods.kt:25 +syntheticMethods.kt:26 +syntheticMethods.kt:25 +syntheticMethods.kt:31 +syntheticMethods.kt:25 +syntheticMethods.kt:28 +syntheticMethods.kt:8 +syntheticMethods.kt:36 +syntheticMethods.kt:42 +syntheticMethods.kt:36 +syntheticMethods.kt:37 +syntheticMethods.kt:36 +syntheticMethods.kt:42 +syntheticMethods.kt:36 +syntheticMethods.kt:39 +syntheticMethods.kt:9 +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.out index b28ba6a1c91..d2cd63e8dca 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepInto/syntheticMethods.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at syntheticMethods.kt:6 Run Java Connected to the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOut/fwBackingField.ir.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOut/fwBackingField.ir.out index 2232a514fb3..aabd0a2dc82 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOut/fwBackingField.ir.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOut/fwBackingField.ir.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR KotlinFieldBreakpoint created at fwBackingField.kt:5 KotlinFieldBreakpoint created at fwBackingField.kt:8 KotlinFieldBreakpoint created at fwBackingField.kt:18