Proper resort variables on inlining lowered ir closures
Original problem is that lowered ir closures doesn't meet inliner expectations
about captured variable position in inlining method.
E.g.: Call 'foo(valueParam) { capturedParam }' to
inline function 'foo' with declaration
inline fun foo(valueParam: Foo, inlineParamWithCaptured: Bar.() ->) ....
is reorganized through inlining to equivalent call foo(valueParam, capturedParam1, cp2 ...).
But lowered closure for lambda parameter has totally different parameters order:
fun loweredLambda$x(extensionReceiver, captured1, cp2..., valueParam1, vp2...)
So before inlining lowered closure should be transformed to
fun loweredLambda$x(extensionReceiver, valueParam1, vp2..., captured1, cp2..)
#KT-28547 Fixed
This commit is contained in:
+24
-18
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.JvmKotlinType
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -34,9 +35,8 @@ class IrInlineCodegen(
|
||||
val lambdaInfo = next as IrExpressionLambda
|
||||
activeLambda = lambdaInfo
|
||||
|
||||
val argumentTypes = lambdaInfo.loweredMethod.argumentTypes
|
||||
lambdaInfo.reference.getArguments().forEachIndexed { index, (_, ir) ->
|
||||
putCapturedValueOnStack(ir, argumentTypes[index], index)
|
||||
putCapturedValueOnStack(ir, lambdaInfo.capturedParamsInDesc[index], index)
|
||||
}
|
||||
activeLambda = null
|
||||
}
|
||||
@@ -70,10 +70,10 @@ class IrInlineCodegen(
|
||||
putArgumentOrCapturedToLocalVal(JvmKotlinType(value.type, value.kotlinType), value, -1, parameterIndex, ValueKind.CAPTURED /*kind*/)
|
||||
}
|
||||
|
||||
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamindex: Int) {
|
||||
private fun putCapturedValueOnStack(argumentExpression: IrExpression, valueType: Type, capturedParamIndex: Int) {
|
||||
val onStack = codegen.gen(argumentExpression, valueType, BlockInfo.create())
|
||||
putArgumentOrCapturedToLocalVal(
|
||||
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamindex, capturedParamindex, ValueKind.CAPTURED
|
||||
JvmKotlinType(onStack.type, onStack.kotlinType), onStack, capturedParamIndex, capturedParamIndex, ValueKind.CAPTURED
|
||||
)
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ class IrInlineCodegen(
|
||||
|
||||
private fun rememberClosure(irReference: IrFunctionReference, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
|
||||
//assert(InlineUtil.isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
|
||||
|
||||
val expression = irReference.symbol.owner as IrFunction
|
||||
return IrExpressionLambda(
|
||||
irReference, expression, typeMapper, parameter.isCrossinline, false/*TODO*/
|
||||
irReference, expression, typeMapper, parameter.isCrossinline, false/*TODO*/,
|
||||
parameter.type.isExtensionFunctionType
|
||||
).also { lambda ->
|
||||
val closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.index)
|
||||
closureInfo.lambda = lambda
|
||||
@@ -110,7 +110,8 @@ class IrExpressionLambda(
|
||||
val function: IrFunction,
|
||||
typeMapper: KotlinTypeMapper,
|
||||
isCrossInline: Boolean,
|
||||
override val isBoundCallableReference: Boolean
|
||||
override val isBoundCallableReference: Boolean,
|
||||
val isExtensionLambda: Boolean
|
||||
) : ExpressionLambda(typeMapper, isCrossInline) {
|
||||
|
||||
override fun isMyLabel(name: String): Boolean {
|
||||
@@ -118,30 +119,35 @@ class IrExpressionLambda(
|
||||
return false
|
||||
}
|
||||
|
||||
override val lambdaClassType: Type
|
||||
get() = Type.getObjectType("test123")
|
||||
override val lambdaClassType: Type = Type.getObjectType("test123")
|
||||
|
||||
override val capturedVars: List<CapturedParamDesc> by lazy {
|
||||
override val capturedVars: List<CapturedParamDesc> =
|
||||
arrayListOf<CapturedParamDesc>().apply {
|
||||
reference.getArguments().forEachIndexed { _, (_, ir) ->
|
||||
val getValue = ir as? IrGetValue ?: error("Unrecognized expression: $ir")
|
||||
add(capturedParamDesc(getValue.descriptor.name.asString(), typeMapper.mapType(getValue.descriptor.type)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val loweredMethod: Method
|
||||
get() = typeMapper.mapAsmMethod(function.descriptor)
|
||||
private val loweredMethod = typeMapper.mapAsmMethod(function.descriptor)
|
||||
|
||||
val capturedParamsInDesc: List<Type> =
|
||||
loweredMethod.argumentTypes.drop(if (isExtensionLambda) 1 else 0).take(capturedVars.size)
|
||||
|
||||
override val invokeMethod: Method = loweredMethod.let {
|
||||
Method(it.name, it.returnType, it.argumentTypes.drop(capturedVars.size).toTypedArray())
|
||||
Method(
|
||||
it.name,
|
||||
it.returnType,
|
||||
(
|
||||
(if (isExtensionLambda) it.argumentTypes.take(1) else emptyList()) +
|
||||
it.argumentTypes.drop((if (isExtensionLambda) 1 else 0) + capturedVars.size)
|
||||
).toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
override val invokeMethodDescriptor: FunctionDescriptor
|
||||
get() = function.descriptor
|
||||
override val invokeMethodDescriptor: FunctionDescriptor = function.descriptor
|
||||
|
||||
override val hasDispatchReceiver: Boolean
|
||||
get() = false
|
||||
override val hasDispatchReceiver: Boolean = false
|
||||
}
|
||||
|
||||
fun isInlineIrExpression(argumentExpression: IrExpression) =
|
||||
|
||||
Reference in New Issue
Block a user