PSI2IR: do not generate when subjects multiple times
`in x` is represented as `<subject expression> 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
This commit is contained in:
Generated
+5
@@ -5667,6 +5667,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
+9
-11
@@ -473,13 +473,19 @@ fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor?
|
|||||||
return getOrFail(BindingContext.REFERENCE_TARGET, superCallExpression.instanceReference) as 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()) {
|
if (resolvedCall.isExtensionInvokeCall()) {
|
||||||
return pregenerateExtensionInvokeCall(resolvedCall)
|
return pregenerateExtensionInvokeCall(resolvedCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
val call = pregenerateCallReceivers(resolvedCall)
|
val call = pregenerateCallReceivers(resolvedCall)
|
||||||
pregenerateValueArguments(call, resolvedCall)
|
pregenerateValueArgumentsUsing(call, resolvedCall, generateArgumentExpression)
|
||||||
|
generateSamConversionForValueArgumentsIfRequired(call, resolvedCall)
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,14 +568,6 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean {
|
|||||||
return extensionReceiver != null
|
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<*>) {
|
fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, resolvedCall: ResolvedCall<*>) {
|
||||||
val samConversion = context.extensions.samConversion
|
val samConversion = context.extensions.samConversion
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -113,7 +113,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
|||||||
for (ktCondition in ktEntry.conditions) {
|
for (ktCondition in ktEntry.conditions) {
|
||||||
val irCondition =
|
val irCondition =
|
||||||
if (irSubject != null)
|
if (irSubject != null)
|
||||||
generateWhenConditionWithSubject(ktCondition, irSubject)
|
generateWhenConditionWithSubject(ktCondition, irSubject, expression.subjectExpression)
|
||||||
else
|
else
|
||||||
generateWhenConditionNoSubject(ktCondition)
|
generateWhenConditionNoSubject(ktCondition)
|
||||||
irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition
|
irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition
|
||||||
@@ -190,12 +190,14 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
|||||||
private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression =
|
private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression =
|
||||||
(ktCondition as KtWhenConditionWithExpression).expression!!.genExpr()
|
(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) {
|
return when (ktCondition) {
|
||||||
is KtWhenConditionWithExpression ->
|
is KtWhenConditionWithExpression ->
|
||||||
generateEqualsCondition(irSubject, ktCondition)
|
generateEqualsCondition(irSubject, ktCondition)
|
||||||
is KtWhenConditionInRange ->
|
is KtWhenConditionInRange ->
|
||||||
generateInRangeCondition(irSubject, ktCondition)
|
generateInCondition(irSubject, ktCondition, ktSubject)
|
||||||
is KtWhenConditionIsPattern ->
|
is KtWhenConditionIsPattern ->
|
||||||
generateIsPatternCondition(irSubject, ktCondition)
|
generateIsPatternCondition(irSubject, ktCondition)
|
||||||
else ->
|
else ->
|
||||||
@@ -227,11 +229,13 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
|||||||
irInstanceOf
|
irInstanceOf
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateInRangeCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange): IrExpression {
|
private fun generateInCondition(irSubject: IrVariable, ktCondition: KtWhenConditionInRange, ktSubject: KtExpression?): IrExpression {
|
||||||
val inCall = statementGenerator.pregenerateCall(getResolvedCall(ktCondition.operationReference)!!)
|
|
||||||
val startOffset = ktCondition.startOffsetSkippingComments
|
val startOffset = ktCondition.startOffsetSkippingComments
|
||||||
val endOffset = ktCondition.endOffset
|
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(<reference to subject expression>)`.
|
||||||
|
if (it === ktSubject) irSubject.loadAt(startOffset, startOffset) else statementGenerator.generateExpression(it)
|
||||||
|
}
|
||||||
val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType())
|
val inOperator = getInfixOperator(ktCondition.operationReference.getReferencedNameElementType())
|
||||||
val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator)
|
val irInCall = CallGenerator(statementGenerator).generateCall(ktCondition, inCall, inOperator)
|
||||||
return when (inOperator) {
|
return when (inOperator) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -5702,6 +5702,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
+5
@@ -5702,6 +5702,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
+5
@@ -5667,6 +5667,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
Generated
+5
@@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
Generated
+5
@@ -4572,6 +4572,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
+5
@@ -4572,6 +4572,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/controlStructures/kt416.kt");
|
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")
|
@TestMetadata("kt513.kt")
|
||||||
public void testKt513() throws Exception {
|
public void testKt513() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
runTest("compiler/testData/codegen/box/controlStructures/kt513.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user