JVM: refactor some SMAP-related classes
In particular, remove redundant copying from SMAPAndMethodNode (which also fails for empty methods).
This commit is contained in:
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user