JVM: do not reify methods of objects in lambdas

All type parameters used in them are not from the inline function
anyway.
This commit is contained in:
pyos
2021-07-07 17:58:17 +02:00
committed by max-kammerer
parent 717cf2066a
commit 07cb3a5ff8
14 changed files with 92 additions and 16 deletions
@@ -295,7 +295,6 @@ class AnonymousObjectTransformer(
capturedBuilder: ParametersBuilder,
isConstructor: Boolean
): InlineResult {
val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
val parameters =
if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode)
@@ -304,7 +303,10 @@ class AnonymousObjectTransformer(
transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor
)
val inliner = MethodInliner(
val reifiedTypeParametersUsages = if (inliningContext.shouldReifyTypeParametersInObjects)
inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode)
else null
val result = MethodInliner(
sourceNode,
parameters,
inliningContext.subInline(transformationInfo.nameGenerator),
@@ -319,10 +321,8 @@ class AnonymousObjectTransformer(
inliningContext.callSiteInfo.file,
inliningContext.callSiteInfo.lineNumber
), null
)
val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify)
).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf())
reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll)
deferringVisitor.visitMaxs(-1, -1)
return result
}
@@ -44,8 +44,16 @@ open class InliningContext(
val lambdaInfo: LambdaInfo?,
val classRegeneration: Boolean
) {
val isInliningLambda
get() = lambdaInfo != null
val isInliningLambda = lambdaInfo != null
// Consider this arrangement:
// inline fun <reified T> f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
// inline fun <reified V> g() = f<...> { /* uses `V` in a local class */ }
// When inlining `f` into `g`, we need to reify the contents of the default for `x` (if it was used), but not the
// contents of the lambda passed as the argument in `g` as all reified type parameters used by the latter are not from `f`.
val shouldReifyTypeParametersInObjects: Boolean
get() = lambdaInfo == null || lambdaInfo is DefaultLambda
var generateAssertField = false
@@ -54,7 +62,8 @@ open class InliningContext(
var isContinuation: Boolean = false
val isRoot: Boolean = parent == null
val isRoot: Boolean
get() = parent == null
val root: RootInliningContext
get() = if (isRoot) this as RootInliningContext else parent!!.root
@@ -318,14 +318,8 @@ class MethodInliner(
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
} else if (ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
// Consider this arrangement:
// inline fun <reified T> f(x: () -> Unit = { /* uses `T` in a local class */ }) = x()
// inline fun <reified V> g() = f<...> { /* uses `V` in a local class */ }
// When inlining `f` into `g`, we need to erase class reification markers from `f` and the default lambda
// (they will be recreated by `handleAnonymousObjectRegeneration` above if `T` is instantiated with another
// reified type parameter), but not from the lambda passed to `f` in `g` (as reified type parameters inside
// it do not belong to `f`, thus we cannot substitute them yet).
if (inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda) {
// If objects are reified, the marker will be recreated by `handleAnonymousObjectRegeneration` above.
if (!inliningContext.shouldReifyTypeParametersInObjects) {
super.visitMethodInsn(opcode, owner, name, desc, itf)
}
} else {
@@ -3822,6 +3822,12 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -0,0 +1,16 @@
// FILE: 1.kt
package test
inline fun <reified T> f(x: () -> String) = x()
inline fun <reified T> g() = f<Unit> {
val x = { T::class.simpleName }
x()!!
}
// FILE: 2.kt
import test.*
class OK
fun box() = g<OK>()
@@ -3822,6 +3822,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3822,6 +3822,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3822,6 +3822,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3822,6 +3822,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3822,6 +3822,12 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3822,6 +3822,12 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@Test
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
@@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");
@@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");
@@ -3085,6 +3085,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt");
}
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt");
}
@TestMetadata("nonCapturingObjectInLambda.kt")
public void testNonCapturingObjectInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");