JVM IR: generate private @JvmStatic functions as in old backend

#KT-46181 Fixed
This commit is contained in:
Alexander Udalov
2021-09-02 22:43:52 +02:00
parent ed035d99ab
commit 9a472c418f
13 changed files with 184 additions and 39 deletions
@@ -118,9 +118,7 @@ private class CompanionObjectJvmStaticTransformer(val context: JvmBackendContext
private fun IrSimpleFunction.needsStaticProxy(): Boolean = when {
// Case 1: `external` static methods are moved to the outer class. JNI code does not care about visibility.
isExternal -> true
// Case 2: `JvmStatic` is useless on private/inline-only methods because they're not visible to any Java code anyway.
visibility == DescriptorVisibilities.PRIVATE -> false
visibility == DescriptorVisibilities.PRIVATE_TO_THIS -> false
// Case 2: `JvmStatic` is useless on inline-only methods because they're not visible to any Java code anyway.
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS -> false
isEffectivelyInlineOnly() -> false
// Case 3: protected non-inline needs a static proxy in the parent to be callable from subclasses
@@ -0,0 +1,35 @@
// WITH_RUNTIME
// For a private @JvmStatic function `f` in `A.Companion`, we generate:
// 1) private instance method `f` in `A.Companion`, with the actual implementation;
// 2) public static method `access$f` in `A.Companion` which calls `A.Companion.f`;
// 3) private static method `f` in `A` which calls `A.Companion.access$f`.
// (which is basically the same as all @JvmStatic companion functions, except that we also need an accessor here.)
//
// This might seem like an overkill, but there are actually some use cases, namely private static helpers for JNI (see KT-46181).
class A {
companion object {
@JvmStatic
private fun f(p: Int) {}
@JvmStatic
private val x = ""
private var xx: String
@JvmStatic get() = ""
@JvmStatic set(value) {}
}
}
object O {
@JvmStatic
private fun g(q: Int) {}
@JvmStatic
private val y = ""
private var yy: String
@JvmStatic get() = ""
@JvmStatic set(value) {}
}
@@ -0,0 +1,40 @@
@kotlin.Metadata
public final class A$Companion {
// source: 'jvmStaticPrivate.kt'
private method <init>(): void
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
public synthetic final static method access$f(p0: A$Companion, p1: int): void
public synthetic final static method access$getXx$p(p0: A$Companion): java.lang.String
public synthetic final static method access$setXx$p(p0: A$Companion, p1: java.lang.String): void
private final @kotlin.jvm.JvmStatic method f(p0: int): void
private synthetic deprecated static @kotlin.jvm.JvmStatic method getX$annotations(): void
private final @kotlin.jvm.JvmStatic method getXx(): java.lang.String
private final @kotlin.jvm.JvmStatic method setXx(p0: java.lang.String): void
public final inner class A$Companion
}
@kotlin.Metadata
public final class A {
// source: 'jvmStaticPrivate.kt'
public final static @org.jetbrains.annotations.NotNull field Companion: A$Companion
private final static field x: java.lang.String
static method <clinit>(): void
public method <init>(): void
private final static @kotlin.jvm.JvmStatic method f(p0: int): void
private final static @kotlin.jvm.JvmStatic method getXx(): java.lang.String
private final static @kotlin.jvm.JvmStatic method setXx(p0: java.lang.String): void
public final inner class A$Companion
}
@kotlin.Metadata
public final class O {
// source: 'jvmStaticPrivate.kt'
public final static @org.jetbrains.annotations.NotNull field INSTANCE: O
private final static field y: java.lang.String
static method <clinit>(): void
private method <init>(): void
private final static @kotlin.jvm.JvmStatic method g(p0: int): void
private synthetic deprecated static @kotlin.jvm.JvmStatic method getY$annotations(): void
private final static @kotlin.jvm.JvmStatic method getYy(): java.lang.String
private final static @kotlin.jvm.JvmStatic method setYy(p0: java.lang.String): void
}
@@ -0,0 +1,40 @@
@kotlin.Metadata
public final class A$Companion {
// source: 'jvmStaticPrivate.kt'
private method <init>(): void
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
public synthetic final static method access$f(p0: A$Companion, p1: int): void
public synthetic final static method access$getXx(p0: A$Companion): java.lang.String
public synthetic final static method access$setXx(p0: A$Companion, p1: java.lang.String): void
private final @kotlin.jvm.JvmStatic method f(p0: int): void
private synthetic deprecated static @kotlin.jvm.JvmStatic method getX$annotations(): void
private final @kotlin.jvm.JvmStatic method getXx(): java.lang.String
private final @kotlin.jvm.JvmStatic method setXx(p0: java.lang.String): void
public final inner class A$Companion
}
@kotlin.Metadata
public final class A {
// source: 'jvmStaticPrivate.kt'
public final static @org.jetbrains.annotations.NotNull field Companion: A$Companion
private final static @org.jetbrains.annotations.NotNull field x: java.lang.String
static method <clinit>(): void
public method <init>(): void
private final static @kotlin.jvm.JvmStatic method f(p0: int): void
private final static @kotlin.jvm.JvmStatic method getXx(): java.lang.String
private final static @kotlin.jvm.JvmStatic method setXx(p0: java.lang.String): void
public final inner class A$Companion
}
@kotlin.Metadata
public final class O {
// source: 'jvmStaticPrivate.kt'
public final static @org.jetbrains.annotations.NotNull field INSTANCE: O
private final static @org.jetbrains.annotations.NotNull field y: java.lang.String
static method <clinit>(): void
private method <init>(): void
private final static @kotlin.jvm.JvmStatic method g(p0: int): void
private synthetic deprecated static @kotlin.jvm.JvmStatic method getY$annotations(): void
private final static @kotlin.jvm.JvmStatic method getYy(): java.lang.String
private final static @kotlin.jvm.JvmStatic method setYy(p0: java.lang.String): void
}
@@ -151,24 +151,6 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/jvmRecordStructure.kt");
}
@Test
@TestMetadata("jvmStaticExternal.kt")
public void testJvmStaticExternal() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStaticExternal.kt");
}
@Test
@TestMetadata("jvmStaticWithDefaultParameters.kt")
public void testJvmStaticWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStaticWithDefaultParameters.kt");
}
@Test
@TestMetadata("kt31389.kt")
public void testKt31389() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/kt31389.kt");
}
@Test
@TestMetadata("kt42137.kt")
public void testKt42137() throws Exception {
@@ -1811,6 +1793,40 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeListing/jvmStatic")
@TestDataPath("$PROJECT_ROOT")
public class JvmStatic {
@Test
public void testAllFilesPresentInJvmStatic() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvmStatic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("jvmStaticExternal.kt")
public void testJvmStaticExternal() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticExternal.kt");
}
@Test
@TestMetadata("jvmStaticPrivate.kt")
public void testJvmStaticPrivate() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticPrivate.kt");
}
@Test
@TestMetadata("jvmStaticWithDefaultParameters.kt")
public void testJvmStaticWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticWithDefaultParameters.kt");
}
@Test
@TestMetadata("kt31389.kt")
public void testKt31389() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/kt31389.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeListing/localFunctions")
@TestDataPath("$PROJECT_ROOT")
@@ -151,24 +151,6 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/jvmRecordStructure.kt");
}
@Test
@TestMetadata("jvmStaticExternal.kt")
public void testJvmStaticExternal() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStaticExternal.kt");
}
@Test
@TestMetadata("jvmStaticWithDefaultParameters.kt")
public void testJvmStaticWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStaticWithDefaultParameters.kt");
}
@Test
@TestMetadata("kt31389.kt")
public void testKt31389() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/kt31389.kt");
}
@Test
@TestMetadata("kt42137.kt")
public void testKt42137() throws Exception {
@@ -1859,6 +1841,40 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeListing/jvmStatic")
@TestDataPath("$PROJECT_ROOT")
public class JvmStatic {
@Test
public void testAllFilesPresentInJvmStatic() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/jvmStatic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("jvmStaticExternal.kt")
public void testJvmStaticExternal() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticExternal.kt");
}
@Test
@TestMetadata("jvmStaticPrivate.kt")
public void testJvmStaticPrivate() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticPrivate.kt");
}
@Test
@TestMetadata("jvmStaticWithDefaultParameters.kt")
public void testJvmStaticWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/jvmStaticWithDefaultParameters.kt");
}
@Test
@TestMetadata("kt31389.kt")
public void testKt31389() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/jvmStatic/kt31389.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeListing/localFunctions")
@TestDataPath("$PROJECT_ROOT")