JVM: remove InlineOnlySmapSkipper
1. the class didn't make much sense anyway; 2. the same code is useful for default lambdas, which can also have a line number equal to the call site.
This commit is contained in:
+1
-2
@@ -335,8 +335,7 @@ class AnonymousObjectTransformer(
|
||||
inliningContext.callSiteInfo.inlineScopeVisibility,
|
||||
inliningContext.callSiteInfo.file,
|
||||
inliningContext.callSiteInfo.lineNumber
|
||||
),
|
||||
null
|
||||
)
|
||||
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
|
||||
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
|
||||
deferringVisitor.visitMaxs(-1, -1)
|
||||
|
||||
@@ -106,7 +106,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
node, parameters, info, FieldRemapper(null, null, parameters), sourceCompiler.isCallInsideSameModuleAsCallee,
|
||||
"Method inlining " + sourceCompiler.callElementText,
|
||||
SourceMapCopier(sourceMapper, nodeAndSmap.classSMAP, callSite),
|
||||
info.callSiteInfo, if (isInlineOnly) InlineOnlySmapSkipper(codegen) else null,
|
||||
info.callSiteInfo, isInlineOnly,
|
||||
!isInlinedToInlineFunInKotlinRuntime()
|
||||
) //with captured
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class MethodInliner(
|
||||
private val errorPrefix: String,
|
||||
private val sourceMapper: SourceMapCopier,
|
||||
private val inlineCallSiteInfo: InlineCallSiteInfo,
|
||||
private val inlineOnlySmapSkipper: InlineOnlySmapSkipper?, //non null only for root
|
||||
private val overrideLineNumber: Boolean = false,
|
||||
private val shouldPreprocessApiVersionCalls: Boolean = false
|
||||
) {
|
||||
private val languageVersionSettings = inliningContext.state.languageVersionSettings
|
||||
@@ -154,9 +154,17 @@ class MethodInliner(
|
||||
|
||||
val fakeContinuationName = CoroutineTransformer.findFakeContinuationConstructorClassName(node)
|
||||
val markerShift = calcMarkerShift(parameters, node)
|
||||
var currentLineNumber = if (overrideLineNumber) sourceMapper.callSite!!.line else -1
|
||||
val lambdaInliner = object : InlineAdapter(remappingMethodAdapter, parameters.argsSizeOnStack, sourceMapper) {
|
||||
private var transformationInfo: TransformationInfo? = null
|
||||
|
||||
override fun visitLineNumber(line: Int, start: Label) {
|
||||
if (!overrideLineNumber) {
|
||||
currentLineNumber = line
|
||||
}
|
||||
super.visitLineNumber(line, start)
|
||||
}
|
||||
|
||||
private fun handleAnonymousObjectRegeneration() {
|
||||
transformationInfo = iterator.next()
|
||||
|
||||
@@ -250,10 +258,29 @@ class MethodInliner(
|
||||
store(valueParamShift, type)
|
||||
}
|
||||
if (expectedParameters.isEmpty()) {
|
||||
nop() // add something for a line number to bind onto
|
||||
nop() // add something for a line number to bind onto (TODO what line number?)
|
||||
}
|
||||
|
||||
val firstLine = info.node.node.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
|
||||
if (currentLineNumber >= 0 && firstLine == currentLineNumber) {
|
||||
// This can happen in two cases:
|
||||
// 1. `someInlineOnlyFunction { singleLineLambda }`: in this case line numbers are removed
|
||||
// from the inline function, so the entirety of its bytecode has the line number of
|
||||
// the call site;
|
||||
// 2. `inline fun someFunction(defaultLambda: ... = { ... }) = singleLineExpression`:
|
||||
// all of `someFunction`, including `defaultLambda` if no value is provided at call site,
|
||||
// has the line number of the declaration.
|
||||
// In those cases the debugger is unable to observe the boundary between the body of the function
|
||||
// and the inline lambda call, as they have the exact same line number. So to force a JDI
|
||||
// event we insert a fake line number separating those two real stretches. The event corresponding
|
||||
// to the fake line number itself should be ignored by the debugger though.
|
||||
val label = Label()
|
||||
val fakeLineNumber =
|
||||
sourceMapper.parent.mapSyntheticLineNumber(SourceMapper.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER)
|
||||
mv.visitLabel(label)
|
||||
mv.visitLineNumber(fakeLineNumber, label)
|
||||
}
|
||||
|
||||
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info.node.node, sourceMapper.parent)
|
||||
addInlineMarker(this, true)
|
||||
val lambdaParameters = info.addAllParameters(nodeRemapper)
|
||||
|
||||
@@ -270,7 +297,7 @@ class MethodInliner(
|
||||
newCapturedRemapper,
|
||||
if (info is DefaultLambda) isSameModule else true /*cause all nested objects in same module as lambda*/,
|
||||
"Lambda inlining " + info.lambdaClassType.internalName,
|
||||
SourceMapCopier(sourceMapper.parent, info.node.classSMAP, callSite), inlineCallSiteInfo, null
|
||||
SourceMapCopier(sourceMapper.parent, info.node.classSMAP, callSite), inlineCallSiteInfo
|
||||
)
|
||||
|
||||
val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift)
|
||||
@@ -284,7 +311,12 @@ class MethodInliner(
|
||||
StackValue.coerce(info.invokeMethod.returnType, info.invokeMethodReturnType, OBJECT_TYPE, nullableAnyType, this)
|
||||
setLambdaInlining(false)
|
||||
addInlineMarker(this, false)
|
||||
inlineOnlySmapSkipper?.onInlineLambdaEnd(remappingMethodAdapter)
|
||||
|
||||
if (overrideLineNumber) {
|
||||
val endLabel = Label()
|
||||
mv.visitLabel(endLabel)
|
||||
mv.visitLineNumber(currentLineNumber, endLabel)
|
||||
}
|
||||
} else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
||||
//TODO add proper message
|
||||
val newInfo = transformationInfo as? AnonymousObjectTransformationInfo ?: throw AssertionError(
|
||||
@@ -371,7 +403,7 @@ class MethodInliner(
|
||||
)
|
||||
|
||||
val transformationVisitor = object : InlineMethodInstructionAdapter(transformedNode) {
|
||||
private val GENERATE_DEBUG_INFO = GENERATE_SMAP && inlineOnlySmapSkipper == null
|
||||
private val GENERATE_DEBUG_INFO = GENERATE_SMAP && !overrideLineNumber
|
||||
|
||||
private val isInliningLambda = nodeRemapper.isInsideInliningLambda
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ class SourceMapper(val sourceInfo: SourceInfo?) {
|
||||
companion object {
|
||||
const val FAKE_FILE_NAME = "fake.kt"
|
||||
const val FAKE_PATH = "kotlin/jvm/internal/FakeKt"
|
||||
const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.ASSERTIONS_DISABLED_FIELD_NAME
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
||||
@@ -695,37 +694,6 @@ fun isFakeLocalVariableForInline(name: String): Boolean {
|
||||
|
||||
internal fun isThis0(name: String): Boolean = AsmUtil.CAPTURED_THIS_FIELD == name
|
||||
|
||||
class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
|
||||
private val callLineNumber = codegen.lastLineNumber
|
||||
|
||||
companion object {
|
||||
const val LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER = 1
|
||||
}
|
||||
|
||||
fun onInlineLambdaStart(mv: MethodVisitor, lambda: MethodNode, smap: SourceMapper) {
|
||||
val firstLine = lambda.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
|
||||
if (callLineNumber >= 0 && firstLine == callLineNumber) {
|
||||
// We want the debugger to be able to break both on the inline call itself, plus on each
|
||||
// invocation of the inline lambda passed to it. For that to happen there needs to be at least
|
||||
// one different line number in between those breakpoints for the VM to emit a locatable event.
|
||||
// @InlineOnly functions, however, contain no line numbers, so if the lambda is single-line,
|
||||
// the entire call will "meld" into a single region. To break it up, we insert a different line
|
||||
// number that is remapped by the SMAP to a line that does not exist.
|
||||
val label = Label()
|
||||
mv.visitLabel(label)
|
||||
mv.visitLineNumber(smap.mapSyntheticLineNumber(LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER), label)
|
||||
}
|
||||
}
|
||||
|
||||
fun onInlineLambdaEnd(mv: MethodVisitor) {
|
||||
if (callLineNumber >= 0) {
|
||||
val label = Label()
|
||||
mv.visitLabel(label)
|
||||
mv.visitLineNumber(callLineNumber, label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MethodNode.preprocessSuspendMarkers(forInline: Boolean, keepFakeContinuation: Boolean = true) {
|
||||
if (instructions.first == null) return
|
||||
if (!keepFakeContinuation) {
|
||||
|
||||
Reference in New Issue
Block a user