[JVM_IR] Improve debugging behavior of inline functions

Specifically, this commit improves the stepping behavior of the IR
backend around functions with defaults.

  - Improved line numbers in the default handler itself for better
    stepping when inlined.

  - Improved source information on default arguments

  - Improved test coverage of stepping behavior in old and IR backends.

Improves the stepping behaviour around inline methods with default
arguments. In particular, we now accurately step through the
evaluation of default arguments, but do _not_ spuriously show the exit
from the $default handler.
This commit is contained in:
Mads Ager
2020-01-31 15:29:19 +01:00
committed by max-kammerer
parent 516692008f
commit 03fb49bb38
36 changed files with 216 additions and 53 deletions
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.psi.PsiElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.context.ClosureContext
@@ -133,14 +132,15 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
inlineDefaultLambdas: Boolean,
mapDefaultSignature: Boolean,
typeSystem: TypeSystemCommonBackendContext,
registerLineNumberAfterwards: Boolean
registerLineNumberAfterwards: Boolean,
isCallOfFunctionInCorrespondingDefaultDispatch: Boolean
) {
var nodeAndSmap: SMAPAndMethodNode? = null
try {
nodeAndSmap = createInlineMethodNode(
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas, isCallOfFunctionInCorrespondingDefaultDispatch), registerLineNumberAfterwards)
} catch (e: CompilationException) {
throw e
} catch (e: InlineException) {
@@ -206,9 +206,9 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
?: error("No stack value for continuation parameter of suspend function")
}
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean): InlineResult {
protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean, isCallOfFunctionInCorrespondingDefaultDispatch: Boolean): InlineResult {
assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" }
defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = CallSiteMarker(codegen.lastLineNumber)
val node = nodeAndSmap.node
if (inlineDefaultLambda) {
for (lambda in extractDefaultLambdas(node)) {
@@ -270,7 +270,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
addInlineMarker(codegen.v, false)
}
defaultSourceMapper.callSiteMarker = null
if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = null
return result
}
@@ -69,7 +69,7 @@ class PsiInlineCodegen(
}
try {
val registerLineNumber = registerLineNumberAfterwards(resolvedCall)
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem, registerLineNumber)
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem, registerLineNumber, false)
} finally {
state.globalInlineContext.exitFromInlining()
}
@@ -6975,11 +6975,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/dataClassCopy.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/defaults.kt");
}
@TestMetadata("delegationBy.kt")
public void testDelegationBy() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/delegationBy.kt");
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.codegen.inline.*
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType
@@ -162,7 +165,8 @@ class IrInlineCodegen(
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
false,
codegen.typeMapper.typeSystem,
false
registerLineNumberAfterwards = false,
isCallOfFunctionInCorrespondingDefaultDispatch = codegen.irFunction == codegen.context.mapping.defaultArgumentsDispatchFunction[function]
)
} finally {
state.globalInlineContext.exitFromInlining()
@@ -161,7 +161,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
}
fun build(): IrExpression = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol).run {
irBlock {
irBlock(irFunctionReference.startOffset, irFunctionReference.endOffset) {
val constructor = createConstructor()
createInvokeMethod(
if (samSuperType != null && boundReceiver != null) {
@@ -1,3 +1,6 @@
// Enable for dexing once we have a D8 version with a fix for
// https://issuetracker.google.com/148661132
// IGNORE_DEXING
// NO_CHECK_LAMBDA_INLINING
// FILE: 1.kt
package test
@@ -1,3 +1,6 @@
// Enable for dexing once we have a D8 version with a fix for
// https://issuetracker.google.com/148661132
// IGNORE_DEXING
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: inlineFun$default
package test
+1 -1
View File
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
package test
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: inlineFun$default
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: inlineFun$default
@@ -1,4 +1,4 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
// SKIP_INLINE_CHECK_IN: lParams$default
+46
View File
@@ -0,0 +1,46 @@
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt
public val MASSERTIONS_ENABLED: Boolean = true
public inline fun massert(value: Boolean, lazyMessage: () -> String) {
if (MASSERTIONS_ENABLED) {
if (!value) {
val message = lazyMessage()
throw AssertionError(message)
}
}
}
public inline fun massert(value: Boolean, message: Any = "Assertion failed") {
if (MASSERTIONS_ENABLED) {
if (!value) {
throw AssertionError(message)
}
}
}
fun box(): String {
massert(true)
massert(true) {
"test"
}
return "OK"
}
// LINENUMBERS
// test.kt:24
// test.kt:15
// test.kt:16
// test.kt:3
// test.kt:16
// test.kt:17
// test.kt:21
// test.kt:25
// test.kt:6
// test.kt:3
// test.kt:6
// test.kt:7
// test.kt:12
// test.kt:29
+16
View File
@@ -0,0 +1,16 @@
// FILE: test.kt
fun ifoo(ok: String = "OK"): String {
return ok
}
fun box(): String {
return ifoo()
}
// LINENUMBERS
// test.kt:8
// test.kt:3
// test.kt:4
// test.kt:3
// test.kt:8
@@ -0,0 +1,15 @@
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt
inline fun ifoo(ok: String = "OK"): String {
return ok
}
fun box(): String {
return ifoo()
}
// TODO: IR Backend behaves like simpleDefaultArg: 8,3,4, _3_ ,8
// LINENUMBERS
// test.kt:8
// test.kt:3
// test.kt:4
// test.kt:8
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JVM_IR
// FILE: test.kt
inline fun alsoInline() = "OK"
inline fun ifoo(s: String = alsoInline()): String {
return s
}
fun box(): String {
return ifoo()
}
// LINENUMBERS
// test.kt:10
// test.kt:5
// test.kt:3
// test.kt:6
// test.kt:10
@@ -1,6 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class C {
fun `a$default`(c: C, x: Int, m: Int, mh: Any) {}
fun a(x: Int = 1) {}
}
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JVM_OLD
// !DIAGNOSTICS: -UNUSED_PARAMETER
open class Base {
open fun `foo$default`(d: Derived, i: Int, mask: Int, mh: Any) {}
}
class Derived : Base() {
<!ACCIDENTAL_OVERRIDE!>fun foo(i: Int = 0)<!> {}
}
@@ -0,0 +1,18 @@
package
public open class Base {
public constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int, /*3*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Derived : Base {
public constructor Derived()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ i: kotlin.Int = ...): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun `foo$default`(/*0*/ d: Derived, /*1*/ i: kotlin.Int, /*2*/ mask: kotlin.Int, /*3*/ mh: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -6982,11 +6982,6 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/dataClassCopy.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/defaults.kt");
}
@TestMetadata("delegationBy.kt")
public void testDelegationBy() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/delegationBy.kt");
@@ -98,9 +98,9 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/classPropertyOverriddenByFunction.kt");
}
@TestMetadata("defaultFunction.kt")
public void testDefaultFunction() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/defaultFunction.kt");
@TestMetadata("defaultFunction_ir.kt")
public void testDefaultFunction_ir() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/defaultFunction_ir.kt");
}
@TestMetadata("delegatedFunctionOverriddenByProperty_ir.kt")
@@ -433,9 +433,9 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/dataClassCopy.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/defaults.kt");
@TestMetadata("defaults_ir.kt")
public void testDefaults_ir() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/defaults_ir.kt");
}
@TestMetadata("delegationBy_ir.kt")
@@ -103,9 +103,9 @@ public class DiagnosticsTestWithOldJvmBackendGenerated extends AbstractDiagnosti
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/classPropertyOverriddenByFunction.kt");
}
@TestMetadata("defaultFunction.kt")
public void testDefaultFunction() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/defaultFunction.kt");
@TestMetadata("defaultFunction_old.kt")
public void testDefaultFunction_old() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/accidentalOverrides/defaultFunction_old.kt");
}
@TestMetadata("delegatedFunctionOverriddenByProperty_old.kt")
@@ -428,9 +428,9 @@ public class DiagnosticsTestWithOldJvmBackendGenerated extends AbstractDiagnosti
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/dataClassCopy.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/defaults.kt");
@TestMetadata("defaults_old.kt")
public void testDefaults_old() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/duplicateJvmSignature/specialNames/defaults_old.kt");
}
@TestMetadata("delegationBy_old.kt")
@@ -6977,11 +6977,6 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/dataClassCopy.kt");
}
@TestMetadata("defaults.kt")
public void testDefaults() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/defaults.kt");
}
@TestMetadata("delegationBy.kt")
public void testDelegationBy() throws Exception {
runTest("compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/delegationBy.kt");
@@ -31,6 +31,12 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/debug/stepping"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("assertion.kt")
public void testAssertion() throws Exception {
runTest("compiler/testData/debug/stepping/assertion.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
@@ -103,6 +109,24 @@ public class IrSteppingTestGenerated extends AbstractIrSteppingTest {
runTest("compiler/testData/debug/stepping/recursion.kt");
}
@Test
@TestMetadata("simpleDefaultArg.kt")
public void testSimpleDefaultArg() throws Exception {
runTest("compiler/testData/debug/stepping/simpleDefaultArg.kt");
}
@Test
@TestMetadata("simpleDefaultArgWithInline.kt")
public void testSimpleDefaultArgWithInline() throws Exception {
runTest("compiler/testData/debug/stepping/simpleDefaultArgWithInline.kt");
}
@Test
@TestMetadata("simpleInlineDefaultArg.kt")
public void testSimpleInlineDefaultArg() throws Exception {
runTest("compiler/testData/debug/stepping/simpleInlineDefaultArg.kt");
}
@Test
@TestMetadata("throwException.kt")
public void testThrowException() throws Exception {
@@ -31,6 +31,12 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/debug/stepping"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("assertion.kt")
public void testAssertion() throws Exception {
runTest("compiler/testData/debug/stepping/assertion.kt");
}
@Test
@TestMetadata("callableReference.kt")
public void testCallableReference() throws Exception {
@@ -103,6 +109,24 @@ public class SteppingTestGenerated extends AbstractSteppingTest {
runTest("compiler/testData/debug/stepping/recursion.kt");
}
@Test
@TestMetadata("simpleDefaultArg.kt")
public void testSimpleDefaultArg() throws Exception {
runTest("compiler/testData/debug/stepping/simpleDefaultArg.kt");
}
@Test
@TestMetadata("simpleDefaultArgWithInline.kt")
public void testSimpleDefaultArgWithInline() throws Exception {
runTest("compiler/testData/debug/stepping/simpleDefaultArgWithInline.kt");
}
@Test
@TestMetadata("simpleInlineDefaultArg.kt")
public void testSimpleInlineDefaultArg() throws Exception {
runTest("compiler/testData/debug/stepping/simpleInlineDefaultArg.kt");
}
@Test
@TestMetadata("throwException.kt")
public void testThrowException() throws Exception {