diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index 0359d70a222..81df0a9f521 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.konan.descriptors.ClassifierAliasingPackageFragmentDescriptor import org.jetbrains.kotlin.backend.konan.descriptors.ExportedForwardDeclarationsPackageFragmentDescriptor import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.backend.konan.serialization.KonanPackageFragment import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor @@ -33,7 +34,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions interface InteropLibrary { fun createSyntheticPackages( module: ModuleDescriptor, - kotlinPackageFragments: List + konanPackageFragments: List ): List } @@ -211,9 +212,9 @@ private class InteropLibraryImpl( ) : InteropLibrary { override fun createSyntheticPackages( module: ModuleDescriptor, - kotlinPackageFragments: List + konanPackageFragments: List ): List { - val interopPackageFragments = kotlinPackageFragments.filter { it.fqName == packageFqName } + val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName } val fqNames = InteropBuiltIns.FqNames diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt index 62c6bda344d..1b0db848c1a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.konan.InteropBuiltIns +import org.jetbrains.kotlin.backend.konan.serialization.KonanPackageFragment import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl @@ -72,14 +73,18 @@ class ExportedForwardDeclarationsPackageFragmentDescriptor( * The package fragment that redirects all requests for classifier lookup to its targets. */ class ClassifierAliasingPackageFragmentDescriptor( - targets: List, module: ModuleDescriptor, fqName: FqName + targets: List, module: ModuleDescriptor, fqName: FqName ) : PackageFragmentDescriptorImpl(module, fqName) { private val memberScope = object : MemberScopeImpl() { override fun getContributedClassifier(name: Name, location: LookupLocation) = targets.firstNotNullResult { - it.getMemberScope().getContributedClassifier(name, location) + if (it.hasTopLevelClassifier(name)) { + it.getMemberScope().getContributedClassifier(name, location) + } else { + null + } } override fun printScopeStructure(p: Printer) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt index 7273f34bb1f..2ce7b79bfc0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt @@ -31,6 +31,9 @@ interface KonanLibraryReader { val isNeededForLink: Boolean get() = true val isDefaultLink: Boolean get() = false val manifestProperties: Properties + val moduleHeaderData: ByteArray + fun packageMetadata(fqName: String): ByteArray + fun markPackageAccessed(fqName: String) fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt index 99711bfa46c..0e28b32428e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt @@ -71,29 +71,28 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int, override val dependencies: List get() = manifestProperties.propertyList("dependencies") - val moduleHeaderData: ByteArray by lazy { + override val moduleHeaderData: ByteArray by lazy { reader.loadSerializedModule() } - override val isNeededForLink: Boolean - get() { - packagesAccessed.forEach { - if (!emptyPackages(moduleHeaderData).contains(it)) { - return true - } - } - return false + override var isNeededForLink: Boolean = false + private set + + private val emptyPackages by lazy { emptyPackages(moduleHeaderData) } + + override fun markPackageAccessed(fqName: String) { + if (!isNeededForLink // fast path + && !emptyPackages.contains(fqName)) { + isNeededForLink = true } + } - val packagesAccessed = mutableSetOf() - - fun packageMetadata(fqName: String): ByteArray { - packagesAccessed.add(fqName) + override fun packageMetadata(fqName: String): ByteArray { return reader.loadSerializedPackageFragment(fqName) } override fun moduleDescriptor(specifics: LanguageVersionSettings) - = deserializeModule(specifics, {packageMetadata(it)}, moduleHeaderData, createInteropLibrary(this)) + = deserializeModule(specifics, this) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt index efbb970c31f..948d91d72c3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -25,20 +26,24 @@ import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.storage.StorageManager -class KonanPackageFragment(fqNameString: String, - packageLoader: (String)->KonanLinkData.PackageFragment, - storageManager: StorageManager, module: ModuleDescriptor) : - DeserializedPackageFragment(FqName(fqNameString), - storageManager, module) { +class KonanPackageFragment( + val fqNameString: String, + val reader: KonanLibraryReader, + storageManager: StorageManager, module: ModuleDescriptor +) : DeserializedPackageFragment(FqName(fqNameString), storageManager, module) { // The proto field is lazy so that we can load only needed // packages from the library. - val proto: KonanLinkData.PackageFragment by lazy { - packageLoader(fqNameString) + private val protoForNames: KonanLinkData.PackageFragment by lazy { + parsePackageFragment(reader.packageMetadata(fqNameString)) + } + + val proto: KonanLinkData.PackageFragment get() = protoForNames.also { + reader.markPackageAccessed(fqNameString) } private val nameResolver by lazy { - NameResolverImpl(proto.getStringTable(), proto.getNameTable()) + NameResolverImpl(protoForNames.getStringTable(), protoForNames.getNameTable()) } override val classDataFinder by lazy { @@ -48,14 +53,23 @@ class KonanPackageFragment(fqNameString: String, override fun computeMemberScope(): DeserializedPackageMemberScope { val packageProto = proto.getPackage() - return DeserializedPackageMemberScope( this, packageProto, - nameResolver, /* containerSource = */ null, + return DeserializedPackageMemberScope( this, packageProto, + nameResolver, /* containerSource = */ null, components, {loadClassNames()} ) } + private val classifierNames by lazy { + val result = mutableSetOf() + result.addAll(loadClassNames()) + protoForNames.getPackage().typeAliasList.mapTo(result) { nameResolver.getName(it.name) } + result + } + + fun hasTopLevelClassifier(name: Name): Boolean = name in classifierNames + private fun loadClassNames(): Collection { - val classNameList = proto.getClasses().getClassNameList() + val classNameList = protoForNames.getClasses().getClassNameList() val names = classNameList.mapNotNull { val classId = nameResolver.getClassId(it) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 7230de0ef74..4afb031fb39 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -16,10 +16,8 @@ package org.jetbrains.kotlin.backend.konan.serialization -import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.InteropLibrary -import org.jetbrains.kotlin.backend.konan.KonanBuiltIns -import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.backend.konan.* +import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.llvm.base64Decode import org.jetbrains.kotlin.backend.konan.llvm.base64Encode @@ -76,15 +74,17 @@ object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer { } fun createKonanPackageFragmentProvider( + reader: KonanLibraryReader, fragmentNames: List, - packageLoader: (String)->KonanLinkData.PackageFragment, storageManager: StorageManager, module: ModuleDescriptor, - configuration: DeserializationConfiguration, - interopLibrary: InteropLibrary?): PackageFragmentProvider { + configuration: DeserializationConfiguration): PackageFragmentProvider { val packageFragments = fragmentNames.map{ - KonanPackageFragment(it, packageLoader, storageManager, module) + KonanPackageFragment(it, reader, storageManager, module) } + + val interopLibrary = createInteropLibrary(reader) + val syntheticInteropPackageFragments = interopLibrary?.createSyntheticPackages(module, packageFragments) ?: emptyList() @@ -123,10 +123,10 @@ public fun emptyPackages(libraryData: ByteArray) = parseModuleHeader(libraryData).emptyPackageList internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, - packageLoader:(String)->ByteArray, library: ByteArray, - interopLibrary: InteropLibrary?): ModuleDescriptorImpl { + reader: KonanLibraryReader): ModuleDescriptorImpl { + + val libraryProto = parseModuleHeader(reader.moduleHeaderData) - val libraryProto = parseModuleHeader(library) val moduleName = libraryProto.moduleName val storageManager = LockBasedStorageManager() @@ -137,10 +137,10 @@ internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) val provider = createKonanPackageFragmentProvider( - libraryProto.packageFragmentNameList, - {it -> parsePackageFragment(packageLoader(it))}, - storageManager, - moduleDescriptor, deserializationConfiguration, interopLibrary) + reader, + libraryProto.packageFragmentNameList, + storageManager, + moduleDescriptor, deserializationConfiguration) moduleDescriptor.initialize(provider)