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 4c16c4ffbd7..adefc5de2dd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAP.kt @@ -24,11 +24,12 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor import java.util.* //TODO join parameter -class SMAPBuilder(val source: String, - val path: String, - val fileMappings: List) { - - val header = "SMAP\n$source\nKotlin\n*S Kotlin" +class SMAPBuilder( + val source: String, + val path: String, + val fileMappings: List +) { + private val header = "SMAP\n$source\nKotlin\n*S Kotlin" fun build(): String? { var realMappings = fileMappings.filter { @@ -37,7 +38,7 @@ class SMAPBuilder(val source: String, } if (realMappings.isEmpty()) { - return null; + return null } val fileIds = "*F" + realMappings.mapIndexed { id, file -> "\n${file.toSMAPFile(id + 1)}" }.joinToString("") @@ -46,29 +47,29 @@ class SMAPBuilder(val source: String, return "$header\n$fileIds\n$lineMappings\n*E\n" } - - fun RangeMapping.toSMAP(fileId: Int): String { + private fun RangeMapping.toSMAP(fileId: Int): String { return if (range == 1) "$source#$fileId:$dest" else "$source#$fileId,$range:$dest" } - fun FileMapping.toSMAPFile(id: Int): String { - this.id = id; + private fun FileMapping.toSMAPFile(id: Int): String { + this.id = id return "+ $id $name\n$path" } //TODO inline - fun FileMapping.toSMAPMapping(): String { + private fun FileMapping.toSMAPMapping(): String { return lineMappings.joinToString("") { "\n${it.toSMAP(id)}" } } } -open class NestedSourceMapper(parent: SourceMapper, val ranges: List, sourceInfo: SourceInfo) : DefaultSourceMapper(sourceInfo, parent) { - +open class NestedSourceMapper( + parent: SourceMapper, val ranges: List, sourceInfo: SourceInfo +) : DefaultSourceMapper(sourceInfo, parent) { override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) { - val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) { + val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator { value, key -> - if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key) - } + if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) + }) if (index < 0) { parent!!.visitSource(sourceInfo.source, sourceInfo.pathOrCleanFQN) parent!!.visitLineNumber(iv, lineNumber, start) @@ -81,8 +82,9 @@ open class NestedSourceMapper(parent: SourceMapper, val ranges: List - if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key) - } + if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) + }) if (index >= 0) { - val fmapping = ranges[index].parent!! - if (fmapping.path == origin.path && fmapping.name == origin.name) { + val mapping = ranges[index].parent!! + if (mapping.path == origin.path && mapping.name == origin.name) { parent!!.visitOrigin() parent!!.visitLineNumber(iv, lineNumber, start) return @@ -117,7 +119,6 @@ open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNod } interface SourceMapper { - val resultMappings: List val parent: SourceMapper? @@ -138,7 +139,6 @@ interface SourceMapper { } companion object { - fun flushToClassBuilder(mapper: SourceMapper, v: ClassBuilder) { for (fileMapping in mapper.resultMappings) { v.addSMAP(fileMapping) @@ -179,15 +179,10 @@ object IdenticalSourceMapper : SourceMapper { } open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper { - protected var maxUsedValue: Int = sourceInfo.linesInFile - var lastVisited: RawFileMapping? = null - private var lastMappedWithChanges: RawFileMapping? = null - - var fileMappings: LinkedHashMap = linkedMapOf() - + private var fileMappings: LinkedHashMap = linkedMapOf() protected val origin: RawFileMapping init { @@ -205,7 +200,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: get() = fileMappings.values.map { it.toFileMapping() } override fun visitSource(name: String, path: String) { - lastVisited = fileMappings.getOrPut(createKey(name, path), { RawFileMapping(name, path) }) + lastVisited = fileMappings.getOrPut(createKey(name, path)) { RawFileMapping(name, path) } } override fun visitOrigin() { @@ -232,7 +227,6 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: } } -/*Source Mapping*/ class SMAP(val fileMappings: List) { init { assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" } @@ -251,9 +245,7 @@ class SMAP(val fileMappings: List) { companion object { val FILE_SECTION = "*F" - val LINE_SECTION = "*L" - val END = "*E" } } @@ -262,15 +254,14 @@ class RawFileMapping(val name: String, val path: String) { private val lineMappings = TIntIntHashMap() private val rangeMappings = arrayListOf() - private var lastMappedWithNewIndex = -1000; + private var lastMappedWithNewIndex = -1000 - fun toFileMapping(): FileMapping { - val fileMapping = FileMapping(name, path) - for (range in rangeMappings) { - fileMapping.addRangeMapping(range) - } - return fileMapping - } + fun toFileMapping() = + FileMapping(name, path).apply { + for (range in rangeMappings) { + addRangeMapping(range) + } + } fun initRange(start: Int, end: Int) { assert(lineMappings.isEmpty) { "initRange should only be called for empty mapping" } @@ -315,14 +306,13 @@ class RawFileMapping(val name: String, val path: String) { private fun couldFoldInRange(first: Int, second: Int): Boolean { //TODO val delta = second - first - return delta > 0 && delta <= 10; + return delta > 0 && delta <= 10 } } open class FileMapping(val name: String, val path: String) { val lineMappings = arrayListOf() - - var id = -1; + var id = -1 fun addRangeMapping(lineMapping: RangeMapping) { lineMappings.add(lineMapping) @@ -338,12 +328,10 @@ open class FileMapping(val name: String, val path: String) { //TODO comparable data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) { - - var parent: FileMapping? = null; - + var parent: FileMapping? = null private val skip = source == -1 && dest == -1 - fun contains(destLine: Int): Boolean { + operator fun contains(destLine: Int): Boolean { return if (skip) true else dest <= destLine && destLine < dest + range } @@ -368,4 +356,4 @@ data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) { companion object { val SKIP = RangeMapping(-1, -1, 1) } -} \ No newline at end of file +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt index 250e6ffe377..4a911b60a5f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPAndMethodNode.kt @@ -16,30 +16,26 @@ package org.jetbrains.kotlin.codegen.inline -import org.jetbrains.org.objectweb.asm.tree.MethodNode import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence import org.jetbrains.org.objectweb.asm.tree.LineNumberNode -import org.jetbrains.org.objectweb.asm.Label -import kotlin.properties.Delegates -import java.util.Collections -import kotlin.properties.ReadOnlyProperty -import org.jetbrains.kotlin.codegen.SourceInfo +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import java.util.* //TODO comment class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) { - - val lineNumbers = - InsnSequence(node.instructions.first, null).filterIsInstance().map { - val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) { + private val lineNumbers = + InsnSequence(node.instructions.first, null).filterIsInstance().map { node -> + val index = classSMAP.intervals.binarySearch(RangeMapping(node.line, node.line, 1), Comparator { value, key -> - if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key) + if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key) + }) + if (index < 0) { + error("Unmapped label in inlined function $node ${node.line}") } - if (index < 0) - throw IllegalStateException("Unmapped label in inlined function $it ${it.line}") - LabelAndMapping(it, classSMAP.intervals[index]) + LabelAndMapping(node, classSMAP.intervals[index]) }.toList() - val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList(); + val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList() } -class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping) \ No newline at end of file +class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping) 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 99249300cc6..2d2c7168fa3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt @@ -16,51 +16,49 @@ package org.jetbrains.kotlin.codegen.inline -import com.intellij.util.SmartFMap - object SMAPParser { - + /*null smap means that there is no any debug info in file (e.g. sourceName)*/ @JvmStatic - /*null smap means that there is no any debug info in file (e.g. sourceName)*/ fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP { - if (mappingInfo == null || mappingInfo.isEmpty()) { - val fm: FileMapping - if (source == null || source.isEmpty()) { - fm = FileMapping.SKIP - } - else { - fm = FileMapping(source, path) - if (methodStartLine <= methodEndLine) { - //one to one - fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)) - } - } - return SMAP(listOf(fm)) + fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP { + if (mappingInfo != null && mappingInfo.isNotEmpty()) { + return parse(mappingInfo) } - return parse(mappingInfo) + + val mapping = + if (source == null || source.isEmpty()) + FileMapping.SKIP + else + FileMapping(source, path).apply { + if (methodStartLine <= methodEndLine) { + //one to one + addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)) + } + } + + return SMAP(listOf(mapping)) } - @JvmStatic fun parse(mappingInfo: String): SMAP { + @JvmStatic + fun parse(mappingInfo: String): SMAP { val fileMappings = linkedMapOf() val fileSectionStart = mappingInfo.indexOf(SMAP.FILE_SECTION) + SMAP.FILE_SECTION.length val lineSectionAnchor = mappingInfo.indexOf(SMAP.LINE_SECTION) val files = mappingInfo.substring(fileSectionStart, lineSectionAnchor) - val fileEntries = files.trim().split('+') for (fileDeclaration in fileEntries) { - if (fileDeclaration == "") continue; + if (fileDeclaration == "") continue val fileInternalName = fileDeclaration.trim() val indexEnd = fileInternalName.indexOf(' ') - val fileIndex = Integer.valueOf(fileInternalName.substring(0, indexEnd)) + val fileIndex = fileInternalName.substring(0, indexEnd).toInt() val newLine = fileInternalName.indexOf('\n') val fileName = fileInternalName.substring(indexEnd + 1, newLine) - fileMappings.put(fileIndex, FileMapping(fileName, fileInternalName.substring(newLine + 1).trim())) + fileMappings[fileIndex] = FileMapping(fileName, fileInternalName.substring(newLine + 1).trim()) } - val lines = mappingInfo.substring(lineSectionAnchor + SMAP.LINE_SECTION.length, mappingInfo.indexOf(SMAP.END)).trim().split('\n') for (lineMapping in lines) { /*only simple mapping now*/ @@ -69,14 +67,14 @@ object SMAPParser { var rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it } val fileSeparator = lineMapping.indexOf('#') - val originalIndex = Integer.valueOf(originalPart.substring(0, fileSeparator)) - val range = if (rangeSeparator == targetSplit) 1 else Integer.valueOf(originalPart.substring(rangeSeparator + 1, targetSplit)) + val originalIndex = originalPart.substring(0, fileSeparator).toInt() + val range = if (rangeSeparator == targetSplit) 1 else originalPart.substring(rangeSeparator + 1, targetSplit).toInt() - val fileIndex = Integer.valueOf(lineMapping.substring(fileSeparator + 1, rangeSeparator)) - val targetIndex = Integer.valueOf(lineMapping.substring(targetSplit + 1)) + val fileIndex = lineMapping.substring(fileSeparator + 1, rangeSeparator).toInt() + val targetIndex = lineMapping.substring(targetSplit + 1).toInt() fileMappings[fileIndex]!!.addRangeMapping(RangeMapping(originalIndex, targetIndex, range)) } return SMAP(fileMappings.values.toList()) } -} \ No newline at end of file +}