diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index b24758e1f49..841767d95fa 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -77,7 +77,7 @@ abstract class InlineCodegen( .mapTo(mutableSetOf()) { parameters.getDeclarationSlot(it) } ) for (info in infos) { - val lambda = DefaultLambda(info, sourceCompiler) + val lambda = DefaultLambda(info, sourceCompiler, node.name.substringBeforeLast("\$default")) parameters.getParameterByDeclarationSlot(info.offset).functionalArgument = lambda if (info.needReification) { lambda.reifiedTypeParametersUsages.mergeAll(reifiedTypeInliner.reifyInstructions(lambda.node.node)) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index 893dc9a20f2..4dec3c14a7a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.codegen.inline import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass +import org.jetbrains.kotlin.load.java.JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.Method -import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode +import org.jetbrains.org.objectweb.asm.tree.* interface FunctionalArgument @@ -75,7 +74,8 @@ abstract class ExpressionLambda : LambdaInfo() { } } -class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline) : LambdaInfo() { +class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompilerForInline, private val functionName: String) : + LambdaInfo() { val isBoundCallableReference: Boolean override val lambdaClassType: Type = info.type @@ -132,7 +132,30 @@ class DefaultLambda(info: ExtractedDefaultLambda, sourceCompiler: SourceCompiler capturedParamDesc(fieldNode.name, Type.getType(fieldNode.desc), isSuspend = false) }?.toList() ?: emptyList() isBoundCallableReference = isReference && capturedVars.isNotEmpty() - node = loadDefaultLambdaBody(classBytes, lambdaClassType, isPropertyReference) + val (originNode, classSmap) = loadDefaultLambdaBody(classBytes, lambdaClassType, isPropertyReference) + node = SMAPAndMethodNode(createNodeWithFakeVariables(originNode), classSmap) + } + + private fun createNodeWithFakeVariables(originNode: MethodNode): MethodNode { + val withFakeVariable = + MethodNode(originNode.access, originNode.name, originNode.desc, originNode.signature, originNode.exceptions?.toTypedArray()) + val fakeVarIndex = originNode.maxLocals + originNode.accept(withFakeVariable) + val startLabel = + withFakeVariable.instructions.first as? LabelNode ?: LabelNode().apply { withFakeVariable.instructions.insert(this) } + val endLabel = withFakeVariable.instructions.last as? LabelNode ?: LabelNode().apply { withFakeVariable.instructions.add(this) } + withFakeVariable.instructions.insert(startLabel, VarInsnNode(Opcodes.ISTORE, fakeVarIndex)) + withFakeVariable.instructions.insert(startLabel, LdcInsnNode(0)) + + withFakeVariable.localVariables.add( + LocalVariableNode( + "$LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT-$functionName-" + lambdaClassType.internalName.substringAfterLast( + '/' + ), Type.INT_TYPE.descriptor, null, startLabel, endLabel, fakeVarIndex + ) + ) + withFakeVariable.maxLocals = withFakeVariable.maxLocals + 1 + return withFakeVariable } private companion object { 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 cbf5d4082db..75172b07786 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 @@ -3442,6 +3442,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("defaultLambda.kt") + public void testDefaultLambda() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt"); + } + @Test @TestMetadata("deleteClassOnTransformation.kt") public void testDeleteClassOnTransformation() throws Exception { diff --git a/compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt b/compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt new file mode 100644 index 00000000000..f73720e77cf --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt @@ -0,0 +1,15 @@ +package test + +inline fun inlineFun(lambda: () -> String = { T::class.java.simpleName }): String { + return lambda() +} + +class OK + +fun box(): String { + return inlineFun() +} + +// 1 LOCALVARIABLE \$i\$a\$-inlineFun-DefaultLambdaKt\$inlineFun\$1 I +// inlineFun, inlineFun$default, inlined inlineFun: +// 3 LOCALVARIABLE \$i\$f\$inlineFun \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index c11413f111a..c3390769e75 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -3172,6 +3172,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("defaultLambda.kt") + public void testDefaultLambda() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt"); + } + @Test @TestMetadata("deleteClassOnTransformation.kt") public void testDeleteClassOnTransformation() throws Exception { 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 04f602c506a..09a9a26615d 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 @@ -3442,6 +3442,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("defaultLambda.kt") + public void testDefaultLambda() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inline/defaultLambda.kt"); + } + @Test @TestMetadata("deleteClassOnTransformation.kt") public void testDeleteClassOnTransformation() throws Exception {