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.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
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.LockBasedStorageManager;
|
||||||
import org.jetbrains.kotlin.storage.NotNullLazyValue;
|
import org.jetbrains.kotlin.storage.NotNullLazyValue;
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils;
|
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);
|
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) {
|
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
|
||||||
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
|
||||||
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
|
for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ public class PackageCodegen {
|
|||||||
@NotNull List<JvmSerializationBindings> bindings
|
@NotNull List<JvmSerializationBindings> bindings
|
||||||
) {
|
) {
|
||||||
generateKotlinPackageReflectionField();
|
generateKotlinPackageReflectionField();
|
||||||
|
MemberCodegen.generateModuleNameField(state, v);
|
||||||
|
|
||||||
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
for (CallableMemberDescriptor member : Ordering.from(MemberComparator.INSTANCE).sortedCopy(tasks.keySet())) {
|
||||||
tasks.get(member).run();
|
tasks.get(member).run();
|
||||||
|
|||||||
+3
-1
@@ -130,7 +130,9 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createReflectedPackageView(classLoader: URLClassLoader, moduleName: String): SyntheticPackageViewForTest {
|
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())
|
val generatedPackageDir = File(tmpdir, LoadDescriptorUtil.TEST_PACKAGE_FQNAME.pathSegments().single().asString())
|
||||||
|
|||||||
+3
-3
@@ -48,11 +48,11 @@ public class LazyJavaPackageScope(
|
|||||||
public val kotlinBinaryClass: KotlinJvmBinaryClass?
|
public val kotlinBinaryClass: KotlinJvmBinaryClass?
|
||||||
= c.components.kotlinClassFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFragment.fqName))
|
= c.components.kotlinClassFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFragment.fqName))
|
||||||
|
|
||||||
public val kotlinBinaryClasses: List<KotlinJvmBinaryClass>
|
public val kotlinBinaryClasses: List<KotlinJvmBinaryClass> by lazy {
|
||||||
init {
|
|
||||||
val files = c.components.packageMapper.findPackageFacades(jPackage.getFqName().asString().replace('.', '/'))
|
val files = c.components.packageMapper.findPackageFacades(jPackage.getFqName().asString().replace('.', '/'))
|
||||||
val packageClassId = PackageClassUtils.getPackageClassId(packageFragment.fqName).packageFqName
|
val packageClassId = PackageClassUtils.getPackageClassId(packageFragment.fqName).packageFqName
|
||||||
kotlinBinaryClasses = files.map {
|
|
||||||
|
files.map {
|
||||||
val classId = ClassId(packageClassId, Name.identifierNoValidate(it.substringAfterLast("/")))
|
val classId = ClassId(packageClassId, Name.identifierNoValidate(it.substringAfterLast("/")))
|
||||||
c.components.kotlinClassFinder.findKotlinClass(classId)
|
c.components.kotlinClassFinder.findKotlinClass(classId)
|
||||||
}.filterNotNull()
|
}.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.components.*
|
||||||
import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
|
import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider
|
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.lazy.SingleModuleClassResolver
|
||||||
import org.jetbrains.kotlin.load.java.reflect.ReflectJavaClassFinder
|
import org.jetbrains.kotlin.load.java.reflect.ReflectJavaClassFinder
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaPropertyInitializerEvaluator
|
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.serialization.deserialization.LocalClassResolver
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
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 module: ModuleDescriptor get() = deserialization.moduleDescriptor
|
||||||
public val localClassResolver: LocalClassResolver get() = deserialization.localClassResolver
|
public val localClassResolver: LocalClassResolver get() = deserialization.localClassResolver
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun create(classLoader: ClassLoader, moduleName: String?): RuntimeModuleData {
|
public fun create(classLoader: ClassLoader): RuntimeModuleData {
|
||||||
val storageManager = LockBasedStorageManager()
|
val storageManager = LockBasedStorageManager()
|
||||||
val module = ModuleDescriptorImpl(Name.special("<runtime module for $classLoader>"), storageManager,
|
val module = ModuleDescriptorImpl(Name.special("<runtime module for $classLoader>"), storageManager,
|
||||||
ModuleParameters(listOf(), JavaToKotlinClassMap.INSTANCE))
|
ModuleParameters(listOf(), JavaToKotlinClassMap.INSTANCE))
|
||||||
@@ -52,12 +51,14 @@ public class RuntimeModuleData private constructor(public val deserialization: D
|
|||||||
val reflectKotlinClassFinder = ReflectKotlinClassFinder(classLoader)
|
val reflectKotlinClassFinder = ReflectKotlinClassFinder(classLoader)
|
||||||
val deserializedDescriptorResolver = DeserializedDescriptorResolver(RuntimeErrorReporter)
|
val deserializedDescriptorResolver = DeserializedDescriptorResolver(RuntimeErrorReporter)
|
||||||
val singleModuleClassResolver = SingleModuleClassResolver()
|
val singleModuleClassResolver = SingleModuleClassResolver()
|
||||||
|
val runtimePackageFacadeProvider = RuntimePackageFacadeProvider(classLoader)
|
||||||
val globalJavaResolverContext = JavaResolverComponents(
|
val globalJavaResolverContext = JavaResolverComponents(
|
||||||
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
|
storageManager, ReflectJavaClassFinder(classLoader), reflectKotlinClassFinder, deserializedDescriptorResolver,
|
||||||
ExternalAnnotationResolver.EMPTY, ExternalSignatureResolver.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY,
|
ExternalAnnotationResolver.EMPTY, ExternalSignatureResolver.DO_NOTHING, RuntimeErrorReporter, JavaResolverCache.EMPTY,
|
||||||
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver, RuntimeSourceElementFactory, singleModuleClassResolver,
|
JavaPropertyInitializerEvaluator.DoNothing, SamConversionResolver, RuntimeSourceElementFactory, singleModuleClassResolver,
|
||||||
if (moduleName == null) PackageFacadeProvider.EMPTY else RuntimePackageFacadeProvider(moduleName, classLoader)
|
runtimePackageFacadeProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
val lazyJavaPackageFragmentProvider =
|
val lazyJavaPackageFragmentProvider =
|
||||||
LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module))
|
LazyJavaPackageFragmentProvider(globalJavaResolverContext, module, ReflectionTypes(module))
|
||||||
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, 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.setDependencies(module, KotlinBuiltIns.getInstance().getBuiltInsModule())
|
||||||
module.initialize(javaDescriptorResolver.packageFragmentProvider)
|
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.descriptors.PackageFacadeProvider
|
||||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackageFacades
|
import java.io.InputStream
|
||||||
import java.io.ByteArrayOutputStream
|
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 module2Mapping = ConcurrentHashMap<String, Lazy<ModuleMapping>>()
|
||||||
val resourceAsStream = classLoader.getResourceAsStream("META-INF/$moduleName.kotlin_module") ?: return@lazy ModuleMapping("")
|
|
||||||
|
|
||||||
try {
|
fun registerModule(moduleName: String?) {
|
||||||
val out = ByteArrayOutputStream(4096)
|
if (moduleName == null) return
|
||||||
val buffer = ByteArray(4096)
|
|
||||||
while (true) {
|
module2Mapping.putIfAbsent(moduleName, lazy {
|
||||||
val r = resourceAsStream.read(buffer)
|
val resourceAsStream: InputStream = classLoader.getResourceAsStream("META-INF/$moduleName.kotlin_module") ?: return@lazy ModuleMapping("")
|
||||||
if (r == -1) break
|
|
||||||
out.write(buffer, 0, r)
|
try {
|
||||||
|
val bytes = resourceAsStream.readBytes()
|
||||||
|
return@lazy ModuleMapping(String(bytes, "UTF-8"))
|
||||||
}
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
val ret = out.toByteArray()
|
return@lazy ModuleMapping("")
|
||||||
return@lazy ModuleMapping(String(ret, "UTF-8"))
|
}
|
||||||
} finally {
|
})
|
||||||
resourceAsStream.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun findPackageFacades(packageInternalName: String): List<String> {
|
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 {
|
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
|
// 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 {
|
val moduleData by ReflectProperties.lazySoft {
|
||||||
jClass.getOrCreateModule(null)
|
jClass.getOrCreateModule()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract val constructorDescriptors: Collection<ConstructorDescriptor>
|
abstract val constructorDescriptors: Collection<ConstructorDescriptor>
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ import kotlin.reflect.KPackage
|
|||||||
|
|
||||||
class KPackageImpl(override val jClass: Class<*>, val moduleName: String) : KDeclarationContainerImpl(), KPackage {
|
class KPackageImpl(override val jClass: Class<*>, val moduleName: String) : KDeclarationContainerImpl(), KPackage {
|
||||||
val descriptor by ReflectProperties.lazySoft {
|
val descriptor by ReflectProperties.lazySoft {
|
||||||
val moduleData = jClass.getOrCreateModule(moduleName)
|
val moduleData = jClass.getOrCreateModule()
|
||||||
|
moduleData.packageFacadeProvider.registerModule(moduleName)
|
||||||
val fqName = jClass.classId.getPackageFqName()
|
val fqName = jClass.classId.getPackageFqName()
|
||||||
|
|
||||||
moduleData.module.getPackage(fqName)
|
moduleData.module.getPackage(fqName)
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ private class WeakClassLoaderBox(classLoader: ClassLoader) {
|
|||||||
ref.get()?.let { it.toString() } ?: "<null>"
|
ref.get()?.let { it.toString() } ?: "<null>"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Class<*>.getOrCreateModule(moduleName: String?): RuntimeModuleData {
|
internal fun Class<*>.getOrCreateModule(): RuntimeModuleData {
|
||||||
val classLoader = this.safeClassLoader
|
val classLoader = this.safeClassLoader
|
||||||
|
|
||||||
val key = WeakClassLoaderBox(classLoader)
|
val key = WeakClassLoaderBox(classLoader)
|
||||||
|
|
||||||
val cached = moduleByClassLoader[key]
|
val cached = moduleByClassLoader[key]
|
||||||
@@ -54,7 +55,7 @@ internal fun Class<*>.getOrCreateModule(moduleName: String?): RuntimeModuleData
|
|||||||
moduleByClassLoader.remove(key, cached)
|
moduleByClassLoader.remove(key, cached)
|
||||||
}
|
}
|
||||||
|
|
||||||
val module = RuntimeModuleData.create(classLoader, moduleName)
|
val module = RuntimeModuleData.create(classLoader)
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
val ref = moduleByClassLoader.putIfAbsent(key, WeakReference(module))
|
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)
|
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/java-interop.html#package-level-functions)
|
||||||
* for more information.
|
* for more information.
|
||||||
*/
|
*/
|
||||||
|
@deprecated("After package refactoring it would be impossible to retrieve package by class")
|
||||||
public val Class<*>.kotlinPackage: KPackage?
|
public val Class<*>.kotlinPackage: KPackage?
|
||||||
get() = if (getSimpleName().endsWith("Package") &&
|
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