Support default inline lambda reification
This commit is contained in:
+1
-1
@@ -183,7 +183,7 @@ class AnonymousObjectTransformer(
|
|||||||
capturedBuilder: ParametersBuilder,
|
capturedBuilder: ParametersBuilder,
|
||||||
isConstructor: Boolean
|
isConstructor: Boolean
|
||||||
): InlineResult {
|
): 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 parameters = if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
|
||||||
|
|
||||||
val remapper = RegeneratedLambdaFieldRemapper(
|
val remapper = RegeneratedLambdaFieldRemapper(
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class RootInliningContext(
|
|||||||
nameGenerator: NameGenerator,
|
nameGenerator: NameGenerator,
|
||||||
val callElement: KtElement,
|
val callElement: KtElement,
|
||||||
override val callSiteInfo: InlineCallSiteInfo,
|
override val callSiteInfo: InlineCallSiteInfo,
|
||||||
val reifiedTypeInliner: ReifiedTypeInliner,
|
val inlineMethodReificator: ReifiedTypeInliner,
|
||||||
typeParameterMappings: TypeParameterMappings
|
typeParameterMappings: TypeParameterMappings
|
||||||
) : InliningContext(
|
) : InliningContext(
|
||||||
null, expressionMap, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false
|
null, expressionMap, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), null, false
|
||||||
|
|||||||
@@ -75,6 +75,12 @@ class MethodInliner(
|
|||||||
): InlineResult {
|
): InlineResult {
|
||||||
//analyze body
|
//analyze body
|
||||||
var transformedNode = markPlacesForInlineAndRemoveInlinable(node, labelOwner, finallyDeepShift)
|
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
|
//substitute returns with "goto end" instruction to keep non local returns in lambdas
|
||||||
val end = Label()
|
val end = Label()
|
||||||
@@ -203,7 +209,7 @@ class MethodInliner(
|
|||||||
setLambdaInlining(true)
|
setLambdaInlining(true)
|
||||||
val lambdaSMAP = info.node.classSMAP
|
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)
|
NestedSourceMapper(sourceMapper, lambdaSMAP.intervals, lambdaSMAP.sourceInfo)
|
||||||
else
|
else
|
||||||
InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
|
InlineLambdaSourceMapper(sourceMapper.parent!!, info.node)
|
||||||
@@ -211,12 +217,12 @@ class MethodInliner(
|
|||||||
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
|
info.node.node, lambdaParameters, inliningContext.subInlineLambda(info),
|
||||||
newCapturedRemapper, true /*cause all calls in same module as lambda*/,
|
newCapturedRemapper, true /*cause all calls in same module as lambda*/,
|
||||||
"Lambda inlining " + info.lambdaClassType.internalName,
|
"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
|
//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.mergeWithNotChangeInfo(lambdaResult)
|
||||||
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
|
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
|
||||||
|
|
||||||
@@ -225,7 +231,7 @@ class MethodInliner(
|
|||||||
StackValue.onStack(info.invokeMethod.returnType).put(bridge.returnType, this)
|
StackValue.onStack(info.invokeMethod.returnType).put(bridge.returnType, this)
|
||||||
setLambdaInlining(false)
|
setLambdaInlining(false)
|
||||||
addInlineMarker(this, false)
|
addInlineMarker(this, false)
|
||||||
mapper.endMapping()
|
sourceMapper.endMapping()
|
||||||
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
|
inlineOnlySmapSkipper?.markCallSiteLineNumber(remappingMethodAdapter)
|
||||||
}
|
}
|
||||||
else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
else if (isAnonymousConstructorCall(owner, name)) { //TODO add method
|
||||||
@@ -268,8 +274,11 @@ class MethodInliner(
|
|||||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!inliningContext.isInliningLambda && ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
|
else if ((!inliningContext.isInliningLambda ||
|
||||||
//we shouldn't process here content of inlining lambda it should be reified at external level
|
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 {
|
else {
|
||||||
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
super.visitMethodInsn(opcode, owner, name, desc, itf)
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ inline fun <reified T> inlineFun(p: String, lambda: () -> String = { { p + T::cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: 2.kt
|
// FILE: 2.kt
|
||||||
|
//NO_CHECK_LAMBDA_INLINING
|
||||||
import test.*
|
import test.*
|
||||||
|
|
||||||
class K
|
class K
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
return inlineFun<OK>("O")
|
return inlineFun<K>("O")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ inline fun <reified T> inlineFun(p: String, crossinline lambda: () -> String = {
|
|||||||
|
|
||||||
import test.*
|
import test.*
|
||||||
|
|
||||||
class OK
|
class K
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
return inlineFun<OK>()
|
return inlineFun<K>("O")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ inline fun <reified T> inlineFun(lambda: () -> String = { { T::class.java.simple
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: 2.kt
|
// FILE: 2.kt
|
||||||
|
//NO_CHECK_LAMBDA_INLINING
|
||||||
import test.*
|
import test.*
|
||||||
|
|
||||||
class OK
|
class OK
|
||||||
|
|||||||
@@ -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 <reified T> inlineFun(p: String, lambda: () -> String = { p + T::class.java.simpleName }): String {
|
||||||
|
return lambda()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified X> inlineFun2(p: String): String {
|
||||||
|
return inlineFun<X>(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return inlineFun2<K>("O")
|
||||||
|
}
|
||||||
+26
@@ -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 <reified T> inlineFun(lambda: () -> String = { T::class.java.simpleName }): String {
|
||||||
|
return lambda()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified X> inlineFun2(): String {
|
||||||
|
return inlineFun<X>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return inlineFun2<OK>()
|
||||||
|
}
|
||||||
@@ -2184,6 +2184,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck")
|
||||||
|
|||||||
+12
@@ -2184,6 +2184,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/defaultLambda/simple.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck")
|
||||||
|
|||||||
Reference in New Issue
Block a user