JVM_IR indy-lambdas: initial implementation and tests
KT-44278 KT-26060 KT-42621
This commit is contained in:
committed by
TeamCityServer
parent
0bc386cb08
commit
d94912ed62
+3
-1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.inline.v
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -101,7 +102,8 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
||||
|
||||
private fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Handle {
|
||||
val irFun = irRawFunctionReference.symbol.owner
|
||||
val irParentClass = irFun.parentAsClass
|
||||
val irParentClass = irFun.parent as? IrClass
|
||||
?: throw AssertionError("Unexpected parent: ${irFun.parent.render()}")
|
||||
val owner = codegen.typeMapper.mapOwner(irParentClass)
|
||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFun)
|
||||
val handleTag = when {
|
||||
|
||||
+24
-6
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.config.JvmSamConversions
|
||||
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -74,6 +74,12 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
irFile.transformChildrenVoid(this)
|
||||
}
|
||||
|
||||
private val shouldGenerateIndySamConversions =
|
||||
context.state.samConversionsScheme == JvmClosureGenerationScheme.INDY
|
||||
|
||||
private val shouldGenerateIndyLambdas =
|
||||
context.state.lambdasScheme == JvmClosureGenerationScheme.INDY
|
||||
|
||||
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||
if (!expression.origin.isLambda)
|
||||
return super.visitBlock(expression)
|
||||
@@ -84,9 +90,24 @@ 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)) {
|
||||
return wrapLambdaReferenceWithIndySamConversion(expression, reference)
|
||||
}
|
||||
|
||||
return FunctionReferenceBuilder(reference).build()
|
||||
}
|
||||
|
||||
private fun wrapLambdaReferenceWithIndySamConversion(expression: IrBlock, reference: IrFunctionReference): IrBlock {
|
||||
expression.statements[expression.statements.size - 1] = wrapWithIndySamConversion(reference.type, reference)
|
||||
val irLambda = reference.symbol.owner
|
||||
// JDK LambdaMetafactory can't adapt '(...)V' tp '(...)Lkotlin/Unit;'.
|
||||
if (irLambda.returnType.isUnit()) {
|
||||
irLambda.returnType = irLambda.returnType.makeNullable()
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
return if (expression.isIgnored)
|
||||
@@ -95,9 +116,6 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
FunctionReferenceBuilder(expression).build()
|
||||
}
|
||||
|
||||
private val shouldUseIndySamConversions =
|
||||
context.state.samConversionsScheme == JvmSamConversions.INDY
|
||||
|
||||
// Handle SAM conversions which wrap a function reference:
|
||||
// class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) }
|
||||
//
|
||||
@@ -121,7 +139,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
reference.transformChildrenVoid()
|
||||
|
||||
val samSuperType = expression.typeOperand
|
||||
return if (shouldUseIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
|
||||
return if (shouldGenerateIndySamConversions && canUseIndySamConversion(reference, samSuperType)) {
|
||||
wrapSamConversionArgumentWithIndySamConversion(expression)
|
||||
} else {
|
||||
FunctionReferenceBuilder(reference, samSuperType).build()
|
||||
@@ -129,7 +147,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
|
||||
private fun canUseIndySamConversion(reference: IrFunctionReference, samSuperType: IrType): Boolean {
|
||||
// Can't use indy for regular function references by default (because of 'equals').
|
||||
// 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)
|
||||
return false
|
||||
|
||||
+2
-3
@@ -231,10 +231,9 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
||||
}
|
||||
|
||||
val targetExtensionReceiverParameter = targetFun.extensionReceiverParameter
|
||||
if (targetExtensionReceiverParameter != null) {
|
||||
if (targetExtensionReceiverParameter != null && irFunRef.extensionReceiver != null) {
|
||||
addValueParameter("p${syntheticParameterIndex++}", targetExtensionReceiverParameter.type)
|
||||
val extensionReceiver = irFunRef.extensionReceiver
|
||||
?: fail("Captured extension receiver is not provided")
|
||||
val extensionReceiver = irFunRef.extensionReceiver!!
|
||||
dynamicCallArguments.add(extensionReceiver)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user