JVM_IR indy-lambdas: don't use indy for big arity lambdas

KT-44278 KT-26060 KT-42621
This commit is contained in:
Dmitry Petrov
2021-01-29 17:59:15 +03:00
committed by TeamCityServer
parent d94912ed62
commit 088448043a
3 changed files with 28 additions and 3 deletions
@@ -91,7 +91,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
expression.statements.dropLast(1).forEach { it.transform(this, null) }
reference.transformChildrenVoid(this)
if (shouldGenerateIndyLambdas && canUseIndySamConversion(reference, reference.type)) {
if (shouldGenerateIndyLambdas && canUseIndySamConversion(reference, reference.type, true)) {
return wrapLambdaReferenceWithIndySamConversion(expression, reference)
}
@@ -139,14 +139,14 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
reference.transformChildrenVoid()
val samSuperType = expression.typeOperand
return if (shouldGenerateIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
return if (shouldGenerateIndySamConversions && canUseIndySamConversion(reference, samSuperType, false)) {
wrapSamConversionArgumentWithIndySamConversion(expression)
} else {
FunctionReferenceBuilder(reference, samSuperType).build()
}
}
private fun canUseIndySamConversion(reference: IrFunctionReference, samSuperType: IrType): Boolean {
private fun canUseIndySamConversion(reference: IrFunctionReference, samSuperType: IrType, plainLambda: Boolean): Boolean {
// Can't use JDK LambdaMetafactory for function references by default (because of 'equals').
// TODO special mode that would generate indy everywhere?
if (reference.origin != IrStatementOrigin.LAMBDA)
@@ -168,6 +168,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
)
return false
if (plainLambda) {
var parametersCount = target.valueParameters.size
if (target.extensionReceiverParameter != null) ++parametersCount
if (parametersCount > 22)
return false
}
// Can't use indy-based SAM conversion inside inline fun (Ok in inline lambda).
if (target.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() })
return false