JVM: refactor some SMAP-related classes

In particular, remove redundant copying from SMAPAndMethodNode (which
also fails for empty methods).
This commit is contained in:
pyos
2020-03-20 14:25:35 +01:00
committed by max-kammerer
parent e73b01f20c
commit a3fe9034e2
5 changed files with 26 additions and 86 deletions
@@ -233,7 +233,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
val inliner = MethodInliner( val inliner = MethodInliner(
node, parameters, info, FieldRemapper(null, null, parameters), isSameModule, node, parameters, info, FieldRemapper(null, null, parameters), isSameModule,
"Method inlining " + sourceCompiler.callElementText, "Method inlining " + sourceCompiler.callElementText,
createNestedSourceMapper(nodeAndSmap, defaultSourceMapper), info.callSiteInfo, NestedSourceMapper(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo,
if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null, if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
!isInlinedToInlineFunInKotlinRuntime() !isInlinedToInlineFunInKotlinRuntime()
) //with captured ) //with captured
@@ -576,7 +576,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
result ?: throw IllegalStateException("Couldn't obtain compiled function body for $functionDescriptor") 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) private fun createDefaultFakeSMAP() = SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
@@ -704,11 +704,6 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
} }
return result return result
} }
fun createNestedSourceMapper(nodeAndSmap: SMAPAndMethodNode, parent: SourceMapper): SourceMapper {
return NestedSourceMapper(parent, nodeAndSmap.sortedRanges, nodeAndSmap.classSMAP.sourceInfo)
}
} }
} }
@@ -42,7 +42,7 @@ class InlineCodegenForDefaultBody(
val nodeAndSmap = InlineCodegen.createInlineMethodNode( val nodeAndSmap = InlineCodegen.createInlineMethodNode(
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline 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 node = nodeAndSmap.node
val transformedMethod = MethodNode( val transformedMethod = MethodNode(
@@ -284,10 +284,11 @@ class MethodInliner(
val childSourceMapper = val childSourceMapper =
if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) if (inliningContext.classRegeneration && !inliningContext.isInliningLambda)
NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) NestedSourceMapper(sourceMapper, lambdaSMAP)
else if (info is DefaultLambda) { else if (info is DefaultLambda)
NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP)
} else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node) else
SameFileNestedSourceMapper(sourceMapper.parent!!, info.node.classSMAP)
val inliner = MethodInliner( val inliner = MethodInliner(
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
@@ -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.LINE_SECTION
import org.jetbrains.kotlin.codegen.inline.SMAP.Companion.STRATA_SECTION import org.jetbrains.kotlin.codegen.inline.SMAP.Companion.STRATA_SECTION
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
@@ -86,8 +87,8 @@ class SMAPBuilder(
} }
open class NestedSourceMapper( open class NestedSourceMapper(
override val parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo override val parent: SourceMapper, protected val smap: SMAP
) : DefaultSourceMapper(sourceInfo) { ) : DefaultSourceMapper(smap.sourceInfo) {
private val visitedLines = TIntIntHashMap() private val visitedLines = TIntIntHashMap()
@@ -104,7 +105,7 @@ open class NestedSourceMapper(
mappedLineNumber mappedLineNumber
} else { } else {
val rangeForMapping = 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}") ?: error("Can't find range to map line $lineNumber in ${sourceInfo.source}: ${sourceInfo.pathOrCleanFQN}")
val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber) val sourceLineNumber = rangeForMapping.mapDestToSource(lineNumber)
val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path) val newLineNumber = parent.mapLineNumber(sourceLineNumber, rangeForMapping.parent!!.name, rangeForMapping.parent!!.path)
@@ -115,22 +116,12 @@ open class NestedSourceMapper(
newLineNumber 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( open class SameFileNestedSourceMapper(parent: SourceMapper, smap: SMAP) : NestedSourceMapper(parent, smap) {
parent: SourceMapper, smap: SMAPAndMethodNode
) : NestedSourceMapper(parent, smap.sortedRanges, smap.classSMAP.sourceInfo) {
override fun mapLineNumber(lineNumber: Int): Int { override fun mapLineNumber(lineNumber: Int): Int {
if (ranges.firstOrNull()?.contains(lineNumber) == true) { if (lineNumber <= smap.sourceInfo.linesInFile) {
//don't remap origin lambda line numbers // assuming the parent source mapper is for the same file, this line number does not need remapping
return lineNumber return lineNumber
} }
return super.mapLineNumber(lineNumber) return super.mapLineNumber(lineNumber)
@@ -250,20 +241,20 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper {
} }
class SMAP(val fileMappings: List<FileMapping>) { class SMAP(val fileMappings: List<FileMapping>) {
init { val sourceInfo: SourceInfo = run {
assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" } 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 private val intervals = fileMappings.flatMap { it.lineMappings }.sortedWith(RangeMapping.Comparator)
get() = fileMappings.first()
val intervals = fileMappings.flatMap { it.lineMappings }.sortedWith(RangeMapping.Comparator) fun findRange(lineNumber: Int): RangeMapping? {
val index = intervals.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { value, key ->
val sourceInfo: SourceInfo if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
})
init { return if (index < 0) null else intervals[index]
val defaultMapping = default.lineMappings.first()
sourceInfo = SourceInfo(default.name, default.path, defaultMapping.source + defaultMapping.range - 1)
} }
companion object { companion object {
@@ -274,6 +265,7 @@ class SMAP(val fileMappings: List<FileMapping>) {
} }
} }
data class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP)
class RawFileMapping(val name: String, val path: String) { class RawFileMapping(val name: String, val path: String) {
private val rangeMappings = arrayListOf<RangeMapping>() private val rangeMappings = arrayListOf<RangeMapping>()
@@ -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<RangeMapping> {
return InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().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]
}
}