Lazy module name propagation
This commit is contained in:
@@ -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<T extends JetElement/* TODO: & JetDeclaratio
|
||||
v.putstatic(thisAsmType.getInternalName(), fieldName, type);
|
||||
}
|
||||
|
||||
public static void generateModuleNameField(
|
||||
@NotNull GenerationState state,
|
||||
@NotNull ClassBuilder classBuilder
|
||||
) {
|
||||
classBuilder.newField(NO_ORIGIN, ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$moduleName",
|
||||
AsmTypes.JAVA_STRING_TYPE.getDescriptor(), null, JvmCodegenUtil.getModuleName(state.getModule()));
|
||||
}
|
||||
|
||||
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
|
||||
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
||||
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
|
||||
|
||||
@@ -249,6 +249,7 @@ public class PackageCodegen {
|
||||
@NotNull List<JvmSerializationBindings> bindings
|
||||
) {
|
||||
generateKotlinPackageReflectionField();
|
||||
MemberCodegen.generateModuleNameField(state, v);
|
||||
|
||||
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
||||
tasks.get(member).run();
|
||||
|
||||
+3
-1
@@ -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())
|
||||
|
||||
+3
-3
@@ -48,11 +48,11 @@ public class LazyJavaPackageScope(
|
||||
public val kotlinBinaryClass: KotlinJvmBinaryClass?
|
||||
= c.components.kotlinClassFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFragment.fqName))
|
||||
|
||||
public val kotlinBinaryClasses: List<KotlinJvmBinaryClass>
|
||||
init {
|
||||
public val kotlinBinaryClasses: List<KotlinJvmBinaryClass> 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()
|
||||
|
||||
+6
-5
@@ -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("<runtime module for $classLoader>"), 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-19
@@ -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<String, Lazy<ModuleMapping>>()
|
||||
|
||||
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<String> {
|
||||
return mapping.package2MiniFacades.getOrElse (packageInternalName, { PackageFacades("default") }).parts.toList()
|
||||
return module2Mapping.values().map { it.value.findPackageParts(packageInternalName) }.filterNotNull().flatMap { it.parts }.distinct()
|
||||
}
|
||||
}
|
||||
@@ -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<ConstructorDescriptor>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -44,8 +44,9 @@ private class WeakClassLoaderBox(classLoader: ClassLoader) {
|
||||
ref.get()?.let { it.toString() } ?: "<null>"
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
@@ -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<kotlin.jvm.internal.KotlinPackage>()) != null) KPackageImpl(this, "undefined") else null
|
||||
getAnnotation(javaClass<kotlin.jvm.internal.KotlinPackage>()) != null) {
|
||||
val field = this.getField("\$moduleName")
|
||||
if (field != null) {
|
||||
KPackageImpl(this, field.get(null) as String)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
} else null
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user