From 4742057b516a2f6ed3769828a08cb3170dc570b1 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 19 Mar 2020 11:45:23 +0300 Subject: [PATCH] IR: generate lambdas in place in Psi2Ir even when arguments are to be rearranged. Lambdas have no side effects, and storing them in temporary variables prevents processing in the backend (such as inserting continuation parameter in AddContinuationLowering). --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../kotlin/psi2ir/generators/CallGenerator.kt | 11 ++++++- .../suspendLambdaWithArgumentRearrangement.kt | 32 +++++++++++++++++++ .../callWithReorderedArguments.txt | 6 ++-- .../codegen/BlackBoxCodegenTestGenerated.java | 10 ++++++ .../LightAnalysisModeTestGenerated.java | 10 ++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 9 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt 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 34de0272d04..175bce90688 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 @@ -6465,6 +6465,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/suspendJavaOverrides.kt"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspendReturningPlatformType.kt") public void testSuspendReturningPlatformType() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendReturningPlatformType.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 5fc05accfef..98e3a77c7e2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -384,7 +384,10 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator for (valueArgument in valueArgumentsInEvaluationOrder) { val valueParameter = valueArgumentsToValueParameters[valueArgument]!! val irArgument = call.getValueArgument(valueParameter) ?: continue - val irArgumentValue = scope.createTemporaryVariableInBlock(context, irArgument, irBlock, valueParameter.name.asString()) + val irArgumentValue = if (irArgument.hasNoSideEffects()) + generateExpressionValue(irArgument.type) { irArgument } // Computing a lambda has no side effects, can generate in place + else + scope.createTemporaryVariableInBlock(context, irArgument, irBlock, valueParameter.name.asString()) irArgumentValues[valueParameter] = irArgumentValue } @@ -399,6 +402,12 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator } } +fun IrExpression.hasNoSideEffects() = + this is IrFunctionExpression || + (this is IrCallableReference && dispatchReceiver == null && extensionReceiver == null) || + this is IrClassReference || + this is IrConst<*> + fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: IrStatementOrigin? = null) = generateCall(ktElement.startOffsetSkippingComments, ktElement.endOffset, call, origin) diff --git a/compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt b/compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt new file mode 100644 index 00000000000..b5a6e0a9454 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt @@ -0,0 +1,32 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JS +// WITH_RUNTIME +// WITH_COROUTINES +// COMMON_COROUTINES_TEST +import helpers.* +import COROUTINES_PACKAGE.* +import COROUTINES_PACKAGE.intrinsics.* + +inline fun callAction(aux: Int, action: () -> String): String { + return action() +} + +suspend fun get() = "OK" + +suspend fun callSuspend(): String { + return callAction(action = { + get() + }, aux = 0) +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + var v = "fail" + builder { + v = callSuspend() + } + return v +} diff --git a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.txt b/compiler/testData/ir/irText/expressions/callWithReorderedArguments.txt index bdc22f5af30..acc634caadb 100644 --- a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.txt +++ b/compiler/testData/ir/irText/expressions/callWithReorderedArguments.txt @@ -34,9 +34,7 @@ FILE fqName: fileName:/callWithReorderedArguments.kt b: GET_VAR 'val tmp_0: kotlin.Int [val] declared in .test' type=kotlin.Int origin=null BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val] - CONST Int type=kotlin.Int value=1 - VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val] CALL 'public final fun reordered2 (): kotlin.Int declared in ' type=kotlin.Int origin=null CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=null - a: GET_VAR 'val tmp_3: kotlin.Int [val] declared in .test' type=kotlin.Int origin=null - b: GET_VAR 'val tmp_2: kotlin.Int [val] declared in .test' type=kotlin.Int origin=null + a: GET_VAR 'val tmp_2: kotlin.Int [val] declared in .test' type=kotlin.Int origin=null + b: CONST Int type=kotlin.Int value=1 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 08c4a845ad8..e1edc1fc7f3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6880,6 +6880,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/suspendJavaOverrides.kt"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspendReturningPlatformType.kt") public void testSuspendReturningPlatformType() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendReturningPlatformType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index dab112bea72..6cea7f6be2a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6880,6 +6880,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/suspendJavaOverrides.kt"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspendReturningPlatformType.kt") public void testSuspendReturningPlatformType() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendReturningPlatformType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 4fca346ad33..b625db521e7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -6465,6 +6465,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/suspendJavaOverrides.kt"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspendReturningPlatformType.kt") public void testSuspendReturningPlatformType() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendReturningPlatformType.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 20d494af17e..369df0195a6 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 @@ -5455,6 +5455,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt", "kotlin.coroutines"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspensionInsideSafeCallWithElvis.kt") public void testSuspensionInsideSafeCallWithElvis_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCallWithElvis.kt", "kotlin.coroutines"); 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 033946a68d1..d30c626eadc 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 @@ -5455,6 +5455,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt", "kotlin.coroutines"); } + @TestMetadata("suspendLambdaWithArgumentRearrangement.kt") + public void testSuspendLambdaWithArgumentRearrangement_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspendLambdaWithArgumentRearrangement.kt", "kotlin.coroutines"); + } + @TestMetadata("suspensionInsideSafeCallWithElvis.kt") public void testSuspensionInsideSafeCallWithElvis_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/suspensionInsideSafeCallWithElvis.kt", "kotlin.coroutines");