diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 66eba35ed4e..d9d7e4a9dc0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -295,6 +295,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/kt3845.kt"); } + @Test + @TestMetadata("kt46615.kt") + public void testKt46615() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/kt46615.kt"); + } + @Test @TestMetadata("kt5016.kt") public void testKt5016() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 2d3090bcdae..f8eda83a10f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -134,6 +134,8 @@ class JvmBackendContext( val inlineMethodGenerationLock = Any() + val directInvokedLambdas = mutableListOf() + init { state.mapInlineClass = { descriptor -> typeMapper.mapType(referenceClass(descriptor).defaultType) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 95614593c2a..e89d3a443a4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType import org.jetbrains.kotlin.ir.expressions.* @@ -302,10 +303,15 @@ class ExpressionCodegen( // Do not generate non-null checks for suspend functions. When resumed the arguments // will be null and the actual values are taken from the continuation. - if (irFunction.isSuspend) return + // As a small optimization, don't generate nullability assertions in methods for directly invoked lambdas + if (irFunction is IrFunctionImpl && irFunction.attributeOwnerId in context.directInvokedLambdas) { + context.directInvokedLambdas.remove(irFunction.attributeOwnerId) + return + } + irFunction.extensionReceiverParameter?.let { generateNonNullAssertion(it) } // Private operator functions don't have null checks on value parameters, 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 822b0354b9b..fec70c9a8e8 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 @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol @@ -153,6 +154,10 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) } val irDirectCall = rewriteDirectInvokeToFunctionReference(irInvokeCall, lastFunRef) ?: return null + + // We track instances of IrFunctionImpl corresponding to direct invoked lambdas, + // so we can perform optimization on it later in ExpressionCodegen.kt + if (callee is IrFunctionImpl) context.directInvokedLambdas.add(callee.attributeOwnerId) val newBlock = IrBlockImpl(irBlock.startOffset, irBlock.endOffset, irDirectCall.type) newBlock.statements.addAll(irBlock.statements) newBlock.statements[newBlock.statements.lastIndex] = irDirectCall diff --git a/compiler/testData/codegen/bytecodeText/kt46615.kt b/compiler/testData/codegen/bytecodeText/kt46615.kt new file mode 100644 index 00000000000..680181b0573 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/kt46615.kt @@ -0,0 +1,11 @@ +// TARGET_BACKEND: JVM_IR + +fun box() { + val str = "OK" + val a = { s: String -> s }("OK") + val b = { s: String -> s }(str) + val c = { s: String -> s } + c.invoke("OK") +} + +// 1 checkNotNullParameter \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index a4c9237018e..01fddaf606b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -295,6 +295,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/kt3845.kt"); } + @Test + @TestMetadata("kt46615.kt") + public void testKt46615() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/kt46615.kt"); + } + @Test @TestMetadata("kt5016.kt") public void testKt5016() throws Exception {