From 1fe7ef6521c57fe0afd73ec022ad395cf8e3bd21 Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 1 Apr 2020 07:59:01 +0200 Subject: [PATCH] JVM: separate the two kinds of source mappers * a writing source mapper has `mapLineNumber(line, file, class)` that inserts a new SMAP entry and returns a fake line number from it; * a copying source mapper has `mapLineNumber(line)` that uses an existing SMAP to resolve the line number and call the former method on a different source mapper; * those two types are disjoint. --- .../kotlin/codegen/MemberCodegen.java | 8 +- .../inline/AnonymousObjectTransformer.kt | 36 ++--- .../kotlin/codegen/inline/InlineAdapter.java | 4 +- .../kotlin/codegen/inline/InlineCodegen.kt | 2 +- .../inline/InlineCodegenForDefaultBody.kt | 2 +- .../kotlin/codegen/inline/MethodInliner.kt | 15 +- .../jetbrains/kotlin/codegen/inline/SMAP.kt | 137 +++++------------- .../kotlin/codegen/inline/SMAPParser.kt | 18 +-- .../codegen/inline/SourceCompilerForInline.kt | 17 +-- .../backend/jvm/codegen/ClassCodegen.kt | 6 +- .../backend/jvm/codegen/ExpressionCodegen.kt | 2 +- .../jvm/codegen/IrSourceCompilerForInline.kt | 2 +- .../backend/jvm/codegen/irCodegenUtils.kt | 6 +- .../severalMappingsForDefaultFile.kt | 7 +- .../smap/newsmap/mappingInInlineFunLambda.kt | 5 +- .../suspensionPointInMonitor/output.txt | 2 +- 16 files changed, 90 insertions(+), 179 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 1250faf800c..2a26313094d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -13,9 +13,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.context.*; -import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper; import org.jetbrains.kotlin.codegen.inline.NameGenerator; import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages; +import org.jetbrains.kotlin.codegen.inline.SourceMapper; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt; @@ -88,7 +88,7 @@ public abstract class MemberCodegen>() private var constructor: MethodNode? = null - private var sourceInfo: String? = null - private var debugInfo: String? = null + private lateinit var sourceMap: SMAP private lateinit var sourceMapper: SourceMapper private val languageVersionSettings = inliningContext.state.languageVersionSettings @@ -56,6 +55,8 @@ class AnonymousObjectTransformer( val methodsToTransform = ArrayList() val metadataReader = ReadKotlinClassHeaderAnnotationVisitor() lateinit var superClassName: String + var sourceInfo: String? = null + var debugInfo: String? = null createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) { override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array) { @@ -113,22 +114,13 @@ class AnonymousObjectTransformer( override fun visitEnd() {} }, ClassReader.SKIP_FRAMES) - if (!inliningContext.isInliningLambda) { - sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) { - SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!)) - } else { - //seems we can't do any clever mapping cause we don't know any about original class name - IdenticalSourceMapper - } - if (sourceInfo != null && !GENERATE_SMAP) { - classBuilder.visitSource(sourceInfo!!, debugInfo) - } - } else { - if (sourceInfo != null) { - classBuilder.visitSource(sourceInfo!!, debugInfo) - } - sourceMapper = IdenticalSourceMapper - } + // When regenerating objects in lambdas, we have to pass the SMAP straight through and keep + // the original line numbers because SMAPParser does not parse call site markers. + val debugInfoToParse = if (inliningContext.isInliningLambda) null else debugInfo + sourceMap = SMAPParser.parseOrCreateDefault(debugInfoToParse, sourceInfo, oldObjectType.internalName, 1, 65535) + // TODO source info should be for the file into which the function is being inlined, else we cannot + // generate correct call site markers for lambdas inlined into the object + sourceMapper = SourceMapper(sourceMap.sourceInfo.takeIf { debugInfoToParse?.isEmpty() == false }) val allCapturedParamBuilder = ParametersBuilder.newBuilder() val constructorParamBuilder = ParametersBuilder.newBuilder() @@ -183,7 +175,11 @@ class AnonymousObjectTransformer( } } - classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax)) + if (GENERATE_SMAP && !inliningContext.isInliningLambda) { + classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax)) + } else if (sourceInfo != null) { + classBuilder.visitSource(sourceInfo!!, debugInfo) + } val visitor = classBuilder.visitor innerClassNodes.forEach { node -> @@ -296,7 +292,7 @@ class AnonymousObjectTransformer( remapper, isSameModule, "Transformer for " + transformationInfo.oldClassName, - sourceMapper, + SourceMapCopier(sourceMapper, sourceMap, keepCallSites = inliningContext.isInliningLambda), InlineCallSiteInfo( transformationInfo.oldClassName, sourceNode.name, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java index f8862b08e0b..9211d23e3f5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineAdapter.java @@ -30,14 +30,14 @@ import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_ import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getLoadStoreArgSize; public class InlineAdapter extends InstructionAdapter { - private final SourceMapper sourceMapper; + private final SourceMapCopier sourceMapper; private final List blocks = new ArrayList<>(); private boolean isLambdaInlining = false; private int nextLocalIndex = 0; private int nextLocalIndexBeforeInline = -1; - public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) { + public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapCopier sourceMapper) { super(Opcodes.API_VERSION, mv); this.nextLocalIndex = localsSize; this.sourceMapper = sourceMapper; 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 b9779f1c20b..cd1fd49caec 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -233,7 +233,7 @@ abstract class InlineCodegen( val inliner = MethodInliner( node, parameters, info, FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + sourceCompiler.callElementText, - NestedSourceMapper(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo, + SourceMapCopier(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null, !isInlinedToInlineFunInKotlinRuntime() ) //with captured 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 08108f9b265..9cd8d0eb248 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 = NestedSourceMapper(sourceMapper, nodeAndSmap.classSMAP, sameFile = true) + val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, keepCallSites = true) 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 132f26e6855..0765ef60c41 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -54,7 +54,7 @@ class MethodInliner( private val nodeRemapper: FieldRemapper, private val isSameModule: Boolean, private val errorPrefix: String, - private val sourceMapper: SourceMapper, + private val sourceMapper: SourceMapCopier, private val inlineCallSiteInfo: InlineCallSiteInfo, private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root private val shouldPreprocessApiVersionCalls: Boolean = false @@ -288,20 +288,17 @@ class MethodInliner( ) setLambdaInlining(true) - val lambdaSMAP = info.node.classSMAP - - val childSourceMapper = - if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) - NestedSourceMapper(sourceMapper, lambdaSMAP) - else - NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP, sameFile = info !is DefaultLambda) + // 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 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, - childSourceMapper, inlineCallSiteInfo, null + SourceMapCopier(sourceMapper.parent, info.node.classSMAP, sameFile), 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 5665865486d..9d7aa5ff0db 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -63,24 +63,15 @@ object SMAPBuilder { lineMappings.joinToString("") { it.toSMAP(id) } } -class NestedSourceMapper( - override val parent: SourceMapper, private val smap: SMAP, private val sameFile: Boolean = false -) : DefaultSourceMapper(smap.sourceInfo) { - +class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, private val keepCallSites: Boolean = false) { private val visitedLines = TIntIntHashMap() - private var lastVisitedRange: RangeMapping? = null - override fun mapLineNumber(lineNumber: Int): Int { + fun mapLineNumber(lineNumber: Int): Int { if (lineNumber in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) { return lineNumber } - if (sameFile && lineNumber <= smap.sourceInfo.linesInFile) { - // assuming the parent source mapper is for the same file, this line number does not need remapping - return lineNumber - } - val mappedLineNumber = visitedLines.get(lineNumber) if (mappedLineNumber > 0) { return mappedLineNumber @@ -88,99 +79,41 @@ class NestedSourceMapper( val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) - ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}") + ?: error("Can't find range to map line $lineNumber in ${smap.sourceInfo.source}: ${smap.sourceInfo.pathOrCleanFQN}") val sourceLineNumber = range.mapDestToSource(lineNumber) - val newLineNumber = if (sameFile) - parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path, range.callSiteMarker) - else - parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path) - if (newLineNumber > 0) { - visitedLines.put(lineNumber, newLineNumber) + if (sourceLineNumber < 0) { + return -1 } + val callSiteMarker = if (keepCallSites) range.callSiteMarker else parent.callSiteMarker + val newLineNumber = parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path, callSiteMarker) + visitedLines.put(lineNumber, newLineNumber) lastVisitedRange = range return newLineNumber } } -interface SourceMapper { - val resultMappings: List - val parent: SourceMapper? - get() = null - - fun mapLineNumber(lineNumber: Int): Int - - fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int = - mapLineNumber(source, sourceName, sourcePath, null) - - fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int - - companion object { - fun createFromSmap(smap: SMAP): SourceMapper { - return DefaultSourceMapper(smap.sourceInfo, smap.fileMappings) - } - } -} - -object IdenticalSourceMapper : SourceMapper { - override val resultMappings: List - get() = emptyList() - - override val parent: SourceMapper? - get() = null - - override fun mapLineNumber(lineNumber: Int) = lineNumber - - override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int = - throw UnsupportedOperationException( - "IdenticalSourceMapper#mapLineNumber($source, $sourceName, $sourcePath)\n" - + "This mapper should not encounter a line number out of range of the current file.\n" - + "This indicates that SMAP generation is missed somewhere." - ) -} - data class CallSiteMarker(val lineNumber: Int) -open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { - private var maxUsedValue: Int = sourceInfo.linesInFile +class SourceMapper(val sourceInfo: SourceInfo?) { + private var maxUsedValue: Int = sourceInfo?.linesInFile ?: 0 private var fileMappings: LinkedHashMap, FileMapping> = linkedMapOf() var callSiteMarker: CallSiteMarker? = null - override val resultMappings: List + val resultMappings: List get() = fileMappings.values.toList() init { - // Explicitly map the file to itself. - getOrRegisterNewSource(sourceInfo.source, sourceInfo.pathOrCleanFQN).mapNewInterval(1, 1, sourceInfo.linesInFile) - } - - constructor(sourceInfo: SourceInfo, fileMappings: List) : this(sourceInfo) { - // The first mapping is already created in the `init` block above. - fileMappings.asSequence().drop(1) - .forEach { fileMapping -> - val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path) - fileMapping.lineMappings.forEach { - newFileMapping.mapNewInterval(it.source, it.dest, it.range) - maxUsedValue = max(it.maxDest, maxUsedValue) - } - } - } - - private fun getOrRegisterNewSource(name: String, path: String): FileMapping { - return fileMappings.getOrPut(name to path) { FileMapping(name, path) } - } - - //TODO maybe add assertion that linenumber contained in fileMappings - override fun mapLineNumber(lineNumber: Int): Int = lineNumber - - override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int = - mapLineNumber(source, sourceName, sourcePath, callSiteMarker) - - override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int { - if (source < 0) { - //no source information, so just skip this linenumber - return -1 + sourceInfo?.let { + // Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce less ranges. + getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile) } + } + + private fun getOrRegisterNewSource(name: String, path: String): FileMapping = + fileMappings.getOrPut(name to path) { FileMapping(name, path) } + + fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int { val fileMapping = getOrRegisterNewSource(sourceName, sourcePath) val mappedLineIndex = fileMapping.mapNewLineNumber(source, maxUsedValue, callSiteMarker) maxUsedValue = max(maxUsedValue, mappedLineIndex) @@ -188,13 +121,12 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { } } +private fun FileMapping.toSourceInfo(): SourceInfo = + SourceInfo(name, path, lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) }) + class SMAP(val fileMappings: List) { - val sourceInfo: SourceInfo = run { - assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" } - val defaultFile = fileMappings.first() - val defaultRange = defaultFile.lineMappings.first() - SourceInfo(defaultFile.name, defaultFile.path, defaultRange.source + defaultRange.range - 1) - } + val sourceInfo: SourceInfo + get() = fileMappings.firstOrNull()?.toSourceInfo() ?: throw AssertionError("no files mapped") // assuming disjoint line mappings (otherwise binary search can't be used anyway) private val intervals = fileMappings.flatMap { it.lineMappings }.sortedBy { it.dest } @@ -218,18 +150,19 @@ class FileMapping(val name: String, val path: String) { val lineMappings = arrayListOf() fun mapNewLineNumber(source: Int, currentIndex: Int, callSiteMarker: CallSiteMarker?): Int { - var mapping = lineMappings.lastOrNull() - if (mapping != null && mapping.callSiteMarker == callSiteMarker && - (source - mapping.source) in 0 until mapping.range + (if (mapping.maxDest == currentIndex) 10 else 0) - ) { - // Save some space in the SMAP by reusing (or extending if it's the last one) the existing range. - mapping.range = max(mapping.range, source - mapping.source + 1) - } else { - mapping = mapNewInterval(source, currentIndex + 1, 1, callSiteMarker) - } + // Save some space in the SMAP by reusing (or extending if it's the last one) the existing range. + // TODO some *other* range may already cover `source`; probably too slow to check them all though. + // Maybe keep the list ordered by `source` and use binary search to locate the closest range on the left? + val mapping = lineMappings.lastOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSiteMarker) } + ?: lineMappings.firstOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSiteMarker) } + ?: mapNewInterval(source, currentIndex + 1, 1, callSiteMarker) + mapping.range = max(mapping.range, source - mapping.source + 1) return mapping.mapSourceToDest(source) } + private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: CallSiteMarker?): Boolean = + callSiteMarker == newCallSite && (newSource - source) in 0 until range + (if (maxDest == globalMaxDest) 10 else 0) + fun mapNewInterval(source: Int, dest: Int, range: Int, callSiteMarker: CallSiteMarker? = null): RangeMapping = RangeMapping(source, dest, range, callSiteMarker, parent = this).also { lineMappings.add(it) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt index 4f4be3ceae6..21b5bc8a731 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt @@ -23,18 +23,12 @@ object SMAPParser { if (mappingInfo != null && mappingInfo.isNotEmpty()) { return parse(mappingInfo) } - - val mapping = - if (source == null || source.isEmpty() || methodStartLine > methodEndLine) - FileMapping.SKIP - else - FileMapping(source, path).apply { - if (methodStartLine <= methodEndLine) { - //one to one - mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1) - } - } - + if (source == null || source.isEmpty() || methodStartLine > methodEndLine) { + return SMAP(listOf(FileMapping.SKIP)) + } + val mapping = FileMapping(source, path).apply { + mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1) + } return SMAP(listOf(mapping)) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index 357273eb4df..d8d967510e4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -46,7 +46,7 @@ interface SourceCompilerForInline { val inlineCallSiteInfo: InlineCallSiteInfo - val lazySourceMapper: DefaultSourceMapper + val lazySourceMapper: SourceMapper fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode @@ -212,18 +212,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages) } - return createSMAPWithDefaultMapping(expression, parentCodegen.orCreateSourceMapper.resultMappings) - } - - - private fun createSMAPWithDefaultMapping( - declaration: KtExpression, - mappings: List - ): SMAP { - val containingFile = declaration.containingFile - CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in $containingFile") - - return SMAP(mappings) + return SMAP(parentCodegen.orCreateSourceMapper.resultMappings) } @Suppress("UNCHECKED_CAST") @@ -310,7 +299,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, inliningFunction as KtNamedFunction?, parentCodegen, asmMethod ) - createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings) + SMAP(parentCodegen.orCreateSourceMapper.resultMappings) } else { generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null) } 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 c93c031cffa..2f7a6ec8fb3 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 @@ -148,7 +148,7 @@ abstract class ClassCodegen protected constructor( if (writeSourceMap) { visitor.visitSMAP(smap, !context.state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax)) } else { - visitor.visitSource(smap.sourceInfo.source, null) + visitor.visitSource(smap.sourceInfo!!.source, null) } visitor.done() @@ -269,7 +269,7 @@ abstract class ClassCodegen protected constructor( protected abstract fun bindMethodMetadata(method: IrFunction, signature: Method) - private fun generateMethod(method: IrFunction, classSMAP: DefaultSourceMapper) { + private fun generateMethod(method: IrFunction, classSMAP: SourceMapper) { if (method.isFakeOverride) { jvmSignatureClashDetector.trackFakeOverrideMethod(method) return @@ -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 = NestedSourceMapper(classSMAP, smap, sameFile = true) + val smapCopier = SourceMapCopier(classSMAP, smap, keepCallSites = true) 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/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index de051cc8e7a..1cfa202c6b3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -106,7 +106,7 @@ class ExpressionCodegen( val mv: InstructionAdapter, val classCodegen: ClassCodegen, val inlinedInto: ExpressionCodegen?, - val smap: DefaultSourceMapper + val smap: SourceMapper ) : IrElementVisitor, BaseExpressionCodegen { var finallyDepth = 0 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt index 8f1c386c594..00a819c9cd1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrSourceCompilerForInline.kt @@ -85,7 +85,7 @@ class IrSourceCompilerForInline( ) } - override val lazySourceMapper: DefaultSourceMapper + override val lazySourceMapper: SourceMapper get() = codegen.smap.also { codegen.classCodegen.writeSourceMap = true } override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode = diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index 0181460ce46..2820e7d6bcc 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper +import org.jetbrains.kotlin.codegen.inline.SourceMapper import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource @@ -80,14 +80,14 @@ val IrDeclaration.fileParent: IrFile internal val DeclarationDescriptorWithSource.psiElement: PsiElement? get() = (source as? PsiSourceElement)?.psi -fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper { +fun JvmBackendContext.getSourceMapper(declaration: IrClass): SourceMapper { val sourceManager = this.psiSourceManager val fileEntry = sourceManager.getFileEntry(declaration.fileParent) // NOTE: apparently inliner requires the source range to cover the // whole file the class is declared in rather than the class only. // TODO: revise val endLineNumber = fileEntry?.getSourceRangeInfo(0, fileEntry.maxOffset)?.endLineNumber ?: 0 - return DefaultSourceMapper( + return SourceMapper( SourceInfo.createInfoForIr( endLineNumber + 1, typeMapper.mapClass(declaration).internalName, diff --git a/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt b/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt index 801bbecf6d0..8e096858a78 100644 --- a/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt +++ b/compiler/testData/codegen/boxInline/smap/anonymous/severalMappingsForDefaultFile.kt @@ -74,7 +74,8 @@ test/_1Kt _2Kt *L 1#1,18:1 -14#2,2:19 -10#2:21 -7#3:22 +14#2:19 +10#2:20 +15#2:22 +7#3:21 *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 c40b1c7a80e..aaf5879d943 100644 --- a/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt +++ b/compiler/testData/codegen/boxInline/smap/newsmap/mappingInInlineFunLambda.kt @@ -90,6 +90,7 @@ test/_1Kt _2Kt *L 1#1,19:1 -7#2,3:20 -9#3,2:23 +7#2,2:20 +9#2:24 +9#3,2:22 *E diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/output.txt index 59cb54abe15..a066b87afe4 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/output.txt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/output.txt @@ -4,7 +4,7 @@ compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/so compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:14:13: error: a suspension point at SourceKt$test$2.invokeSuspend(source.kt:17) is inside a critical section builder { ^ -compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:9: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:62) is inside a critical section +compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:9: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:60) is inside a critical section withCrossinline { ^ compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:50:34: error: a suspension point at SourceKt$withCrossinline$c$1.invokeSuspend(source.kt:52) is inside a critical section