From 6730fa2bbf032b560eefda02e75e2a4faf90fd88 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Mon, 15 May 2017 11:57:06 +0200 Subject: [PATCH] Support default inline lambda reification --- .../inline/AnonymousObjectTransformer.kt | 2 +- .../kotlin/codegen/inline/InliningContext.kt | 2 +- .../kotlin/codegen/inline/MethodInliner.kt | 23 +++++++++++----- .../boxInline/reified/defaultLambda/nested.kt | 4 +-- .../reified/defaultLambda/nested2.kt | 4 +-- .../reified/defaultLambda/nestedStatic.kt | 2 +- .../reified/defaultLambda/transitiveChain.kt | 23 ++++++++++++++++ .../defaultLambda/transitiveChainStatic.kt | 26 +++++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 12 +++++++++ ...otlinAgainstInlineKotlinTestGenerated.java | 12 +++++++++ 10 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt create mode 100644 compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index 86b0ca77939..b12187d13fc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -183,7 +183,7 @@ class AnonymousObjectTransformer( capturedBuilder: ParametersBuilder, isConstructor: Boolean ): InlineResult { - val typeParametersToReify = inliningContext.root.reifiedTypeInliner.reifyInstructions(sourceNode) + val typeParametersToReify = inliningContext.root.inlineMethodReificator.reifyInstructions(sourceNode) val parameters = if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode) val remapper = RegeneratedLambdaFieldRemapper( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt index 5f77055bfd9..0c95089daf3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt @@ -25,7 +25,7 @@ class RootInliningContext( nameGenerator: NameGenerator, val callElement: KtElement, override val callSiteInfo: InlineCallSiteInfo, - val reifiedTypeInliner: ReifiedTypeInliner, + val inlineMethodReificator: ReifiedTypeInliner, typeParameterMappings: TypeParameterMappings ) : InliningContext( null, expressionMap, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 02cef236bbd..0c03d874bab 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -75,6 +75,12 @@ class MethodInliner( ): InlineResult { //analyze body var transformedNode = markPlacesForInlineAndRemoveInlinable(node, labelOwner, finallyDeepShift) + if (inliningContext.isInliningLambda && + inliningContext.lambdaInfo is DefaultLambda && + inliningContext.lambdaInfo.needReification) { + //TODO maybe move reification in one place + inliningContext.root.inlineMethodReificator.reifyInstructions(transformedNode) + } //substitute returns with "goto end" instruction to keep non local returns in lambdas val end = Label() @@ -203,7 +209,7 @@ class MethodInliner( setLambdaInlining(true) val lambdaSMAP = info.node.classSMAP - val mapper = if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) + val sourceMapper = if (inliningContext.classRegeneration && !inliningContext.isInliningLambda) NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo) else InlineLambdaSourceMapper(sourceMapper.parent!!, info.node) @@ -211,12 +217,12 @@ class MethodInliner( info.node.node, lambdaParameters, inliningContext.subInlineLambda(info), newCapturedRemapper, true /*cause all calls in same module as lambda*/, "Lambda inlining " + info.lambdaClassType.internalName, - mapper, inlineCallSiteInfo, null + sourceMapper, inlineCallSiteInfo, null ) - val remapper = LocalVarRemapper(lambdaParameters, valueParamShift) + val varRemapper = LocalVarRemapper(lambdaParameters, valueParamShift) //TODO add skipped this and receiver - val lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift) + val lambdaResult = inliner.doInline(this.mv, varRemapper, true, info, invokeCall.finallyDepthShift) result.mergeWithNotChangeInfo(lambdaResult) result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages) @@ -225,7 +231,7 @@ class MethodInliner( StackValue.onStack(info.invokeMethod.returnType).put(bridge.returnType, this) setLambdaInlining(false) addInlineMarker(this, false) - mapper.endMapping() + sourceMapper.endMapping() inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter) } else if (isAnonymousConstructorCall(owner, name)) { //TODO add method @@ -268,8 +274,11 @@ class MethodInliner( super.visitMethodInsn(opcode, owner, name, desc, itf) } } - else if (!inliningContext.isInliningLambda && ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) { - //we shouldn't process here content of inlining lambda it should be reified at external level + else if ((!inliningContext.isInliningLambda || + inliningContext.lambdaInfo is DefaultLambda && + inliningContext.lambdaInfo.needReification) && + ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) { + //we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas } else { super.visitMethodInsn(opcode, owner, name, desc, itf) diff --git a/compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt b/compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt index 26e073fb5bd..1fd4510e82a 100644 --- a/compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt +++ b/compiler/testData/codegen/boxInline/reified/defaultLambda/nested.kt @@ -9,11 +9,11 @@ inline fun inlineFun(p: String, lambda: () -> String = { { p + T::cl } // FILE: 2.kt - +//NO_CHECK_LAMBDA_INLINING import test.* class K fun box(): String { - return inlineFun("O") + return inlineFun("O") } diff --git a/compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt b/compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt index eb9ae8bafaa..d0719a7cab8 100644 --- a/compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt +++ b/compiler/testData/codegen/boxInline/reified/defaultLambda/nested2.kt @@ -14,8 +14,8 @@ inline fun inlineFun(p: String, crossinline lambda: () -> String = { import test.* -class OK +class K fun box(): String { - return inlineFun() + return inlineFun("O") } diff --git a/compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt b/compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt index cac8b2b977f..c0b31d9fa9a 100644 --- a/compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt +++ b/compiler/testData/codegen/boxInline/reified/defaultLambda/nestedStatic.kt @@ -9,7 +9,7 @@ inline fun inlineFun(lambda: () -> String = { { T::class.java.simple } // FILE: 2.kt - +//NO_CHECK_LAMBDA_INLINING import test.* class OK diff --git a/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt b/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt new file mode 100644 index 00000000000..dbe837a08e9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt @@ -0,0 +1,23 @@ +// FILE: 1.kt +// SKIP_INLINE_CHECK_IN: inlineFun$default +//WITH_RUNTIME +package test + +class K + +@Suppress("NOT_YET_SUPPORTED_IN_INLINE") +inline fun inlineFun(p: String, lambda: () -> String = { p + T::class.java.simpleName }): String { + return lambda() +} + +inline fun inlineFun2(p: String): String { + return inlineFun(p) +} + +// FILE: 2.kt + +import test.* + +fun box(): String { + return inlineFun2("O") +} diff --git a/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt b/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt new file mode 100644 index 00000000000..65db55b9545 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt @@ -0,0 +1,26 @@ +// FILE: 1.kt +// SKIP_INLINE_CHECK_IN: inlineFun$default +//WITH_RUNTIME +package test + +class OK +class FAIL + +@Suppress("NOT_YET_SUPPORTED_IN_INLINE") +inline fun inlineFun(lambda: () -> String = { T::class.java.simpleName }): String { + return lambda() +} + +inline fun inlineFun2(): String { + return inlineFun() +} + +// FILE: 2.kt + +import test.* + + + +fun box(): String { + return inlineFun2() +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index f9ea22b97c0..069bbc24245 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -2184,6 +2184,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt"); doTest(fileName); } + + @TestMetadata("transitiveChain.kt") + public void testTransitiveChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt"); + doTest(fileName); + } + + @TestMetadata("transitiveChainStatic.kt") + public void testTransitiveChainStatic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index c397dceb089..0d6ce1b022e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -2184,6 +2184,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt"); doTest(fileName); } + + @TestMetadata("transitiveChain.kt") + public void testTransitiveChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChain.kt"); + doTest(fileName); + } + + @TestMetadata("transitiveChainStatic.kt") + public void testTransitiveChainStatic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/transitiveChainStatic.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck")