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(
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<out T : BaseExpressionCodegen>(
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<out T : BaseExpressionCodegen>(
}
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(
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(
@@ -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),
@@ -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<RangeMapping>, 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<FileMapping>) {
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<FileMapping>) {
}
}
data class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP)
class RawFileMapping(val name: String, val path: String) {
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]
}
}