JVM IR: Use inline SAM wrappers inside of inline lambdas

This commit is contained in:
Steven Schäfer
2020-10-28 12:04:32 +01:00
committed by Alexander Udalov
parent f2b8c67962
commit 36711a768b
5 changed files with 44 additions and 0 deletions
@@ -4324,6 +4324,11 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullableInitialization.kt");
}
@TestMetadata("samWrapperInInlineLambda.kt")
public void testSamWrapperInInlineLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt");
}
@TestMetadata("samWrapperOfLambda.kt")
public void testSamWrapperOfLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperOfLambda.kt");
@@ -12,11 +12,13 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal val singleAbstractMethodPhase = makeIrFilePhase(
::JvmSingleAbstractMethodLowering,
@@ -25,6 +27,15 @@ internal val singleAbstractMethodPhase = makeIrFilePhase(
)
private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) {
// The JVM BE produces inline SAM wrappers both in the scope of an inline function as well as in the scope
// of an inline lambda. Compare with `SamWrapperClasses.getSamWrapperClass`.
override val inInlineFunctionScope: Boolean
get() = allScopes.any { scope ->
scope.irElement.safeAs<IrFunction>()?.let {
it.isInline || it.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
} ?: false
}
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>) =
if (inInlineFunctionScope) DescriptorVisibilities.PUBLIC else JavaDescriptorVisibilities.PACKAGE_VISIBILITY
@@ -0,0 +1,18 @@
// FILE: J.java
public class J {
public static void g(Runnable r) {
r.run();
}
}
// FILE: test.kt
fun box(): String {
var result = "Fail"
val setter = { result = "OK" }
1.apply { J.g(setter) }
return result
}
// 1 INVOKESPECIAL TestKt\$sam\$i\$java_lang_Runnable\$0.<init> \(Lkotlin/jvm/functions/Function0;\)V
@@ -4396,6 +4396,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullableInitialization.kt");
}
@TestMetadata("samWrapperInInlineLambda.kt")
public void testSamWrapperInInlineLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt");
}
@TestMetadata("samWrapperOfLambda.kt")
public void testSamWrapperOfLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperOfLambda.kt");
@@ -4324,6 +4324,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullableInitialization.kt");
}
@TestMetadata("samWrapperInInlineLambda.kt")
public void testSamWrapperInInlineLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt");
}
@TestMetadata("samWrapperOfLambda.kt")
public void testSamWrapperOfLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperOfLambda.kt");