From 86b28b95ca8b7320a3f8f43e121d2fde0204665f Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 1 Apr 2020 09:33:47 +0200 Subject: [PATCH] JVM: keep call site markers when inlining lambdas into objects A follow-up for KT-35006: fun f() = foo { bar() } inline fun foo(crossinline x: () -> Unit) = { x() }() inline fun bar() = TODO() does not provide the option to navigate to bar's call site at all. --- .../codegen/inline/AnonymousObjectTransformer.kt | 2 +- .../jetbrains/kotlin/codegen/inline/InlineCodegen.kt | 12 +++++------- .../codegen/inline/InlineCodegenForDefaultBody.kt | 2 +- .../jetbrains/kotlin/codegen/inline/MethodInliner.kt | 7 ++----- .../src/org/jetbrains/kotlin/codegen/inline/SMAP.kt | 11 +++-------- .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 2 +- .../smap/anonymous/severalMappingsForDefaultFile.kt | 8 ++++++++ .../smap/newsmap/mappingInInlineFunLambda.kt | 8 ++++++++ 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index dbd20fe9336..15c079c957f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -290,7 +290,7 @@ class AnonymousObjectTransformer( remapper, isSameModule, "Transformer for " + transformationInfo.oldClassName, - SourceMapCopier(sourceMapper, sourceMap, keepCallSites = inliningContext.isInliningLambda), + SourceMapCopier(sourceMapper, sourceMap), InlineCallSiteInfo( transformationInfo.oldClassName, sourceNode.name, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index 4da2253bb61..c298456997a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -72,7 +72,7 @@ abstract class InlineCodegen( var activeLambda: LambdaInfo? = null protected set - private val defaultSourceMapper = sourceCompiler.lazySourceMapper + private val sourceMapper = sourceCompiler.lazySourceMapper protected var delayedHiddenWriting: Function0? = null @@ -208,7 +208,6 @@ abstract class InlineCodegen( protected fun inlineCall(nodeAndSmap: SMAPAndMethodNode, inlineDefaultLambda: Boolean, isCallOfFunctionInCorrespondingDefaultDispatch: Boolean): InlineResult { assert(delayedHiddenWriting == null) { "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'" } - if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = codegen.lastLineNumber val node = nodeAndSmap.node if (inlineDefaultLambda) { for (lambda in extractDefaultLambdas(node)) { @@ -230,11 +229,13 @@ abstract class InlineCodegen( sourceCompiler, sourceCompiler.inlineCallSiteInfo, reifiedTypeInliner, typeParameterMappings ) + val sourceInfo = sourceMapper.sourceInfo!! + val callSite = SourcePosition(codegen.lastLineNumber, sourceInfo.source, sourceInfo.pathOrCleanFQN) val inliner = MethodInliner( node, parameters, info, FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + sourceCompiler.callElementText, - SourceMapCopier(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo, - if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null, + SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, callSite.takeIf { !isCallOfFunctionInCorrespondingDefaultDispatch }), + info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null, !isInlinedToInlineFunInKotlinRuntime() ) //with captured @@ -269,9 +270,6 @@ abstract class InlineCodegen( if (shouldSpillStack) { addInlineMarker(codegen.v, false) } - - if (!isCallOfFunctionInCorrespondingDefaultDispatch) defaultSourceMapper.callSiteMarker = null - return result } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt index 9cd8d0eb248..b8c92362fb6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -42,7 +42,7 @@ class InlineCodegenForDefaultBody( val nodeAndSmap = InlineCodegen.createInlineMethodNode( function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline ) - val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, keepCallSites = true) + val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP) val node = nodeAndSmap.node val transformedMethod = MethodNode( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 0765ef60c41..3a16cb8a5a2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -289,16 +289,13 @@ class MethodInliner( setLambdaInlining(true) - // TODO we cannot keep call site markers when inlining lambdas into objects because AnonymousObjectTransformer - // uses the original's source info, thus KotlinDebug would point to the file with the inline function - // instead of the one with the call. - val sameFile = info !is DefaultLambda && (!inliningContext.classRegeneration || inliningContext.isInliningLambda) + val callSite = sourceMapper.callSite.takeIf { info is DefaultLambda } val inliner = MethodInliner( info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), newCapturedRemapper, if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/, "Lambda inlining " + info.lambdaClassType.internalName, - SourceMapCopier(sourceMapper.parent, info.node.classSMAP, sameFile), inlineCallSiteInfo, null + SourceMapCopier(sourceMapper.parent, info.node.classSMAP, callSite), inlineCallSiteInfo, null ) val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt index 1743984e83a..b2f58ad81ed 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -58,7 +58,7 @@ object SMAPBuilder { lineMappings.joinToString("") { it.toSMAP(id, mapToFirstLine) } } -class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, private val keepCallSites: Boolean = false) { +class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, val callSite: SourcePosition? = null) { private val visitedLines = TIntIntHashMap() private var lastVisitedRange: RangeMapping? = null @@ -79,10 +79,7 @@ class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, private if (inlineSource.line < 0) { return -1 } - val inlineCallSite = if (keepCallSites) range.callSite else parent.callSiteMarker?.let { - SourcePosition(it, parent.sourceInfo!!.source, parent.sourceInfo.pathOrCleanFQN) - } - val newLineNumber = parent.mapLineNumber(inlineSource, inlineCallSite) + val newLineNumber = parent.mapLineNumber(inlineSource, callSite ?: range.callSite) visitedLines.put(lineNumber, newLineNumber) lastVisitedRange = range return newLineNumber @@ -95,14 +92,12 @@ class SourceMapper(val sourceInfo: SourceInfo?) { private var maxUsedValue: Int = sourceInfo?.linesInFile ?: 0 private var fileMappings: LinkedHashMap, FileMapping> = linkedMapOf() - var callSiteMarker: Int? = null - val resultMappings: List get() = fileMappings.values.toList() init { sourceInfo?.let { - // Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce less ranges. + // Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce fewer ranges. getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 2f7a6ec8fb3..5ad5c671162 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -281,7 +281,7 @@ abstract class ClassCodegen protected constructor( method.origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE ) val mv = with(node) { visitor.newMethod(method.OtherOrigin, access, name, desc, signature, exceptions.toTypedArray()) } - val smapCopier = SourceMapCopier(classSMAP, smap, keepCallSites = true) + val smapCopier = SourceMapCopier(classSMAP, smap) val smapCopyingVisitor = object : MethodVisitor(Opcodes.API_VERSION, mv) { override fun visitLineNumber(line: Int, start: Label) = super.visitLineNumber(smapCopier.mapLineNumber(line), start) diff --git a/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt b/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt index e47c4fd18e8..03c7864a230 100644 --- a/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt +++ b/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt @@ -73,4 +73,12 @@ _2Kt 10#2:20 15#2:22 7#3:21 +*E +*S KotlinDebug +*F ++ 1 1.kt +test/_1Kt$annotatedWith2$1 +*L +6#1:19 +6#1:22 *E \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt b/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt index aaf5879d943..be59b950177 100644 --- a/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt +++ b/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt @@ -94,3 +94,11 @@ _2Kt 9#2:24 9#3,2:22 *E +*S KotlinDebug +*F ++ 1 1.kt +test/_1Kt$test$1 +*L +14#1,2:20 +14#1:24 +*E