diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index cf7fb5b2d22..0888f2aa371 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1773,6 +1773,10 @@ public class ExpressionCodegen extends KtVisitor impleme } } + public int getLastLineNumber() { + return myLastLineNumber; + } + private void doFinallyOnReturn(@NotNull Label afterReturnLabel) { if(!blockStackElements.isEmpty()) { BlockStackElement stackElement = blockStackElements.peek(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index 4af194c6f2f..be66881e651 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -249,7 +249,8 @@ public class AnonymousObjectTransformer { new InlineCallSiteInfo( anonymousObjectGen.getOwnerInternalName(), sourceNode.name, - isConstructor ? anonymousObjectGen.getNewConstructorDescriptor() : sourceNode.desc) + isConstructor ? anonymousObjectGen.getNewConstructorDescriptor() : sourceNode.desc), + null ); InlineResult result = inliner.doInline(deferringVisitor, new LocalVarRemapper(parameters, 0), false, LabelOwner.NOT_APPLICABLE); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index ae05241243d..ed40818cbb7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -289,13 +289,14 @@ public class InlineCodegen extends CallGenerator { InliningContext info = new RootInliningContext( expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()), - codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings, - AnnotationUtilKt.hasInlineOnlyAnnotation(functionDescriptor) - ); + codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings); - MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, - "Method inlining " + callElement.getText(), - createNestedSourceMapper(nodeAndSmap), info.getCallSiteInfo()); //with captured + MethodInliner inliner = new MethodInliner( + node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, + "Method inlining " + callElement.getText(), + createNestedSourceMapper(nodeAndSmap), info.getCallSiteInfo(), + AnnotationUtilKt.hasInlineOnlyAnnotation(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null + ); //with captured LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index 39b2891bb44..88ba2352b1c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -71,7 +71,7 @@ public class MethodInliner { private int lambdasFinallyBlocks; - private final boolean skipSmap; + private final InlineOnlySmapSkipper inlineOnlySmapSkipper; /* * @@ -88,7 +88,8 @@ public class MethodInliner { boolean isSameModule, @NotNull String errorPrefix, @NotNull SourceMapper sourceMapper, - @NotNull InlineCallSiteInfo inlineCallSiteInfo + @NotNull InlineCallSiteInfo inlineCallSiteInfo, + @Nullable InlineOnlySmapSkipper smapSkipper //non null only for root ) { this.node = node; this.parameters = parameters; @@ -100,7 +101,7 @@ public class MethodInliner { this.inlineCallSiteInfo = inlineCallSiteInfo; this.typeMapper = inliningContext.state.getTypeMapper(); this.result = InlineResult.create(); - skipSmap = inliningContext instanceof RootInliningContext && ((RootInliningContext) inliningContext).skipSmap; + this.inlineOnlySmapSkipper = smapSkipper; } public InlineResult doInline( @@ -162,7 +163,7 @@ public class MethodInliner { final Iterator iterator = anonymousObjectGenerations.iterator(); final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping); - RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter( + final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter( resultNode.access, resultNode.desc, resultNode, @@ -252,7 +253,7 @@ public class MethodInliner { inliningContext.subInlineLambda(info), newCapturedRemapper, true /*cause all calls in same module as lambda*/, "Lambda inlining " + info.getLambdaClassType().getInternalName(), - mapper, inlineCallSiteInfo); + mapper, inlineCallSiteInfo, null); LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift); InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);//TODO add skipped this and receiver @@ -266,6 +267,9 @@ public class MethodInliner { setLambdaInlining(false); addInlineMarker(this, false); mapper.endMapping(); + if (inlineOnlySmapSkipper != null) { + inlineOnlySmapSkipper.markCallSiteLineNumber(remappingMethodAdapter); + } } else if (isAnonymousConstructorCall(owner, name)) { //TODO add method assert anonymousObjectGen != null : " call not corresponds to new call" + owner + " " + name; @@ -341,7 +345,7 @@ public class MethodInliner { node.instructions.resetLabels(); MethodNode transformedNode = new MethodNode(InlineCodegenUtil.API, node.access, node.name, Type.getMethodDescriptor(returnType, allTypes), node.signature, null) { - private final boolean GENERATE_DEBUG_INFO = InlineCodegenUtil.GENERATE_SMAP && !skipSmap; + private final boolean GENERATE_DEBUG_INFO = InlineCodegenUtil.GENERATE_SMAP && inlineOnlySmapSkipper == null; private final boolean isInliningLambda = nodeRemapper.isInsideInliningLambda(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java index 9543800a5c7..194a787ee4e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/RootInliningContext.java @@ -28,7 +28,6 @@ public class RootInliningContext extends InliningContext { public final CodegenContext startContext; private final InlineCallSiteInfo inlineCallSiteInfo; public final TypeParameterMappings typeParameterMappings; - public final boolean skipSmap; public final KtElement callElement; public RootInliningContext( @@ -39,15 +38,13 @@ public class RootInliningContext extends InliningContext { @NotNull KtElement callElement, @NotNull InlineCallSiteInfo classNameToInline, @NotNull ReifiedTypeInliner inliner, - @Nullable TypeParameterMappings typeParameterMappings, - boolean skipSmap + @Nullable TypeParameterMappings typeParameterMappings ) { super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false); this.callElement = callElement; this.startContext = startContext; this.inlineCallSiteInfo = classNameToInline; this.typeParameterMappings = typeParameterMappings; - this.skipSmap = skipSmap; } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt index 902f2533f4e..3cdddcc30f4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/inlineCodegenUtils.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -26,6 +27,8 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.MethodVisitor val FunctionDescriptor.sourceFilePath: String get() { @@ -61,4 +64,17 @@ fun FunctionDescriptor.getClassFilePath(typeMapper: KotlinTypeMapper, cache: Inc cache.getClassFilePath(className) } } +} + +class InlineOnlySmapSkipper(codegen: ExpressionCodegen) { + + val callLineNumber = codegen.lastLineNumber + + fun markCallSiteLineNumber(mv: MethodVisitor) { + if (callLineNumber >= 0) { + val label = Label() + mv.visitLabel(label) + mv.visitLineNumber(callLineNumber, label) + } + } } \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/inlineOnly.out b/idea/testData/debugger/tinyApp/outs/inlineOnly.out index 2fe147125c7..a1799035c79 100644 --- a/idea/testData/debugger/tinyApp/outs/inlineOnly.out +++ b/idea/testData/debugger/tinyApp/outs/inlineOnly.out @@ -2,6 +2,14 @@ LineBreakpoint created at inlineOnly.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! inlineOnly.InlineOnlyKt Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' inlineOnly.kt:5 +inlineOnly.kt:7 +inlineOnly.kt:13 +inlineOnly.kt:14 +inlineOnly.kt:7 +inlineOnly.kt:13 +inlineOnly.kt:14 +inlineOnly.kt:7 +inlineOnly.kt:9 PrintStream.!EXT! Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' diff --git a/idea/testData/debugger/tinyApp/src/stepping/stepInto/inlineOnly.kt b/idea/testData/debugger/tinyApp/src/stepping/stepInto/inlineOnly.kt index ecc00fde4ef..737db2ba756 100644 --- a/idea/testData/debugger/tinyApp/src/stepping/stepInto/inlineOnly.kt +++ b/idea/testData/debugger/tinyApp/src/stepping/stepInto/inlineOnly.kt @@ -2,7 +2,30 @@ package inlineOnly fun main(args: Array) { //Breakpoint! - println("OK") + myPrint("OK") + + forEach { print2("123")} + + println("OK") //stdlib test } +fun print2(s: String){ + val z = s; +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline fun myPrint(s: String) { + val z = s; +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +@kotlin.internal.InlineOnly +inline fun forEach(s: () -> Unit) { + for (i in 1..2) { + s() + } +} + +// STEP_INTO: 9 // TRACING_FILTERS_ENABLED: false \ No newline at end of file