JVM: expect consistent signatures from LambdaInfo
This commit is contained in:
@@ -23,13 +23,10 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
|
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
|
||||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
|
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -233,35 +230,31 @@ class MethodInliner(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val valueParameters = info.invokeMethodParameters
|
val nullableAnyType = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns.nullableAnyType
|
||||||
// If suspend lambda has no continuation at the end, add it here. (In the IR backend, suspend lambdas
|
val expectedParameters = info.invokeMethod.argumentTypes
|
||||||
// always come pre-lowered with the continuation parameter.)
|
val expectedKotlinParameters = info.invokeMethodParameters
|
||||||
var coroutineDesc = desc
|
val argumentCount = Type.getArgumentTypes(desc).size.let {
|
||||||
if (!inliningContext.root.state.isIrBackend && info.isSuspend) {
|
if (!inliningContext.root.state.isIrBackend && info.isSuspend && it < expectedParameters.size) {
|
||||||
val argumentTypes = Type.getArgumentTypes(desc)
|
// Inlining suspend lambda into a function that takes a non-suspend lambda.
|
||||||
if (argumentTypes.size != valueParameters.size) {
|
// In the IR backend, this cannot happen as inline lambdas are not lowered.
|
||||||
addFakeContinuationMarker(this)
|
addFakeContinuationMarker(this)
|
||||||
coroutineDesc = Type.getMethodDescriptor(Type.getReturnType(desc), *argumentTypes, AsmTypes.OBJECT_TYPE)
|
it + 1
|
||||||
}
|
} else it
|
||||||
|
}
|
||||||
|
assert(argumentCount == expectedParameters.size && argumentCount == expectedKotlinParameters.size) {
|
||||||
|
"inconsistent lambda arguments: $argumentCount on stack, ${expectedParameters.size} expected, " +
|
||||||
|
"${expectedKotlinParameters.size} Kotlin types"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is a weird way to get N instances of `Any?`
|
var valueParamShift = max(nextLocalIndex, markerShift) + expectedParameters.sumOf { it.size }
|
||||||
val moduleBuiltIns = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns
|
for (index in argumentCount - 1 downTo 0) {
|
||||||
val erasedFunctionType = moduleBuiltIns.getFunction(valueParameters.size).defaultType
|
val type = expectedParameters[index]
|
||||||
val erasedInvokeFunction = erasedFunctionType.memberScope
|
StackValue.coerce(AsmTypes.OBJECT_TYPE, nullableAnyType, type, expectedKotlinParameters[index], this)
|
||||||
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).first()
|
valueParamShift -= type.size
|
||||||
val invokeParameters = erasedInvokeFunction.valueParameters.map { it.returnType }
|
store(valueParamShift, type)
|
||||||
|
}
|
||||||
val valueParamShift = max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
|
if (expectedParameters.isEmpty()) {
|
||||||
val parameterTypesFromDesc = info.invokeMethod.argumentTypes
|
nop() // add something for a line number to bind onto
|
||||||
putStackValuesIntoLocalsForLambdaOnInvoke(
|
|
||||||
listOf(*parameterTypesFromDesc), valueParameters, invokeParameters, valueParamShift, this, coroutineDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
if (parameterTypesFromDesc.isEmpty()) {
|
|
||||||
// There won't be no parameters processing and line call can be left without actual instructions.
|
|
||||||
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
|
|
||||||
visitInsn(Opcodes.NOP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info.node.node, sourceMapper.parent)
|
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info.node.node, sourceMapper.parent)
|
||||||
@@ -291,9 +284,7 @@ class MethodInliner(
|
|||||||
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
|
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
|
||||||
result.reifiedTypeParametersUsages.mergeAll(info.reifiedTypeParametersUsages)
|
result.reifiedTypeParametersUsages.mergeAll(info.reifiedTypeParametersUsages)
|
||||||
|
|
||||||
StackValue
|
StackValue.coerce(info.invokeMethod.returnType, info.invokeMethodReturnType, OBJECT_TYPE, nullableAnyType, this)
|
||||||
.onStack(info.invokeMethod.returnType, info.invokeMethodReturnType)
|
|
||||||
.put(OBJECT_TYPE, erasedInvokeFunction.returnType, this)
|
|
||||||
setLambdaInlining(false)
|
setLambdaInlining(false)
|
||||||
addInlineMarker(this, false)
|
addInlineMarker(this, false)
|
||||||
inlineOnlySmapSkipper?.onInlineLambdaEnd(remappingMethodAdapter)
|
inlineOnlySmapSkipper?.onInlineLambdaEnd(remappingMethodAdapter)
|
||||||
@@ -1060,46 +1051,6 @@ class MethodInliner(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun putStackValuesIntoLocalsForLambdaOnInvoke(
|
|
||||||
directOrder: List<Type>,
|
|
||||||
directOrderOfArguments: List<KotlinType?>,
|
|
||||||
directOrderOfInvokeParameters: List<KotlinType?>,
|
|
||||||
shift: Int,
|
|
||||||
iv: InstructionAdapter,
|
|
||||||
descriptor: String
|
|
||||||
) {
|
|
||||||
val actualParams = Type.getArgumentTypes(descriptor)
|
|
||||||
assert(actualParams.size == directOrder.size) {
|
|
||||||
"Number of expected and actual parameters should be equal, but ${actualParams.size} != ${directOrder.size}!"
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentShift = shift + directOrder.sumOf { it.size }
|
|
||||||
|
|
||||||
val safeToUseArgumentKotlinType =
|
|
||||||
directOrder.size == directOrderOfArguments.size && directOrderOfArguments.size == directOrderOfInvokeParameters.size
|
|
||||||
|
|
||||||
for (index in directOrder.lastIndex downTo 0) {
|
|
||||||
val type = directOrder[index]
|
|
||||||
currentShift -= type.size
|
|
||||||
val typeOnStack = actualParams[index]
|
|
||||||
|
|
||||||
val argumentKotlinType: KotlinType?
|
|
||||||
val invokeParameterKotlinType: KotlinType?
|
|
||||||
if (safeToUseArgumentKotlinType) {
|
|
||||||
argumentKotlinType = directOrderOfArguments[index]
|
|
||||||
invokeParameterKotlinType = directOrderOfInvokeParameters[index]
|
|
||||||
} else {
|
|
||||||
argumentKotlinType = null
|
|
||||||
invokeParameterKotlinType = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeOnStack != type || invokeParameterKotlinType != argumentKotlinType) {
|
|
||||||
StackValue.onStack(typeOnStack, invokeParameterKotlinType).put(type, argumentKotlinType, iv)
|
|
||||||
}
|
|
||||||
iv.store(currentShift, type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//process local and global returns (local substituted with goto end-label global kept unchanged)
|
//process local and global returns (local substituted with goto end-label global kept unchanged)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun processReturns(
|
fun processReturns(
|
||||||
|
|||||||
Reference in New Issue
Block a user