Debugger, BE: Generate original line number after inlining if call is used in an if condition
If a part of an 'if' condition is an inline function call, we need to insert the original condition line after it. Otherwise, the debugger will think it is inside the inline function implementation. Obviously, this breaks stepping – instead of the 'if' body, we go on stepping through the inline function. This commit fixes 'KotlinSteppingTestGenerated.StepOver#testSoInlineLibFun' test.
This commit is contained in:
@@ -47,7 +47,7 @@ interface BaseExpressionCodegen {
|
||||
functionReferenceReceiver: StackValue?
|
||||
)
|
||||
|
||||
fun markLineNumberAfterInlineIfNeeded()
|
||||
fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean)
|
||||
|
||||
fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker)
|
||||
|
||||
|
||||
@@ -1499,10 +1499,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.visitLineNumber(lineNumber, label);
|
||||
}
|
||||
|
||||
//we should generate additional linenumber info after inline call only if it used as argument
|
||||
@Override
|
||||
public void markLineNumberAfterInlineIfNeeded() {
|
||||
if (!shouldMarkLineNumbers) {
|
||||
public void markLineNumberAfterInlineIfNeeded(boolean registerLineNumberAfterwards) {
|
||||
if (!shouldMarkLineNumbers || registerLineNumberAfterwards) {
|
||||
//if it used as general argument
|
||||
if (myLastLineNumber > -1) {
|
||||
Label label = new Label();
|
||||
@@ -1510,7 +1509,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
v.visitLineNumber(myLastLineNumber, label);
|
||||
}
|
||||
} else {
|
||||
//if it used as argument of infix call (in this case lineNumber for simple inlineCall also would be reset)
|
||||
resetLastLineNumber();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,28 +118,29 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", message)
|
||||
}
|
||||
|
||||
protected fun endCall(result: InlineResult) {
|
||||
protected fun endCall(result: InlineResult, registerLineNumberAfterwards: Boolean) {
|
||||
leaveTemps()
|
||||
|
||||
codegen.propagateChildReifiedTypeParametersUsages(result.reifiedTypeParametersUsages)
|
||||
|
||||
state.factory.removeClasses(result.calcClassesToRemove())
|
||||
|
||||
codegen.markLineNumberAfterInlineIfNeeded()
|
||||
codegen.markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards)
|
||||
}
|
||||
|
||||
fun performInline(
|
||||
typeArguments: List<TypeParameterMarker>?,
|
||||
inlineDefaultLambdas: Boolean,
|
||||
mapDefaultSignature: Boolean,
|
||||
typeSystem: TypeSystemCommonBackendContext
|
||||
typeSystem: TypeSystemCommonBackendContext,
|
||||
registerLineNumberAfterwards: Boolean
|
||||
) {
|
||||
var nodeAndSmap: SMAPAndMethodNode? = null
|
||||
try {
|
||||
nodeAndSmap = createInlineMethodNode(
|
||||
functionDescriptor, methodOwner, jvmSignature, mapDefaultSignature, typeArguments, typeSystem, state, sourceCompiler
|
||||
)
|
||||
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas))
|
||||
endCall(inlineCall(nodeAndSmap, inlineDefaultLambdas), registerLineNumberAfterwards)
|
||||
} catch (e: CompilationException) {
|
||||
throw e
|
||||
} catch (e: InlineException) {
|
||||
|
||||
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
@@ -66,12 +69,19 @@ class PsiInlineCodegen(
|
||||
return
|
||||
}
|
||||
try {
|
||||
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem)
|
||||
val registerLineNumber = registerLineNumberAfterwards(resolvedCall)
|
||||
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem, registerLineNumber)
|
||||
} finally {
|
||||
state.globalInlineContext.exitFromInliningOf(inlineCall)
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerLineNumberAfterwards(resolvedCall: ResolvedCall<*>?): Boolean {
|
||||
val callElement = resolvedCall?.call?.callElement ?: return false
|
||||
val parentIfCondition = callElement.getParentOfType<KtIfExpression>(true)?.condition ?: return false
|
||||
return parentIfCondition.isAncestor(callElement, false)
|
||||
}
|
||||
|
||||
override fun processAndPutHiddenParameters(justProcess: Boolean) {
|
||||
if (getMethodAsmFlags(functionDescriptor, sourceCompiler.contextKind, state) and Opcodes.ACC_STATIC == 0) {
|
||||
invocationParamBuilder.addNextParameter(methodOwner, false, actualDispatchReceiver)
|
||||
|
||||
+1
-1
@@ -1119,7 +1119,7 @@ class ExpressionCodegen(
|
||||
//TODO
|
||||
}
|
||||
|
||||
override fun markLineNumberAfterInlineIfNeeded() {
|
||||
override fun markLineNumberAfterInlineIfNeeded(registerLineNumberAfterwards: Boolean) {
|
||||
// Inline function has its own line number which is in a separate instance of codegen,
|
||||
// therefore we need to reset lastLineNumber to force a line number generation after visiting inline function.
|
||||
lastLineNumber = -1
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
|
||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -187,7 +188,8 @@ class IrInlineCodegen(
|
||||
expression.symbol.owner.typeParameters.map { it.symbol },
|
||||
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
false,
|
||||
codegen.typeMapper.typeSystem
|
||||
codegen.typeMapper.typeSystem,
|
||||
false
|
||||
)
|
||||
} finally {
|
||||
state.globalInlineContext.exitFromInliningOf(inlineCall)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//FILE: test.kt
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
fun box() {
|
||||
if (listOf(1, 2, 3).myAny { it > 2 }) {
|
||||
println("foo")
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <T> Iterable<T>.myAny(predicate: (T) -> Boolean): Boolean {
|
||||
for (element in this) {
|
||||
if (predicate(element)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 3 LINENUMBER 5
|
||||
@@ -0,0 +1,16 @@
|
||||
//FILE: test.kt
|
||||
|
||||
fun box() {
|
||||
if (listOf(1, 2, 3).myAny { it > 2 } == true) {
|
||||
println("foo")
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <T> Iterable<T>.myAny(predicate: (T) -> Boolean): Boolean {
|
||||
for (element in this) {
|
||||
if (predicate(element)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 3 LINENUMBER 4
|
||||
@@ -3253,6 +3253,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/ifTrueElse.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineCondition.kt")
|
||||
public void testInlineCondition() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineCondition2.kt")
|
||||
public void testInlineCondition2() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("singleThen.kt")
|
||||
public void testSingleThen() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt");
|
||||
|
||||
+10
@@ -3298,6 +3298,16 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/ifTrueElse.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineCondition.kt")
|
||||
public void testInlineCondition() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineCondition2.kt")
|
||||
public void testInlineCondition2() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("singleThen.kt")
|
||||
public void testSingleThen() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt");
|
||||
|
||||
Reference in New Issue
Block a user