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
@@ -0,0 +1,13 @@
// TARGET_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// LAMBDAS: INDY
fun box() =
{ p0: String, p1: String, p2: Int, p3: Int, p4: Int, p5: Int, p6: Int, p7: Int, p8: Int, p9: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int
-> p0 + p1
}(
"O", "K", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
)
@@ -16191,6 +16191,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/lambdas"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("bigArityFun.kt")
public void testBigArityFun() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/bigArityFun.kt");
}
@TestMetadata("capturedDispatchReceiver.kt")
public void testCapturedDispatchReceiver() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/lambdas/capturedDispatchReceiver.kt");