diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 6b910cd40db..27f55d06aa9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo; import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature; +import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers; import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeKt; @@ -57,10 +58,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.types.JetType; -import org.jetbrains.org.objectweb.asm.AnnotationVisitor; -import org.jetbrains.org.objectweb.asm.Label; -import org.jetbrains.org.objectweb.asm.MethodVisitor; -import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.commons.Method; import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor; @@ -355,6 +353,10 @@ public class FunctionCodegen { JetTypeMapper typeMapper = parentCodegen.typeMapper; Label methodEnd; + + int functionFakeIndex = -1; + int lambdaFakeIndex = -1; + if (context.getParentContext() instanceof DelegatingFacadeContext) { generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (DelegatingFacadeContext) context.getParentContext()); methodEnd = new Label(); @@ -362,6 +364,13 @@ public class FunctionCodegen { else { FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(), functionDescriptor)); + if (context.isInlineFunction()) { + functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE); + } + + if (context.isInliningLambda()) { + lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE); + } Label methodEntry = new Label(); mv.visitLabel(methodEntry); @@ -379,6 +388,27 @@ public class FunctionCodegen { Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper); generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind()); + + if (context.isInlineFunction() && functionFakeIndex != -1) { + mv.visitLocalVariable( + JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + functionDescriptor.getName().asString(), + Type.INT_TYPE.getDescriptor(), null, + methodBegin, methodEnd, + functionFakeIndex); + } + + if (context.isInliningLambda() && thisType != null && lambdaFakeIndex != -1) { + String name = thisType.getClassName(); + int indexOfLambdaOrdinal = name.lastIndexOf("$"); + if (indexOfLambdaOrdinal > 0) { + int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1)); + mv.visitLocalVariable( + JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal, + Type.INT_TYPE.getDescriptor(), null, + methodBegin, methodEnd, + lambdaFakeIndex); + } + } } private static void generateLocalVariableTable( diff --git a/compiler/testData/checkLocalVariablesTable/inlineLambdaWithItParam.kt b/compiler/testData/checkLocalVariablesTable/inlineLambdaWithItParam.kt index 7957e769367..84c8b9879df 100644 --- a/compiler/testData/checkLocalVariablesTable/inlineLambdaWithItParam.kt +++ b/compiler/testData/checkLocalVariablesTable/inlineLambdaWithItParam.kt @@ -14,4 +14,6 @@ class A { // METHOD : A.foo()V // VARIABLE : NAME=zzz TYPE=I INDEX=3 // VARIABLE : NAME=it TYPE=I INDEX=2 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=4 +// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=5 // VARIABLE : NAME=this TYPE=LA; INDEX=0 diff --git a/compiler/testData/checkLocalVariablesTable/inlineLambdaWithParam.kt b/compiler/testData/checkLocalVariablesTable/inlineLambdaWithParam.kt index 4a676161142..fd693e66834 100644 --- a/compiler/testData/checkLocalVariablesTable/inlineLambdaWithParam.kt +++ b/compiler/testData/checkLocalVariablesTable/inlineLambdaWithParam.kt @@ -16,7 +16,10 @@ class A { // METHOD : A.foo()V // VARIABLE : NAME=zzz TYPE=I INDEX=4 // VARIABLE : NAME=l TYPE=I INDEX=3 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=5 // VARIABLE : NAME=zzz TYPE=I INDEX=4 // VARIABLE : NAME=l TYPE=I INDEX=3 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=5 // VARIABLE : NAME=p TYPE=I INDEX=2 +// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=6 // VARIABLE : NAME=this TYPE=LA; INDEX=0 diff --git a/compiler/testData/checkLocalVariablesTable/inlineSimple.kt b/compiler/testData/checkLocalVariablesTable/inlineSimple.kt index c70300b0aa1..6c462f5dde1 100644 --- a/compiler/testData/checkLocalVariablesTable/inlineSimple.kt +++ b/compiler/testData/checkLocalVariablesTable/inlineSimple.kt @@ -14,5 +14,7 @@ class A { // METHOD : A.foo()V // VARIABLE : NAME=zzz TYPE=I INDEX=3 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=4 +// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=5 // VARIABLE : NAME=s TYPE=I INDEX=1 // VARIABLE : NAME=this TYPE=LA; INDEX=0 diff --git a/compiler/testData/checkLocalVariablesTable/inlineSimpleChain.kt b/compiler/testData/checkLocalVariablesTable/inlineSimpleChain.kt index 1c36a039497..32a2c1bd871 100644 --- a/compiler/testData/checkLocalVariablesTable/inlineSimpleChain.kt +++ b/compiler/testData/checkLocalVariablesTable/inlineSimpleChain.kt @@ -19,6 +19,10 @@ class A { // METHOD : A.foo()V // VARIABLE : NAME=zz2 TYPE=I INDEX=5 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=6 +// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=7 // VARIABLE : NAME=z TYPE=I INDEX=3 +// VARIABLE : NAME=$i$a$1 TYPE=I INDEX=8 +// VARIABLE : NAME=$i$f$inlineFun TYPE=I INDEX=9 // VARIABLE : NAME=s TYPE=I INDEX=1 // VARIABLE : NAME=this TYPE=LA; INDEX=0 diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt index 2cf80131a0f..0a39cbbff66 100644 --- a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/differentTypes.kt @@ -12,5 +12,5 @@ fun foo() : String { // 8 ALOAD // 2 LSTORE // 6 LLOAD -// 1 MAXLOCALS = 9 +// 1 MAXLOCALS = 10 // 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt index 903728de080..1c7855885db 100644 --- a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/primitiveMerge.kt @@ -12,5 +12,6 @@ fun test() { // 3 ILOAD // 2 ASTORE // 7 ALOAD -// 3 MAXLOCALS = 3 +// 2 MAXLOCALS = 3 +// 1 MAXLOCALS = 4 // 0 InlineMarker diff --git a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt index 30394ac1a02..ceaff450323 100644 --- a/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt +++ b/compiler/testData/codegen/bytecodeText/storeStackBeforeInline/withLambda.kt @@ -7,5 +7,5 @@ fun foo() : String { // 6 ASTORE // 21 ALOAD -// 1 MAXLOCALS = 5 +// 1 MAXLOCALS = 7 // 0 InlineMarker diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index 7fd238d67cd..e16ce126b8e 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -57,6 +57,9 @@ public final class JvmAbi { public static final String DEFAULT_MODULE_NAME = "main"; public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl")); + public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT = "$i$a$"; + public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION = "$i$f$"; + @NotNull public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) { return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX; diff --git a/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out b/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out index b24fb55f809..485747531a2 100644 --- a/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out +++ b/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out @@ -25,6 +25,8 @@ inline fun foo(f: () -> Unit) { local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} (sp = frameSharedVarLocalVar.kt, 3) local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1 (sp = frameSharedVarLocalVar.kt, 4) field = element: int = 1 (sp = Ref.!EXT!) + local = $i$a$1: int = 0 (sp = null) + local = $i$f$foo: int = 0 (sp = null) Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0