From 9f0662468f171e7da94d0bbe78f7debdf6f33171 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 28 Aug 2015 12:14:14 +0300 Subject: [PATCH] Lazy module name propagation --- .../kotlin/codegen/MemberCodegen.java | 9 +++++ .../kotlin/codegen/PackageCodegen.java | 1 + .../AbstractJvmRuntimeDescriptorLoaderTest.kt | 4 +- .../lazy/descriptors/LazyJavaPackageScope.kt | 6 +-- .../load/kotlin/reflect/RuntimeModuleData.kt | 11 +++--- .../reflect/RuntimePackageFacadeProvider.kt | 38 +++++++++---------- .../jvm/internal/KDeclarationContainerImpl.kt | 2 +- .../reflect/jvm/internal/KPackageImpl.kt | 3 +- .../jvm/internal/moduleByClassLoader.kt | 5 ++- .../src/kotlin/reflect/jvm/mapping.kt | 11 +++++- 10 files changed, 57 insertions(+), 33 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 80cadd4c543..638c13ca677 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage; +import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.storage.NotNullLazyValue; import org.jetbrains.kotlin.types.ErrorUtils; @@ -474,6 +475,14 @@ public abstract class MemberCodegen delegatedProperties = new ArrayList(); for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java index 1ca57d90a74..48852fef51d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java @@ -249,6 +249,7 @@ public class PackageCodegen { @NotNull List bindings ) { generateKotlinPackageReflectionField(); + MemberCodegen.generateModuleNameField(state, v); for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) { tasks.get(member).run(); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 3703cffb949..44836798c97 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -130,7 +130,9 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi } private fun createReflectedPackageView(classLoader: URLClassLoader, moduleName: String): SyntheticPackageViewForTest { - val module = RuntimeModuleData.create(classLoader, moduleName).module + val moduleData = RuntimeModuleData.create(classLoader) + moduleData.packageFacadeProvider.registerModule(moduleName) + val module = moduleData.module val generatedPackageDir = File(tmpdir, LoadDescriptorUtil.TEST_PACKAGE_FQNAME.pathSegments().single().asString()) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt index ecf7a2efc55..3c999259766 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt @@ -48,11 +48,11 @@ public class LazyJavaPackageScope( public val kotlinBinaryClass: KotlinJvmBinaryClass? = c.components.kotlinClassFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFragment.fqName)) - public val kotlinBinaryClasses: List - init { + public val kotlinBinaryClasses: List by lazy { val files = c.components.packageMapper.findPackageFacades(jPackage.getFqName().asString().replace('.', '/')) val packageClassId = PackageClassUtils.getPackageClassId(packageFragment.fqName).packageFqName - kotlinBinaryClasses = files.map { + + files.map { val classId = ClassId(packageClassId, Name.identifierNoValidate(it.substringAfterLast("/"))) c.components.kotlinClassFinder.findKotlinClass(classId) }.filterNotNull() diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt index 0fd59ee8e81..6f0d234ed91 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimeModuleData.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.load.java.components.* import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider -import org.jetbrains.kotlin.descriptors.PackageFacadeProvider import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver import org.jetbrains.kotlin.load.java.reflect.ReflectJavaClassFinder import org.jetbrains.kotlin.load.java.structure.JavaPropertyInitializerEvaluator @@ -39,12 +38,12 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolver import org.jetbrains.kotlin.storage.LockBasedStorageManager -public class RuntimeModuleData private constructor(public val deserialization: DeserializationComponents) { +public class RuntimeModuleData private constructor(public val deserialization: DeserializationComponents, val packageFacadeProvider: RuntimePackageFacadeProvider) { public val module: ModuleDescriptor get() = deserialization.moduleDescriptor public val localClassResolver: LocalClassResolver get() = deserialization.localClassResolver companion object { - public fun create(classLoader: ClassLoader, moduleName: String?): RuntimeModuleData { + public fun create(classLoader: ClassLoader): RuntimeModuleData { val storageManager = LockBasedStorageManager() val module = ModuleDescriptorImpl(Name.special(""), storageManager, ModuleParameters(listOf(), JavaToKotlinClassMap.INSTANCE)) @@ -52,12 +51,14 @@ public class RuntimeModuleData private constructor(public val deserialization: D val reflectKotlinClassFinder = ReflectKotlinClassFinder(classLoader) val deserializedDescriptorResolver = DeserializedDescriptorResolver(RuntimeErrorReporter) val singleModuleClassResolver = SingleModuleClassResolver() + val runtimePackageFacadeProvider = RuntimePackageFacadeProvider(classLoader) val globalJavaResolverContext = JavaResolverComponents( storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver, ExternalAnnotationResolver.EMPTY, ExternalSignatureResolver.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY, JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver, RuntimeSourceElementFactory, singleModuleClassResolver, - if (moduleName == null) PackageFacadeProvider.EMPTY else RuntimePackageFacadeProvider(moduleName, classLoader) + runtimePackageFacadeProvider ) + val lazyJavaPackageFragmentProvider = LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module)) val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, module) @@ -70,7 +71,7 @@ public class RuntimeModuleData private constructor(public val deserialization: D module.setDependencies(module, KotlinBuiltIns.getInstance().getBuiltInsModule()) module.initialize(javaDescriptorResolver.packageFragmentProvider) - return RuntimeModuleData(deserializationComponentsForJava.components) + return RuntimeModuleData(deserializationComponentsForJava.components, runtimePackageFacadeProvider) } } } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageFacadeProvider.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageFacadeProvider.kt index 7d90f72ad2f..08d6ed72add 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageFacadeProvider.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackageFacadeProvider.kt @@ -18,31 +18,31 @@ package org.jetbrains.kotlin.load.kotlin.reflect import org.jetbrains.kotlin.descriptors.PackageFacadeProvider import org.jetbrains.kotlin.load.kotlin.ModuleMapping -import org.jetbrains.kotlin.load.kotlin.PackageFacades -import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.util.concurrent.ConcurrentHashMap -class RuntimePackageFacadeProvider(val moduleName: String, val classLoader : ClassLoader) : PackageFacadeProvider { +class RuntimePackageFacadeProvider(val classLoader : ClassLoader) : PackageFacadeProvider { - val mapping: ModuleMapping by lazy { - val resourceAsStream = classLoader.getResourceAsStream("META-INF/$moduleName.kotlin_module") ?: return@lazy ModuleMapping("") + val module2Mapping = ConcurrentHashMap>() - try { - val out = ByteArrayOutputStream(4096) - val buffer = ByteArray(4096) - while (true) { - val r = resourceAsStream.read(buffer) - if (r == -1) break - out.write(buffer, 0, r) + fun registerModule(moduleName: String?) { + if (moduleName == null) return + + module2Mapping.putIfAbsent(moduleName, lazy { + val resourceAsStream: InputStream = classLoader.getResourceAsStream("META-INF/$moduleName.kotlin_module") ?: return@lazy ModuleMapping("") + + try { + val bytes = resourceAsStream.readBytes() + return@lazy ModuleMapping(String(bytes, "UTF-8")) } - - val ret = out.toByteArray() - return@lazy ModuleMapping(String(ret, "UTF-8")) - } finally { - resourceAsStream.close() - } + catch (e: Exception) { + return@lazy ModuleMapping("") + } + }) } + override fun findPackageFacades(packageInternalName: String): List { - return mapping.package2MiniFacades.getOrElse (packageInternalName, { PackageFacades("default") }).parts.toList() + return module2Mapping.values().map { it.value.findPackageParts(packageInternalName) }.filterNotNull().flatMap { it.parts }.distinct() } } \ No newline at end of file diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt index 287a51a57e9..d9a37fc547e 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt @@ -39,7 +39,7 @@ import kotlin.reflect.KotlinReflectionInternalError abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer { // Note: this is stored here on a soft reference to prevent GC from destroying the weak reference to it in the moduleByClassLoader cache val moduleData by ReflectProperties.lazySoft { - jClass.getOrCreateModule(null) + jClass.getOrCreateModule() } abstract val constructorDescriptors: Collection diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt index 3e27cc9081d..726c9e23228 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt @@ -29,7 +29,8 @@ import kotlin.reflect.KPackage class KPackageImpl(override val jClass: Class<*>, val moduleName: String) : KDeclarationContainerImpl(), KPackage { val descriptor by ReflectProperties.lazySoft { - val moduleData = jClass.getOrCreateModule(moduleName) + val moduleData = jClass.getOrCreateModule() + moduleData.packageFacadeProvider.registerModule(moduleName) val fqName = jClass.classId.getPackageFqName() moduleData.module.getPackage(fqName) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt index 5d274af7c25..7ae12643d26 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/moduleByClassLoader.kt @@ -44,8 +44,9 @@ private class WeakClassLoaderBox(classLoader: ClassLoader) { ref.get()?.let { it.toString() } ?: "" } -internal fun Class<*>.getOrCreateModule(moduleName: String?): RuntimeModuleData { +internal fun Class<*>.getOrCreateModule(): RuntimeModuleData { val classLoader = this.safeClassLoader + val key = WeakClassLoaderBox(classLoader) val cached = moduleByClassLoader[key] @@ -54,7 +55,7 @@ internal fun Class<*>.getOrCreateModule(moduleName: String?): RuntimeModuleData moduleByClassLoader.remove(key, cached) } - val module = RuntimeModuleData.create(classLoader, moduleName) + val module = RuntimeModuleData.create(classLoader) try { while (true) { val ref = moduleByClassLoader.putIfAbsent(key, WeakReference(module)) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt index 4b8d90d7a3a..8976f419aa6 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/mapping.kt @@ -92,9 +92,18 @@ public val KType.javaType: Type * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/java-interop.html#package-level-functions) * for more information. */ +@deprecated("After package refactoring it would be impossible to retrieve package by class") public val Class<*>.kotlinPackage: KPackage? get() = if (getSimpleName().endsWith("Package") && - getAnnotation(javaClass()) != null) KPackageImpl(this, "undefined") else null + getAnnotation(javaClass()) != null) { + val field = this.getField("\$moduleName") + if (field != null) { + KPackageImpl(this, field.get(null) as String) + } else { + null + } + + } else null /**