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:
Yan Zhulanow
2019-12-23 18:08:13 +09:00
parent f115bde682
commit cc2fe6b0c6
10 changed files with 76 additions and 12 deletions
@@ -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)