From 36711a768ba020504d0a23852fe3b50a670d0dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Wed, 28 Oct 2020 12:04:32 +0100 Subject: [PATCH] JVM IR: Use inline SAM wrappers inside of inline lambdas --- .../ir/FirBytecodeTextTestGenerated.java | 5 +++++ .../lower/JvmSingleAbstractMethodLowering.kt | 11 +++++++++++ .../sam/samWrapperInInlineLambda.kt | 18 ++++++++++++++++++ .../codegen/BytecodeTextTestGenerated.java | 5 +++++ .../ir/IrBytecodeTextTestGenerated.java | 5 +++++ 5 files changed, 44 insertions(+) create mode 100644 compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java index eae587e2d32..920fa9cc1f4 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBytecodeTextTestGenerated.java @@ -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"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt index b2742527f55..34ab64c92f5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmSingleAbstractMethodLowering.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()?.let { + it.isInline || it.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA + } ?: false + } + override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List) = if (inInlineFunctionScope) DescriptorVisibilities.PUBLIC else JavaDescriptorVisibilities.PACKAGE_VISIBILITY diff --git a/compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt b/compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt new file mode 100644 index 00000000000..b4f83ded013 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/sam/samWrapperInInlineLambda.kt @@ -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. \(Lkotlin/jvm/functions/Function0;\)V \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 26afbae6c86..7a5cb39f472 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index e1b2a17d070..9ccedc51394 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -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");