JVM: separate the two kinds of source mappers
* a writing source mapper has `mapLineNumber(line, file, class)` that inserts a new SMAP entry and returns a fake line number from it; * a copying source mapper has `mapLineNumber(line)` that uses an existing SMAP to resolve the line number and call the former method on a different source mapper; * those two types are disjoint.
This commit is contained in:
@@ -13,9 +13,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.inline.NameGenerator;
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
@@ -88,7 +88,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
private NameGenerator inlineNameGenerator;
|
||||
private boolean jvmAssertFieldGenerated;
|
||||
|
||||
private DefaultSourceMapper sourceMapper;
|
||||
private SourceMapper sourceMapper;
|
||||
|
||||
public MemberCodegen(
|
||||
@NotNull GenerationState state,
|
||||
@@ -722,10 +722,10 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DefaultSourceMapper getOrCreateSourceMapper() {
|
||||
public SourceMapper getOrCreateSourceMapper() {
|
||||
if (sourceMapper == null) {
|
||||
// note: this is used in InlineCodegen and the element is always physical (KtElement) there
|
||||
sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
|
||||
sourceMapper = new SourceMapper(SourceInfo.Companion.createInfo((KtElement)element, getClassName()));
|
||||
}
|
||||
return sourceMapper;
|
||||
}
|
||||
|
||||
+16
-20
@@ -42,8 +42,7 @@ class AnonymousObjectTransformer(
|
||||
private val fieldNames = hashMapOf<String, MutableList<String>>()
|
||||
|
||||
private var constructor: MethodNode? = null
|
||||
private var sourceInfo: String? = null
|
||||
private var debugInfo: String? = null
|
||||
private lateinit var sourceMap: SMAP
|
||||
private lateinit var sourceMapper: SourceMapper
|
||||
private val languageVersionSettings = inliningContext.state.languageVersionSettings
|
||||
|
||||
@@ -56,6 +55,8 @@ class AnonymousObjectTransformer(
|
||||
val methodsToTransform = ArrayList<MethodNode>()
|
||||
val metadataReader = ReadKotlinClassHeaderAnnotationVisitor()
|
||||
lateinit var superClassName: String
|
||||
var sourceInfo: String? = null
|
||||
var debugInfo: String? = null
|
||||
|
||||
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||
@@ -113,22 +114,13 @@ class AnonymousObjectTransformer(
|
||||
override fun visitEnd() {}
|
||||
}, ClassReader.SKIP_FRAMES)
|
||||
|
||||
if (!inliningContext.isInliningLambda) {
|
||||
sourceMapper = if (debugInfo != null && !debugInfo!!.isEmpty()) {
|
||||
SourceMapper.createFromSmap(SMAPParser.parse(debugInfo!!))
|
||||
} else {
|
||||
//seems we can't do any clever mapping cause we don't know any about original class name
|
||||
IdenticalSourceMapper
|
||||
}
|
||||
if (sourceInfo != null && !GENERATE_SMAP) {
|
||||
classBuilder.visitSource(sourceInfo!!, debugInfo)
|
||||
}
|
||||
} else {
|
||||
if (sourceInfo != null) {
|
||||
classBuilder.visitSource(sourceInfo!!, debugInfo)
|
||||
}
|
||||
sourceMapper = IdenticalSourceMapper
|
||||
}
|
||||
// When regenerating objects in lambdas, we have to pass the SMAP straight through and keep
|
||||
// the original line numbers because SMAPParser does not parse call site markers.
|
||||
val debugInfoToParse = if (inliningContext.isInliningLambda) null else debugInfo
|
||||
sourceMap = SMAPParser.parseOrCreateDefault(debugInfoToParse, sourceInfo, oldObjectType.internalName, 1, 65535)
|
||||
// TODO source info should be for the file into which the function is being inlined, else we cannot
|
||||
// generate correct call site markers for lambdas inlined into the object
|
||||
sourceMapper = SourceMapper(sourceMap.sourceInfo.takeIf { debugInfoToParse?.isEmpty() == false })
|
||||
|
||||
val allCapturedParamBuilder = ParametersBuilder.newBuilder()
|
||||
val constructorParamBuilder = ParametersBuilder.newBuilder()
|
||||
@@ -183,7 +175,11 @@ class AnonymousObjectTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
|
||||
if (GENERATE_SMAP && !inliningContext.isInliningLambda) {
|
||||
classBuilder.visitSMAP(sourceMapper, !state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
|
||||
} else if (sourceInfo != null) {
|
||||
classBuilder.visitSource(sourceInfo!!, debugInfo)
|
||||
}
|
||||
|
||||
val visitor = classBuilder.visitor
|
||||
innerClassNodes.forEach { node ->
|
||||
@@ -296,7 +292,7 @@ class AnonymousObjectTransformer(
|
||||
remapper,
|
||||
isSameModule,
|
||||
"Transformer for " + transformationInfo.oldClassName,
|
||||
sourceMapper,
|
||||
SourceMapCopier(sourceMapper, sourceMap, keepCallSites = inliningContext.isInliningLambda),
|
||||
InlineCallSiteInfo(
|
||||
transformationInfo.oldClassName,
|
||||
sourceNode.name,
|
||||
|
||||
@@ -30,14 +30,14 @@ import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getLoadStoreArgSize;
|
||||
|
||||
public class InlineAdapter extends InstructionAdapter {
|
||||
private final SourceMapper sourceMapper;
|
||||
private final SourceMapCopier sourceMapper;
|
||||
private final List<CatchBlock> blocks = new ArrayList<>();
|
||||
|
||||
private boolean isLambdaInlining = false;
|
||||
private int nextLocalIndex = 0;
|
||||
private int nextLocalIndexBeforeInline = -1;
|
||||
|
||||
public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapper sourceMapper) {
|
||||
public InlineAdapter(@NotNull MethodVisitor mv, int localsSize, @NotNull SourceMapCopier sourceMapper) {
|
||||
super(Opcodes.API_VERSION, mv);
|
||||
this.nextLocalIndex = localsSize;
|
||||
this.sourceMapper = sourceMapper;
|
||||
|
||||
@@ -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,
|
||||
NestedSourceMapper(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo,
|
||||
SourceMapCopier(defaultSourceMapper, nodeAndSmap.classSMAP), info.callSiteInfo,
|
||||
if (functionDescriptor.isInlineOnly()) InlineOnlySmapSkipper(codegen) else null,
|
||||
!isInlinedToInlineFunInKotlinRuntime()
|
||||
) //with captured
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ class InlineCodegenForDefaultBody(
|
||||
val nodeAndSmap = InlineCodegen.createInlineMethodNode(
|
||||
function, methodOwner, jvmSignature, callDefault, null, codegen.typeSystem, state, sourceCompilerForInline
|
||||
)
|
||||
val childSourceMapper = NestedSourceMapper(sourceMapper, nodeAndSmap.classSMAP, sameFile = true)
|
||||
val childSourceMapper = SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, keepCallSites = true)
|
||||
|
||||
val node = nodeAndSmap.node
|
||||
val transformedMethod = MethodNode(
|
||||
|
||||
@@ -54,7 +54,7 @@ class MethodInliner(
|
||||
private val nodeRemapper: FieldRemapper,
|
||||
private val isSameModule: Boolean,
|
||||
private val errorPrefix: String,
|
||||
private val sourceMapper: SourceMapper,
|
||||
private val sourceMapper: SourceMapCopier,
|
||||
private val inlineCallSiteInfo: InlineCallSiteInfo,
|
||||
private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root
|
||||
private val shouldPreprocessApiVersionCalls: Boolean = false
|
||||
@@ -288,20 +288,17 @@ class MethodInliner(
|
||||
)
|
||||
|
||||
setLambdaInlining(true)
|
||||
val lambdaSMAP = info.node.classSMAP
|
||||
|
||||
val childSourceMapper =
|
||||
if (inliningContext.classRegeneration && !inliningContext.isInliningLambda)
|
||||
NestedSourceMapper(sourceMapper, lambdaSMAP)
|
||||
else
|
||||
NestedSourceMapper(sourceMapper.parent!!, lambdaSMAP, sameFile = info !is DefaultLambda)
|
||||
|
||||
// TODO we cannot keep call site markers when inlining lambdas into objects because AnonymousObjectTransformer
|
||||
// uses the original's source info, thus KotlinDebug would point to the file with the inline function
|
||||
// instead of the one with the call.
|
||||
val sameFile = info !is DefaultLambda && (!inliningContext.classRegeneration || inliningContext.isInliningLambda)
|
||||
val inliner = MethodInliner(
|
||||
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
|
||||
newCapturedRemapper,
|
||||
if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/,
|
||||
"Lambda inlining " + info.lambdaClassType.internalName,
|
||||
childSourceMapper, inlineCallSiteInfo, null
|
||||
SourceMapCopier(sourceMapper.parent, info.node.classSMAP, sameFile), inlineCallSiteInfo, null
|
||||
)
|
||||
|
||||
val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift)
|
||||
|
||||
@@ -63,24 +63,15 @@ object SMAPBuilder {
|
||||
lineMappings.joinToString("") { it.toSMAP(id) }
|
||||
}
|
||||
|
||||
class NestedSourceMapper(
|
||||
override val parent: SourceMapper, private val smap: SMAP, private val sameFile: Boolean = false
|
||||
) : DefaultSourceMapper(smap.sourceInfo) {
|
||||
|
||||
class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, private val keepCallSites: Boolean = false) {
|
||||
private val visitedLines = TIntIntHashMap()
|
||||
|
||||
private var lastVisitedRange: RangeMapping? = null
|
||||
|
||||
override fun mapLineNumber(lineNumber: Int): Int {
|
||||
fun mapLineNumber(lineNumber: Int): Int {
|
||||
if (lineNumber in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) {
|
||||
return lineNumber
|
||||
}
|
||||
|
||||
if (sameFile && lineNumber <= smap.sourceInfo.linesInFile) {
|
||||
// assuming the parent source mapper is for the same file, this line number does not need remapping
|
||||
return lineNumber
|
||||
}
|
||||
|
||||
val mappedLineNumber = visitedLines.get(lineNumber)
|
||||
if (mappedLineNumber > 0) {
|
||||
return mappedLineNumber
|
||||
@@ -88,99 +79,41 @@ class NestedSourceMapper(
|
||||
|
||||
val range = lastVisitedRange?.takeIf { lineNumber in it }
|
||||
?: 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 ${smap.sourceInfo.source}: ${smap.sourceInfo.pathOrCleanFQN}")
|
||||
val sourceLineNumber = range.mapDestToSource(lineNumber)
|
||||
val newLineNumber = if (sameFile)
|
||||
parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path, range.callSiteMarker)
|
||||
else
|
||||
parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path)
|
||||
if (newLineNumber > 0) {
|
||||
visitedLines.put(lineNumber, newLineNumber)
|
||||
if (sourceLineNumber < 0) {
|
||||
return -1
|
||||
}
|
||||
val callSiteMarker = if (keepCallSites) range.callSiteMarker else parent.callSiteMarker
|
||||
val newLineNumber = parent.mapLineNumber(sourceLineNumber, range.parent.name, range.parent.path, callSiteMarker)
|
||||
visitedLines.put(lineNumber, newLineNumber)
|
||||
lastVisitedRange = range
|
||||
return newLineNumber
|
||||
}
|
||||
}
|
||||
|
||||
interface SourceMapper {
|
||||
val resultMappings: List<FileMapping>
|
||||
val parent: SourceMapper?
|
||||
get() = null
|
||||
|
||||
fun mapLineNumber(lineNumber: Int): Int
|
||||
|
||||
fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int =
|
||||
mapLineNumber(source, sourceName, sourcePath, null)
|
||||
|
||||
fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int
|
||||
|
||||
companion object {
|
||||
fun createFromSmap(smap: SMAP): SourceMapper {
|
||||
return DefaultSourceMapper(smap.sourceInfo, smap.fileMappings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object IdenticalSourceMapper : SourceMapper {
|
||||
override val resultMappings: List<FileMapping>
|
||||
get() = emptyList()
|
||||
|
||||
override val parent: SourceMapper?
|
||||
get() = null
|
||||
|
||||
override fun mapLineNumber(lineNumber: Int) = lineNumber
|
||||
|
||||
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int =
|
||||
throw UnsupportedOperationException(
|
||||
"IdenticalSourceMapper#mapLineNumber($source, $sourceName, $sourcePath)\n"
|
||||
+ "This mapper should not encounter a line number out of range of the current file.\n"
|
||||
+ "This indicates that SMAP generation is missed somewhere."
|
||||
)
|
||||
}
|
||||
|
||||
data class CallSiteMarker(val lineNumber: Int)
|
||||
|
||||
open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper {
|
||||
private var maxUsedValue: Int = sourceInfo.linesInFile
|
||||
class SourceMapper(val sourceInfo: SourceInfo?) {
|
||||
private var maxUsedValue: Int = sourceInfo?.linesInFile ?: 0
|
||||
private var fileMappings: LinkedHashMap<Pair<String, String>, FileMapping> = linkedMapOf()
|
||||
|
||||
var callSiteMarker: CallSiteMarker? = null
|
||||
|
||||
override val resultMappings: List<FileMapping>
|
||||
val resultMappings: List<FileMapping>
|
||||
get() = fileMappings.values.toList()
|
||||
|
||||
init {
|
||||
// Explicitly map the file to itself.
|
||||
getOrRegisterNewSource(sourceInfo.source, sourceInfo.pathOrCleanFQN).mapNewInterval(1, 1, sourceInfo.linesInFile)
|
||||
}
|
||||
|
||||
constructor(sourceInfo: SourceInfo, fileMappings: List<FileMapping>) : this(sourceInfo) {
|
||||
// The first mapping is already created in the `init` block above.
|
||||
fileMappings.asSequence().drop(1)
|
||||
.forEach { fileMapping ->
|
||||
val newFileMapping = getOrRegisterNewSource(fileMapping.name, fileMapping.path)
|
||||
fileMapping.lineMappings.forEach {
|
||||
newFileMapping.mapNewInterval(it.source, it.dest, it.range)
|
||||
maxUsedValue = max(it.maxDest, maxUsedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrRegisterNewSource(name: String, path: String): FileMapping {
|
||||
return fileMappings.getOrPut(name to path) { FileMapping(name, path) }
|
||||
}
|
||||
|
||||
//TODO maybe add assertion that linenumber contained in fileMappings
|
||||
override fun mapLineNumber(lineNumber: Int): Int = lineNumber
|
||||
|
||||
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String): Int =
|
||||
mapLineNumber(source, sourceName, sourcePath, callSiteMarker)
|
||||
|
||||
override fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int {
|
||||
if (source < 0) {
|
||||
//no source information, so just skip this linenumber
|
||||
return -1
|
||||
sourceInfo?.let {
|
||||
// Explicitly map the file to itself -- we'll probably need a lot of lines from it, so this will produce less ranges.
|
||||
getOrRegisterNewSource(it.source, it.pathOrCleanFQN).mapNewInterval(1, 1, it.linesInFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrRegisterNewSource(name: String, path: String): FileMapping =
|
||||
fileMappings.getOrPut(name to path) { FileMapping(name, path) }
|
||||
|
||||
fun mapLineNumber(source: Int, sourceName: String, sourcePath: String, callSiteMarker: CallSiteMarker?): Int {
|
||||
val fileMapping = getOrRegisterNewSource(sourceName, sourcePath)
|
||||
val mappedLineIndex = fileMapping.mapNewLineNumber(source, maxUsedValue, callSiteMarker)
|
||||
maxUsedValue = max(maxUsedValue, mappedLineIndex)
|
||||
@@ -188,13 +121,12 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo) : SourceMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun FileMapping.toSourceInfo(): SourceInfo =
|
||||
SourceInfo(name, path, lineMappings.fold(0) { result, mapping -> max(result, mapping.source + mapping.range - 1) })
|
||||
|
||||
class SMAP(val fileMappings: List<FileMapping>) {
|
||||
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 sourceInfo: SourceInfo
|
||||
get() = fileMappings.firstOrNull()?.toSourceInfo() ?: throw AssertionError("no files mapped")
|
||||
|
||||
// assuming disjoint line mappings (otherwise binary search can't be used anyway)
|
||||
private val intervals = fileMappings.flatMap { it.lineMappings }.sortedBy { it.dest }
|
||||
@@ -218,18 +150,19 @@ class FileMapping(val name: String, val path: String) {
|
||||
val lineMappings = arrayListOf<RangeMapping>()
|
||||
|
||||
fun mapNewLineNumber(source: Int, currentIndex: Int, callSiteMarker: CallSiteMarker?): Int {
|
||||
var mapping = lineMappings.lastOrNull()
|
||||
if (mapping != null && mapping.callSiteMarker == callSiteMarker &&
|
||||
(source - mapping.source) in 0 until mapping.range + (if (mapping.maxDest == currentIndex) 10 else 0)
|
||||
) {
|
||||
// Save some space in the SMAP by reusing (or extending if it's the last one) the existing range.
|
||||
mapping.range = max(mapping.range, source - mapping.source + 1)
|
||||
} else {
|
||||
mapping = mapNewInterval(source, currentIndex + 1, 1, callSiteMarker)
|
||||
}
|
||||
// Save some space in the SMAP by reusing (or extending if it's the last one) the existing range.
|
||||
// TODO some *other* range may already cover `source`; probably too slow to check them all though.
|
||||
// Maybe keep the list ordered by `source` and use binary search to locate the closest range on the left?
|
||||
val mapping = lineMappings.lastOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSiteMarker) }
|
||||
?: lineMappings.firstOrNull()?.takeIf { it.canReuseFor(source, currentIndex, callSiteMarker) }
|
||||
?: mapNewInterval(source, currentIndex + 1, 1, callSiteMarker)
|
||||
mapping.range = max(mapping.range, source - mapping.source + 1)
|
||||
return mapping.mapSourceToDest(source)
|
||||
}
|
||||
|
||||
private fun RangeMapping.canReuseFor(newSource: Int, globalMaxDest: Int, newCallSite: CallSiteMarker?): Boolean =
|
||||
callSiteMarker == newCallSite && (newSource - source) in 0 until range + (if (maxDest == globalMaxDest) 10 else 0)
|
||||
|
||||
fun mapNewInterval(source: Int, dest: Int, range: Int, callSiteMarker: CallSiteMarker? = null): RangeMapping =
|
||||
RangeMapping(source, dest, range, callSiteMarker, parent = this).also { lineMappings.add(it) }
|
||||
|
||||
|
||||
@@ -23,18 +23,12 @@ object SMAPParser {
|
||||
if (mappingInfo != null && mappingInfo.isNotEmpty()) {
|
||||
return parse(mappingInfo)
|
||||
}
|
||||
|
||||
val mapping =
|
||||
if (source == null || source.isEmpty() || methodStartLine > methodEndLine)
|
||||
FileMapping.SKIP
|
||||
else
|
||||
FileMapping(source, path).apply {
|
||||
if (methodStartLine <= methodEndLine) {
|
||||
//one to one
|
||||
mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)
|
||||
}
|
||||
}
|
||||
|
||||
if (source == null || source.isEmpty() || methodStartLine > methodEndLine) {
|
||||
return SMAP(listOf(FileMapping.SKIP))
|
||||
}
|
||||
val mapping = FileMapping(source, path).apply {
|
||||
mapNewInterval(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1)
|
||||
}
|
||||
return SMAP(listOf(mapping))
|
||||
}
|
||||
|
||||
|
||||
+3
-14
@@ -46,7 +46,7 @@ interface SourceCompilerForInline {
|
||||
|
||||
val inlineCallSiteInfo: InlineCallSiteInfo
|
||||
|
||||
val lazySourceMapper: DefaultSourceMapper
|
||||
val lazySourceMapper: SourceMapper
|
||||
|
||||
fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode
|
||||
|
||||
@@ -212,18 +212,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
|
||||
}
|
||||
|
||||
return createSMAPWithDefaultMapping(expression, parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
}
|
||||
|
||||
|
||||
private fun createSMAPWithDefaultMapping(
|
||||
declaration: KtExpression,
|
||||
mappings: List<FileMapping>
|
||||
): SMAP {
|
||||
val containingFile = declaration.containingFile
|
||||
CodegenUtil.getLineNumberForElement(containingFile, true) ?: error("Couldn't extract line count in $containingFile")
|
||||
|
||||
return SMAP(mappings)
|
||||
return SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -310,7 +299,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
|
||||
)
|
||||
createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
SMAP(parentCodegen.orCreateSourceMapper.resultMappings)
|
||||
} else {
|
||||
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
|
||||
}
|
||||
|
||||
+3
-3
@@ -148,7 +148,7 @@ abstract class ClassCodegen protected constructor(
|
||||
if (writeSourceMap) {
|
||||
visitor.visitSMAP(smap, !context.state.languageVersionSettings.supportsFeature(LanguageFeature.CorrectSourceMappingSyntax))
|
||||
} else {
|
||||
visitor.visitSource(smap.sourceInfo.source, null)
|
||||
visitor.visitSource(smap.sourceInfo!!.source, null)
|
||||
}
|
||||
|
||||
visitor.done()
|
||||
@@ -269,7 +269,7 @@ abstract class ClassCodegen protected constructor(
|
||||
|
||||
protected abstract fun bindMethodMetadata(method: IrFunction, signature: Method)
|
||||
|
||||
private fun generateMethod(method: IrFunction, classSMAP: DefaultSourceMapper) {
|
||||
private fun generateMethod(method: IrFunction, classSMAP: SourceMapper) {
|
||||
if (method.isFakeOverride) {
|
||||
jvmSignatureClashDetector.trackFakeOverrideMethod(method)
|
||||
return
|
||||
@@ -281,7 +281,7 @@ abstract class ClassCodegen protected constructor(
|
||||
method.origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE
|
||||
)
|
||||
val mv = with(node) { visitor.newMethod(method.OtherOrigin, access, name, desc, signature, exceptions.toTypedArray()) }
|
||||
val smapCopier = NestedSourceMapper(classSMAP, smap, sameFile = true)
|
||||
val smapCopier = SourceMapCopier(classSMAP, smap, keepCallSites = true)
|
||||
val smapCopyingVisitor = object : MethodVisitor(Opcodes.API_VERSION, mv) {
|
||||
override fun visitLineNumber(line: Int, start: Label) =
|
||||
super.visitLineNumber(smapCopier.mapLineNumber(line), start)
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ class ExpressionCodegen(
|
||||
val mv: InstructionAdapter,
|
||||
val classCodegen: ClassCodegen,
|
||||
val inlinedInto: ExpressionCodegen?,
|
||||
val smap: DefaultSourceMapper
|
||||
val smap: SourceMapper
|
||||
) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen {
|
||||
|
||||
var finallyDepth = 0
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ class IrSourceCompilerForInline(
|
||||
)
|
||||
}
|
||||
|
||||
override val lazySourceMapper: DefaultSourceMapper
|
||||
override val lazySourceMapper: SourceMapper
|
||||
get() = codegen.smap.also { codegen.classCodegen.writeSourceMap = true }
|
||||
|
||||
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode =
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
@@ -80,14 +80,14 @@ val IrDeclaration.fileParent: IrFile
|
||||
internal val DeclarationDescriptorWithSource.psiElement: PsiElement?
|
||||
get() = (source as? PsiSourceElement)?.psi
|
||||
|
||||
fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper {
|
||||
fun JvmBackendContext.getSourceMapper(declaration: IrClass): SourceMapper {
|
||||
val sourceManager = this.psiSourceManager
|
||||
val fileEntry = sourceManager.getFileEntry(declaration.fileParent)
|
||||
// NOTE: apparently inliner requires the source range to cover the
|
||||
// whole file the class is declared in rather than the class only.
|
||||
// TODO: revise
|
||||
val endLineNumber = fileEntry?.getSourceRangeInfo(0, fileEntry.maxOffset)?.endLineNumber ?: 0
|
||||
return DefaultSourceMapper(
|
||||
return SourceMapper(
|
||||
SourceInfo.createInfoForIr(
|
||||
endLineNumber + 1,
|
||||
typeMapper.mapClass(declaration).internalName,
|
||||
|
||||
+4
-3
@@ -74,7 +74,8 @@ test/_1Kt
|
||||
_2Kt
|
||||
*L
|
||||
1#1,18:1
|
||||
14#2,2:19
|
||||
10#2:21
|
||||
7#3:22
|
||||
14#2:19
|
||||
10#2:20
|
||||
15#2:22
|
||||
7#3:21
|
||||
*E
|
||||
+3
-2
@@ -90,6 +90,7 @@ test/_1Kt
|
||||
_2Kt
|
||||
*L
|
||||
1#1,19:1
|
||||
7#2,3:20
|
||||
9#3,2:23
|
||||
7#2,2:20
|
||||
9#2:24
|
||||
9#3,2:22
|
||||
*E
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/so
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:14:13: error: a suspension point at SourceKt$test$2.invokeSuspend(source.kt:17) is inside a critical section
|
||||
builder {
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:9: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:62) is inside a critical section
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:24:9: error: a suspension point at SourceKt$test$3$invokeSuspend$$inlined$withCrossinline$2.invokeSuspend(source.kt:60) is inside a critical section
|
||||
withCrossinline {
|
||||
^
|
||||
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:50:34: error: a suspension point at SourceKt$withCrossinline$c$1.invokeSuspend(source.kt:52) is inside a critical section
|
||||
|
||||
Reference in New Issue
Block a user