JVM_IR: create temporaries for complex SAM conversion arguments
To avoid bytecode sequences like
new _1Kt$sam$i$java_lang_Runnable$0
dup
new _1Kt$f$1
dup
invokespecial _1Kt$f$1.<init>()V
invokespecial _1Kt$sam$i$java_lang_Runnable$0.<init>(...)V
as the different order of `new` and `<init>` confuses the inliner.
This commit is contained in:
+10
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
@@ -120,6 +121,15 @@ class SingleAbstractMethodLowering(val context: CommonBackendContext) : FileLowe
|
|||||||
}
|
}
|
||||||
+irIfNull(superType, irGet(invokableVariable), irNull(), instance)
|
+irIfNull(superType, irGet(invokableVariable), irNull(), instance)
|
||||||
}
|
}
|
||||||
|
} else if (invokable !is IrGetValue) {
|
||||||
|
// Hack for the JVM inliner: since the SAM wrappers might be regenerated, avoid putting complex logic
|
||||||
|
// between the creation of the wrapper and the call of its `<init>`. `MethodInliner` tends to break
|
||||||
|
// otherwise, e.g. if the argument constructs an anonymous object, resulting in new-new-<init>-<init>.
|
||||||
|
// (See KT-21781 for a similar problem with anonymous object constructor arguments.)
|
||||||
|
irBlock(invokable, null, superType) {
|
||||||
|
val invokableVariable = irTemporary(invokable)
|
||||||
|
+irCall(implementation.constructors.single()).apply { putValueArgument(0, irGet(invokableVariable)) }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
irCall(implementation.constructors.single()).apply { putValueArgument(0, invokable) }
|
irCall(implementation.constructors.single()).apply { putValueArgument(0, invokable) }
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// IGNORE_BACKEND: JVM_IR
|
||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun f(crossinline g: () -> Unit) = Runnable(object : () -> Unit {
|
||||||
|
override fun invoke() = g()
|
||||||
|
})
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = "FAIL"
|
||||||
|
f { result = "OK" }.run()
|
||||||
|
return result
|
||||||
|
}
|
||||||
+5
@@ -432,6 +432,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObjectToSam.kt")
|
||||||
|
public void testAnonymousObjectToSam() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/anonymousObjectToSam.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt17091.kt")
|
@TestMetadata("kt17091.kt")
|
||||||
public void testKt17091() throws Exception {
|
public void testKt17091() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
||||||
|
|||||||
Generated
+5
@@ -432,6 +432,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObjectToSam.kt")
|
||||||
|
public void testAnonymousObjectToSam() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/anonymousObjectToSam.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt17091.kt")
|
@TestMetadata("kt17091.kt")
|
||||||
public void testKt17091() throws Exception {
|
public void testKt17091() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
||||||
|
|||||||
+5
@@ -432,6 +432,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObjectToSam.kt")
|
||||||
|
public void testAnonymousObjectToSam() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/anonymousObjectToSam.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt17091.kt")
|
@TestMetadata("kt17091.kt")
|
||||||
public void testKt17091() throws Exception {
|
public void testKt17091() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
||||||
|
|||||||
Generated
+5
@@ -432,6 +432,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/sam"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObjectToSam.kt")
|
||||||
|
public void testAnonymousObjectToSam() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/anonymousObjectToSam.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt17091.kt")
|
@TestMetadata("kt17091.kt")
|
||||||
public void testKt17091() throws Exception {
|
public void testKt17091() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
runTest("compiler/testData/codegen/boxInline/anonymousObject/sam/kt17091.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user