From 98088f739d53d98b669f77cabb73c087d82bd4e5 Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 7 Oct 2020 12:46:07 +0200 Subject: [PATCH] PSI2IR: do not generate when subjects multiple times `in x` is represented as ` in x` in psi, so generating the entire call and then replacing the argument with a read of a temporary results in redundant regenerations of the subject. #KT-42054 Fixed #KT-42455 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../generators/ArgumentsGenerationUtils.kt | 20 +++++++++---------- .../BranchingExpressionGenerator.kt | 16 +++++++++------ .../codegen/box/controlStructures/kt42455.kt | 9 +++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../LightAnalysisModeTestGenerated.java | 5 +++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../IrJsCodegenBoxTestGenerated.java | 5 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++++ 10 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/codegen/box/controlStructures/kt42455.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 fd92d007057..336ab6a0d6d 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 @@ -5667,6 +5667,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index c35b0639380..f468f7ca61a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -473,13 +473,19 @@ fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? return getOrFail(BindingContext.REFERENCE_TARGET, superCallExpression.instanceReference) as ClassDescriptor } -fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder { +fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder = + pregenerateCallUsing(resolvedCall) { generateExpression(it) } + +fun StatementGenerator.pregenerateCallUsing( + resolvedCall: ResolvedCall<*>, + generateArgumentExpression: (KtExpression) -> IrExpression? +): CallBuilder { if (resolvedCall.isExtensionInvokeCall()) { return pregenerateExtensionInvokeCall(resolvedCall) } - val call = pregenerateCallReceivers(resolvedCall) - pregenerateValueArguments(call, resolvedCall) + pregenerateValueArgumentsUsing(call, resolvedCall, generateArgumentExpression) + generateSamConversionForValueArgumentsIfRequired(call, resolvedCall) return call } @@ -562,14 +568,6 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean { return extensionReceiver != null } -private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) { - pregenerateValueArgumentsUsing(call, resolvedCall) { - generateExpression(it) - } - - generateSamConversionForValueArgumentsIfRequired(call, resolvedCall) -} - fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, resolvedCall: ResolvedCall<*>) { val samConversion = context.extensions.samConversion diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index 43015ba3ee8..90614436fd3 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt @@ -113,7 +113,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta for (ktCondition in ktEntry.conditions) { val irCondition = if (irSubject != null) - generateWhenConditionWithSubject(ktCondition, irSubject) + generateWhenConditionWithSubject(ktCondition, irSubject, expression.subjectExpression) else generateWhenConditionNoSubject(ktCondition) irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition @@ -190,12 +190,14 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression = (ktCondition as KtWhenConditionWithExpression).expression!!.genExpr() - private fun generateWhenConditionWithSubject(ktCondition: KtWhenCondition, irSubject: IrVariable): IrExpression { + private fun generateWhenConditionWithSubject( + ktCondition: KtWhenCondition, irSubject: IrVariable, ktSubject: KtExpression? + ): IrExpression { return when (ktCondition) { is KtWhenConditionWithExpression -> generateEqualsCondition(irSubject, ktCondition) is KtWhenConditionInRange -> - generateInRangeCondition(irSubject, ktCondition) + generateInCondition(irSubject, ktCondition, ktSubject) is KtWhenConditionIsPattern -> generateIsPatternCondition(irSubject, ktCondition) else -> @@ -227,11 +229,13 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta irInstanceOf } - private fun generateInRangeCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange): IrExpression { - val inCall = statementGenerator.pregenerateCall(getResolvedCall(ktCondition.operationReference)!!) + private fun generateInCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange, ktSubject: KtExpression?): IrExpression { val startOffset = ktCondition.startOffsetSkippingComments val endOffset = ktCondition.endOffset - inCall.irValueArgumentsByIndex[0] = irSubject.loadAt(startOffset, startOffset) + val inCall = statementGenerator.pregenerateCallUsing(getResolvedCall(ktCondition.operationReference)!!) { + // In a `when` with a subject, `in x` is represented as `x.contains()`. + if (it === ktSubject) irSubject.loadAt(startOffset, startOffset) else statementGenerator.generateExpression(it) + } val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType()) val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator) return when (inOperator) { diff --git a/compiler/testData/codegen/box/controlStructures/kt42455.kt b/compiler/testData/codegen/box/controlStructures/kt42455.kt new file mode 100644 index 00000000000..930e0b403a6 --- /dev/null +++ b/compiler/testData/codegen/box/controlStructures/kt42455.kt @@ -0,0 +1,9 @@ +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME +fun box(): String { + val xs = listOf(1, 2, 3) + return when (xs.first { it > 1 }) { + in xs -> "OK" + else -> "fail" + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f5e627a27b8..79397078176 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5702,6 +5702,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 18bb6128000..38baaf118ee 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -5702,6 +5702,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index bd3ec01f646..67649216f94 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -5667,6 +5667,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.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 5be5287719b..cf9b6414938 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 @@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.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 26893a1cde7..0114790def5 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 @@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.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 b0b8a6b8337..bedcd0c50d9 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 @@ -4572,6 +4572,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/controlStructures/kt416.kt"); } + @TestMetadata("kt42455.kt") + public void testKt42455() throws Exception { + runTest("compiler/testData/codegen/box/controlStructures/kt42455.kt"); + } + @TestMetadata("kt513.kt") public void testKt513() throws Exception { runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");