Introduce KClass-based cache for KPackageFragment
* It is a heavy-weight object that is hard to compute * It is being constructed each type _cached_ method ref is used in equals/hashCode * Module name is deliberately ignored, corresponding doc is added where appropriate #KT-48136 Merge-request: KT-MR-6817 Merged-by: Vsevolod Tolstopyatov <qwwdfsad@gmail.com>
This commit is contained in:
committed by
Space
parent
28310eb970
commit
c6cbab43f7
+12
@@ -41267,6 +41267,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmKPackageCaching.kt")
|
||||||
|
public void testJvmKPackageCaching() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/jvmKPackageCaching.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmKTypeCaching.kt")
|
||||||
|
public void testJvmKTypeCaching() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/jvmKTypeCaching.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/annotations")
|
@TestMetadata("compiler/testData/codegen/box/reflection/annotations")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// FULL_JDK
|
||||||
|
// WITH_REFLECT
|
||||||
|
import kotlin.jvm.internal.*
|
||||||
|
|
||||||
|
class A
|
||||||
|
fun box(): String {
|
||||||
|
val pckg = Reflection.getOrCreateKotlinPackage(A::class.java)
|
||||||
|
System.gc()
|
||||||
|
val pckg2 = Reflection.getOrCreateKotlinPackage(A::class.java)
|
||||||
|
if (pckg === pckg2) return "OK"
|
||||||
|
return "Fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// FULL_JDK
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
class A
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val clz = A::class
|
||||||
|
System.gc()
|
||||||
|
val clz2 = A::class
|
||||||
|
if (clz === clz2) return "OK"
|
||||||
|
return "Fail"
|
||||||
|
}
|
||||||
+12
@@ -41267,6 +41267,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmKPackageCaching.kt")
|
||||||
|
public void testJvmKPackageCaching() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/jvmKPackageCaching.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmKTypeCaching.kt")
|
||||||
|
public void testJvmKTypeCaching() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/reflection/jvmKTypeCaching.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/reflection/annotations")
|
@TestMetadata("compiler/testData/codegen/box/reflection/annotations")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+7
-1
@@ -5,13 +5,19 @@
|
|||||||
|
|
||||||
package kotlin.reflect.jvm.internal
|
package kotlin.reflect.jvm.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.KDeclarationContainer
|
||||||
|
|
||||||
|
|
||||||
private val K_CLASS_CACHE = createCache { KClassImpl(it) }
|
private val K_CLASS_CACHE = createCache { KClassImpl(it) }
|
||||||
|
private val K_PACKAGE_CACHE = createCache { KPackageImpl(it) }
|
||||||
|
|
||||||
// This function is invoked on each reflection access to Java classes, properties, etc. Performance is critical here.
|
// This function is invoked on each reflection access to Java classes, properties, etc. Performance is critical here.
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal fun <T : Any> getOrCreateKotlinClass(jClass: Class<T>): KClassImpl<T> = K_CLASS_CACHE.get(jClass) as KClassImpl<T>
|
internal fun <T : Any> getOrCreateKotlinClass(jClass: Class<T>): KClassImpl<T> = K_CLASS_CACHE.get(jClass) as KClassImpl<T>
|
||||||
|
|
||||||
internal fun clearKClassCache() {
|
internal fun <T : Any> getOrCreateKotlinPackage(jClass: Class<T>): KDeclarationContainer = K_PACKAGE_CACHE.get(jClass)
|
||||||
|
|
||||||
|
internal fun clearCaches() {
|
||||||
K_CLASS_CACHE.clear()
|
K_CLASS_CACHE.clear()
|
||||||
|
K_PACKAGE_CACHE.clear()
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,6 @@ import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.D
|
|||||||
|
|
||||||
internal class KPackageImpl(
|
internal class KPackageImpl(
|
||||||
override val jClass: Class<*>,
|
override val jClass: Class<*>,
|
||||||
@Suppress("unused") val usageModuleName: String? = null // may be useful for debug
|
|
||||||
) : KDeclarationContainerImpl() {
|
) : KDeclarationContainerImpl() {
|
||||||
private inner class Data : KDeclarationContainerImpl.Data() {
|
private inner class Data : KDeclarationContainerImpl.Data() {
|
||||||
private val kotlinClass: ReflectKotlinClass? by ReflectProperties.lazySoft {
|
private val kotlinClass: ReflectKotlinClass? by ReflectProperties.lazySoft {
|
||||||
|
|||||||
@@ -32,17 +32,18 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KDeclarationContainer getOrCreateKotlinPackage(Class javaClass, String moduleName) {
|
public KDeclarationContainer getOrCreateKotlinPackage(Class javaClass, String moduleName) {
|
||||||
return new KPackageImpl(javaClass, moduleName);
|
// moduleName is unused deliberately and only left in public ABI
|
||||||
|
return ClassCachesKt.getOrCreateKotlinPackage(javaClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KClass getOrCreateKotlinClass(Class javaClass) {
|
public KClass getOrCreateKotlinClass(Class javaClass) {
|
||||||
return KClassCacheKt.getOrCreateKotlinClass(javaClass);
|
return ClassCachesKt.getOrCreateKotlinClass(javaClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KClass getOrCreateKotlinClass(Class javaClass, String internalName) {
|
public KClass getOrCreateKotlinClass(Class javaClass, String internalName) {
|
||||||
return KClassCacheKt.getOrCreateKotlinClass(javaClass);
|
return ClassCachesKt.getOrCreateKotlinClass(javaClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -154,7 +155,7 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
|
|||||||
// Misc
|
// Misc
|
||||||
|
|
||||||
public static void clearCaches() {
|
public static void clearCaches() {
|
||||||
KClassCacheKt.clearKClassCache();
|
ClassCachesKt.clearCaches();
|
||||||
ModuleByClassLoaderKt.clearModuleByClassLoaderCache();
|
ModuleByClassLoaderKt.clearModuleByClassLoaderCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public class Reflection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static KDeclarationContainer getOrCreateKotlinPackage(Class javaClass, String moduleName) {
|
public static KDeclarationContainer getOrCreateKotlinPackage(Class javaClass, String moduleName) {
|
||||||
|
// This signature cannot be removed as it is used in FunctionReferenceLowering.kt non-directly
|
||||||
return factory.getOrCreateKotlinPackage(javaClass, moduleName);
|
return factory.getOrCreateKotlinPackage(javaClass, moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user