Lazy module name propagation

This commit is contained in:
Michael Bogdanov
2015-08-28 12:14:14 +03:00
parent c274ceffe8
commit 9f0662468f
10 changed files with 57 additions and 33 deletions
@@ -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();
@@ -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())
@@ -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()
@@ -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)
}
}
}
@@ -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
/**