From a4b67f007f7e1ac39bae9ec56488bb5ec99294d2 Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 6 Oct 2020 17:06:11 +0200 Subject: [PATCH] JVM_IR: treat suspend-converted references as lambdas for inlining Again, this is consistent with adapted function references, since they're pretty much the same anyway. --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../backend/jvm/codegen/IrInlineCodegen.kt | 15 ++++---- .../jvm/ir/IrInlineReferenceLocator.kt | 2 +- .../jvm/lower/FunctionReferenceLowering.kt | 2 +- ...eDeclarationsThatWouldBeInlinedLowering.kt | 3 +- .../jvm/lower/SuspendLambdaLowering.kt | 5 +-- .../suspendConversion/onInlineArgument.kt | 21 +++++++++++ .../suspendConversion/onInlineArgument_ir.txt | 36 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 14 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt create mode 100644 compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument_ir.txt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index cd8c8a3f6cd..564d1f55c7d 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -8678,6 +8678,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt index a207d605254..8ec2f91e44e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrInlineCodegen.kt @@ -76,7 +76,7 @@ class IrInlineCodegen( blockInfo: BlockInfo ) { val isInlineParameter = irValueParameter.isInlineParameter() - if (isInlineParameter && isInlineIrExpression(argumentExpression)) { + if (isInlineParameter && argumentExpression.isInlineIrExpression()) { val irReference = (argumentExpression as IrBlock).statements.filterIsInstance().single() val lambdaInfo = IrExpressionLambdaImpl(codegen, irReference, irValueParameter) val closureInfo = invocationParamBuilder.addNextValueParameter(parameterType, true, null, irValueParameter.index) @@ -245,18 +245,19 @@ class IrDefaultLambda( }.toIrBasedDescriptor() } -fun isInlineIrExpression(argumentExpression: IrExpression) = - when (argumentExpression) { - is IrBlock -> argumentExpression.isInlineIrBlock() +fun IrExpression.isInlineIrExpression() = + when (this) { + is IrBlock -> origin.isInlineIrExpression() is IrCallableReference<*> -> true.also { - assert((0 until argumentExpression.valueArgumentsCount).count { argumentExpression.getValueArgument(it) != null } == 0) { - "Expecting 0 value arguments for bounded callable reference: ${argumentExpression.dump()}" + assert((0 until valueArgumentsCount).count { getValueArgument(it) != null } == 0) { + "Expecting 0 value arguments for bounded callable reference: ${dump()}" } } else -> false } -fun IrBlock.isInlineIrBlock(): Boolean = origin.isLambda || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE +fun IrStatementOrigin?.isInlineIrExpression() = + isLambda || this == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || this == IrStatementOrigin.SUSPEND_CONVERSION fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) = (!context.state.isInlineDisabled || typeParameters.any { it.isReified }) && isInline diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt index b50b86d34bd..ae1fed26604 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrInlineReferenceLocator.kt @@ -36,7 +36,7 @@ internal open class IrInlineReferenceLocator(private val context: JvmBackendCont continue val valueArgument = expression.getValueArgument(parameter.index) ?: continue - if (!isInlineIrExpression(valueArgument)) + if (!valueArgument.isInlineIrExpression()) continue if (valueArgument is IrBlock) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index c38c4a45fa3..a70771eee1b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -54,7 +54,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) // because they are also their own continuation classes. // TODO: Currently, origin of callable references explicitly written in source code is null. Do we need to create one? private fun IrFunctionReference.isSuspendFunctionReference(): Boolean = isSuspend && - (origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) + (origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE || origin == IrStatementOrigin.SUSPEND_CONVERSION) override fun lower(irFile: IrFile) { ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile)) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RemoveDeclarationsThatWouldBeInlinedLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RemoveDeclarationsThatWouldBeInlinedLowering.kt index 13f54c17213..c48cfe9f712 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RemoveDeclarationsThatWouldBeInlinedLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/RemoveDeclarationsThatWouldBeInlinedLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass @@ -37,7 +38,7 @@ private class RemoveDeclarationsThatWouldBeInlinedLowering(val context: JvmBacke override fun visitElement(element: IrElement) = element.acceptChildrenVoid(this) override fun visitFunctionReference(expression: IrFunctionReference) { - if (expression.origin.isLambda || expression.origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE) { + if (expression.origin.isInlineIrExpression()) { loweredLambdasToDelete.add(expression.symbol.owner) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt index 044ac58d71c..cd8a5d8afe8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt @@ -109,12 +109,9 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin override fun lower(irFile: IrFile) { val inlineReferences = IrInlineReferenceLocator.scan(context, irFile) irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { - private fun IrFunctionReference.shouldBeTreatedAsSuspendLambda() = - isSuspend && (origin == IrStatementOrigin.LAMBDA || origin == IrStatementOrigin.SUSPEND_CONVERSION) - override fun visitBlock(expression: IrBlock): IrExpression { val reference = expression.statements.lastOrNull() as? IrFunctionReference ?: return super.visitBlock(expression) - if (reference.shouldBeTreatedAsSuspendLambda() && reference !in inlineReferences) { + if (reference.isSuspend && reference.origin.isLambda && reference !in inlineReferences) { assert(expression.statements.size == 2 && expression.statements[0] is IrFunction) expression.transformChildrenVoid(this) val parent = currentDeclarationParent ?: error("No current declaration parent at ${reference.dump()}") diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt new file mode 100644 index 00000000000..e8cb5ec713c --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt @@ -0,0 +1,21 @@ +// !LANGUAGE: +SuspendConversion +// WITH_RUNTIME +// WITH_COROUTINES +// IGNORE_BACKEND: JVM, NATIVE +// IGNORE_LIGHT_ANALYSIS + +// `lambda` should not be wrapped in yet another object (so no OnInlineArgumentKt$box$1$1). +// CHECK_BYTECODE_LISTING + +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +inline suspend fun runS(fn: suspend (String) -> String) = fn("O") + +fun box(): String { + var test = "Failed" + val lambda: (String) -> String = { it + "K" } + suspend { test = runS(lambda) }.startCoroutine(EmptyContinuation) + return test +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument_ir.txt b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument_ir.txt new file mode 100644 index 00000000000..985e2334948 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument_ir.txt @@ -0,0 +1,36 @@ +@kotlin.coroutines.jvm.internal.DebugMetadata +@kotlin.Metadata +final class OnInlineArgumentKt$box$1 { + // source: 'onInlineArgument.kt' + enclosing method OnInlineArgumentKt.box()Ljava/lang/String; + synthetic final field $lambda: kotlin.jvm.functions.Function1 + synthetic final field $test: kotlin.jvm.internal.Ref$ObjectRef + field label: int + inner (anonymous) class OnInlineArgumentKt$box$1 + method (p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function1, p2: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation + public final method invoke(p0: java.lang.Object): java.lang.Object + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +final class OnInlineArgumentKt$box$lambda$1 { + // source: 'onInlineArgument.kt' + enclosing method OnInlineArgumentKt.box()Ljava/lang/String; + public final static field INSTANCE: OnInlineArgumentKt$box$lambda$1 + inner (anonymous) class OnInlineArgumentKt$box$lambda$1 + static method (): void + method (): void + public final @org.jetbrains.annotations.NotNull method invoke(@org.jetbrains.annotations.NotNull p0: java.lang.String): java.lang.String + public synthetic bridge method invoke(p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class OnInlineArgumentKt { + // source: 'onInlineArgument.kt' + inner (anonymous) class OnInlineArgumentKt$box$1 + inner (anonymous) class OnInlineArgumentKt$box$lambda$1 + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + private final static method runS$$forInline(p0: kotlin.jvm.functions.Function2, p1: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method runS(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 4e3bb6c9e40..ff3e51b46c2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -9893,6 +9893,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 7dd4edaebfc..78a9f591916 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -9885,6 +9885,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void ignoreOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void ignoreSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 1696bb0f15e..bf531162a13 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -8678,6 +8678,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index f556dfb0522..613bfcc7944 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -7373,6 +7373,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index cc8b5e710a6..a9f12b35a2a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -7373,6 +7373,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index cbb386dca34..d35966879bb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -7373,6 +7373,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onArgument.kt"); } + @TestMetadata("onInlineArgument.kt") + public void testOnInlineArgument() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendConversion/onInlineArgument.kt"); + } + @TestMetadata("subtypeOfFunctionalTypeToSuspendConversion.kt") public void testSubtypeOfFunctionalTypeToSuspendConversion() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt");