From a3fe9034e2fa3f57ce6bb536d932986473447ab9 Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 20 Mar 2020 14:25:35 +0100 Subject: [PATCH] JVM: refactor some SMAP-related classes In particular, remove redundant copying from SMAPAndMethodNode (which also fails for empty methods). --- .../kotlin/codegen/inline/InlineCodegen.kt | 9 +--- .../inline/InlineCodegenForDefaultBody.kt | 2 +- .../kotlin/codegen/inline/MethodInliner.kt | 9 ++-- .../jetbrains/kotlin/codegen/inline/SMAP.kt | 44 +++++++---------- .../codegen/inline/SMAPAndMethodNode.kt | 48 ------------------- 5 files changed, 26 insertions(+), 86 deletions(-) delete mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt 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 2769befdd89..cb60ed3dd95 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, - createNestedSourceMapper(nodeAndSmap, defaultSourceMapper), info.callSiteInfo, + NestedSourceMapper(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null, !isInlinedToInlineFunInKotlinRuntime() ) //with captured @@ -576,7 +576,7 @@ abstract class InlineCodegen( result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor") } - return resultInCache.copyWithNewNode(cloneMethodNode(resultInCache.node)) + return SMAPAndMethodNode(cloneMethodNode(resultInCache.node), resultInCache.classSMAP) } private fun createDefaultFakeSMAP() = SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1) @@ -704,11 +704,6 @@ abstract class InlineCodegen( } return result } - - - fun createNestedSourceMapper(nodeAndSmap: SMAPAndMethodNode, parent: SourceMapper): SourceMapper { - return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo) - } } } 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 854b1e7c544..44930e1f2a2 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 = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper) + val childSourceMapper = NestedSourceMapper(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 5bfbcb29592..103cec4e34a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -284,10 +284,11 @@ class MethodInliner( val childSourceMapper = if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) - NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) - else if (info is DefaultLambda) { - NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) - } else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node) + NestedSourceMapper(sourceMapper, lambdaSMAP) + else if (info is DefaultLambda) + NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP) + else + SameFileNestedSourceMapper(sourceMapper.parent!!, info.node.classSMAP) val inliner = MethodInliner( info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), 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 876836e8b30..21cc1e70c4d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.codegen.inline.SMAP.Companion.FILE_SECTION import org.jetbrains.kotlin.codegen.inline.SMAP.Companion.LINE_SECTION import org.jetbrains.kotlin.codegen.inline.SMAP.Companion.STRATA_SECTION import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.org.objectweb.asm.tree.MethodNode import java.util.* import kotlin.math.max @@ -86,8 +87,8 @@ class SMAPBuilder( } open class NestedSourceMapper( - override val parent: SourceMapper, val ranges: List, sourceInfo: SourceInfo -) : DefaultSourceMapper(sourceInfo) { + override val parent: SourceMapper, protected val smap: SMAP +) : DefaultSourceMapper(smap.sourceInfo) { private val visitedLines = TIntIntHashMap() @@ -104,7 +105,7 @@ open class NestedSourceMapper( mappedLineNumber } else { val rangeForMapping = - (if (lastVisitedRange?.contains(lineNumber) == true) lastVisitedRange!! else findMappingIfExists(lineNumber)) + (if (lastVisitedRange?.contains(lineNumber) == true) lastVisitedRange!! else smap.findRange(lineNumber)) ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}") val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber) val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path) @@ -115,22 +116,12 @@ open class NestedSourceMapper( newLineNumber } } - - private fun findMappingIfExists(lineNumber: Int): RangeMapping? { - val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { value, key -> - if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) - }) - return if (index < 0) null else ranges[index] - } } -open class InlineLambdaSourceMapper( - parent: SourceMapper, smap: SMAPAndMethodNode -) : NestedSourceMapper(parent, smap.sortedRanges, smap.classSMAP.sourceInfo) { - +open class SameFileNestedSourceMapper(parent: SourceMapper, smap: SMAP) : NestedSourceMapper(parent, smap) { override fun mapLineNumber(lineNumber: Int): Int { - if (ranges.firstOrNull()?.contains(lineNumber) == true) { - //don't remap origin lambda line numbers + if (lineNumber <= smap.sourceInfo.linesInFile) { + // assuming the parent source mapper is for the same file, this line number does not need remapping return lineNumber } return super.mapLineNumber(lineNumber) @@ -250,20 +241,20 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper { } class SMAP(val fileMappings: List) { - init { + 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 default: FileMapping - get() = fileMappings.first() + private val intervals = fileMappings.flatMap { it.lineMappings }.sortedWith(RangeMapping.Comparator) - val intervals = fileMappings.flatMap { it.lineMappings }.sortedWith(RangeMapping.Comparator) - - val sourceInfo: SourceInfo - - init { - val defaultMapping = default.lineMappings.first() - sourceInfo = SourceInfo(default.name, default.path, defaultMapping.source + defaultMapping.range - 1) + fun findRange(lineNumber: Int): RangeMapping? { + val index = intervals.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { value, key -> + if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) + }) + return if (index < 0) null else intervals[index] } companion object { @@ -274,6 +265,7 @@ class SMAP(val fileMappings: List) { } } +data class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) class RawFileMapping(val name: String, val path: String) { private val rangeMappings = arrayListOf() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt deleted file mode 100644 index 51afe04635a..00000000000 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.codegen.inline - -import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.org.objectweb.asm.tree.LineNumberNode -import org.jetbrains.org.objectweb.asm.tree.MethodNode -import java.util.* - -//TODO comment -class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) { - val sortedRanges = createLineNumberSequence(node, classSMAP).distinct().toList().sortedWith(RangeMapping.Comparator) - - fun copyWithNewNode(newMethodNode: MethodNode) = SMAPAndMethodNode(newMethodNode, classSMAP) -} - -private fun createLineNumberSequence(node: MethodNode, classSMAP: SMAP): Sequence { - return InsnSequence(node.instructions.first, null).filterIsInstance().map { lineNumber -> - val mapping = RangeMapping(lineNumber.line, lineNumber.line, 1) - - if (lineNumber.line in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) { - return@map mapping - } - - val index = classSMAP.intervals.binarySearch(mapping, Comparator { value, key -> - if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) - }) - if (index < 0) { - error("Unmapped line number in inlined function ${node.name}:${lineNumber.line}") - } - classSMAP.intervals[index] - } -}