Don't mark library needed if it was touched while looking for cnames.*

Also do minor refactoring.
This commit is contained in:
Svyatoslav Scherbina
2017-10-11 11:47:15 +03:00
committed by SvyatoslavScherbina
parent de2cfce12f
commit 081b990863
6 changed files with 67 additions and 45 deletions
@@ -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.ClassifierAliasingPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.konan.descriptors.ExportedForwardDeclarationsPackageFragmentDescriptor import org.jetbrains.kotlin.backend.konan.descriptors.ExportedForwardDeclarationsPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader 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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
@@ -33,7 +34,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
interface InteropLibrary { interface InteropLibrary {
fun createSyntheticPackages( fun createSyntheticPackages(
module: ModuleDescriptor, module: ModuleDescriptor,
kotlinPackageFragments: List<PackageFragmentDescriptor> konanPackageFragments: List<KonanPackageFragment>
): List<PackageFragmentDescriptor> ): List<PackageFragmentDescriptor>
} }
@@ -211,9 +212,9 @@ private class InteropLibraryImpl(
) : InteropLibrary { ) : InteropLibrary {
override fun createSyntheticPackages( override fun createSyntheticPackages(
module: ModuleDescriptor, module: ModuleDescriptor,
kotlinPackageFragments: List<PackageFragmentDescriptor> konanPackageFragments: List<KonanPackageFragment>
): List<PackageFragmentDescriptor> { ): List<PackageFragmentDescriptor> {
val interopPackageFragments = kotlinPackageFragments.filter { it.fqName == packageFqName } val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName }
val fqNames = InteropBuiltIns.FqNames val fqNames = InteropBuiltIns.FqNames
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.konan.descriptors package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.konan.InteropBuiltIns 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl 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. * The package fragment that redirects all requests for classifier lookup to its targets.
*/ */
class ClassifierAliasingPackageFragmentDescriptor( class ClassifierAliasingPackageFragmentDescriptor(
targets: List<PackageFragmentDescriptor>, module: ModuleDescriptor, fqName: FqName targets: List<KonanPackageFragment>, module: ModuleDescriptor, fqName: FqName
) : PackageFragmentDescriptorImpl(module, fqName) { ) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() { private val memberScope = object : MemberScopeImpl() {
override fun getContributedClassifier(name: Name, location: LookupLocation) = override fun getContributedClassifier(name: Name, location: LookupLocation) =
targets.firstNotNullResult { targets.firstNotNullResult {
it.getMemberScope().getContributedClassifier(name, location) if (it.hasTopLevelClassifier(name)) {
it.getMemberScope().getContributedClassifier(name, location)
} else {
null
}
} }
override fun printScopeStructure(p: Printer) { override fun printScopeStructure(p: Printer) {
@@ -31,6 +31,9 @@ interface KonanLibraryReader {
val isNeededForLink: Boolean get() = true val isNeededForLink: Boolean get() = true
val isDefaultLink: Boolean get() = false val isDefaultLink: Boolean get() = false
val manifestProperties: Properties val manifestProperties: Properties
val moduleHeaderData: ByteArray
fun packageMetadata(fqName: String): ByteArray
fun markPackageAccessed(fqName: String)
fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor
} }
@@ -71,29 +71,28 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
override val dependencies: List<String> override val dependencies: List<String>
get() = manifestProperties.propertyList("dependencies") get() = manifestProperties.propertyList("dependencies")
val moduleHeaderData: ByteArray by lazy { override val moduleHeaderData: ByteArray by lazy {
reader.loadSerializedModule() reader.loadSerializedModule()
} }
override val isNeededForLink: Boolean override var isNeededForLink: Boolean = false
get() { private set
packagesAccessed.forEach {
if (!emptyPackages(moduleHeaderData).contains(it)) { private val emptyPackages by lazy { emptyPackages(moduleHeaderData) }
return true
} override fun markPackageAccessed(fqName: String) {
} if (!isNeededForLink // fast path
return false && !emptyPackages.contains(fqName)) {
isNeededForLink = true
} }
}
val packagesAccessed = mutableSetOf<String>() override fun packageMetadata(fqName: String): ByteArray {
fun packageMetadata(fqName: String): ByteArray {
packagesAccessed.add(fqName)
return reader.loadSerializedPackageFragment(fqName) return reader.loadSerializedPackageFragment(fqName)
} }
override fun moduleDescriptor(specifics: LanguageVersionSettings) override fun moduleDescriptor(specifics: LanguageVersionSettings)
= deserializeModule(specifics, {packageMetadata(it)}, moduleHeaderData, createInteropLibrary(this)) = deserializeModule(specifics, this)
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.backend.konan.serialization 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.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name 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.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
class KonanPackageFragment(fqNameString: String, class KonanPackageFragment(
packageLoader: (String)->KonanLinkData.PackageFragment, val fqNameString: String,
storageManager: StorageManager, module: ModuleDescriptor) : val reader: KonanLibraryReader,
DeserializedPackageFragment(FqName(fqNameString), storageManager: StorageManager, module: ModuleDescriptor
storageManager, module) { ) : DeserializedPackageFragment(FqName(fqNameString), storageManager, module) {
// The proto field is lazy so that we can load only needed // The proto field is lazy so that we can load only needed
// packages from the library. // packages from the library.
val proto: KonanLinkData.PackageFragment by lazy { private val protoForNames: KonanLinkData.PackageFragment by lazy {
packageLoader(fqNameString) parsePackageFragment(reader.packageMetadata(fqNameString))
}
val proto: KonanLinkData.PackageFragment get() = protoForNames.also {
reader.markPackageAccessed(fqNameString)
} }
private val nameResolver by lazy { private val nameResolver by lazy {
NameResolverImpl(proto.getStringTable(), proto.getNameTable()) NameResolverImpl(protoForNames.getStringTable(), protoForNames.getNameTable())
} }
override val classDataFinder by lazy { override val classDataFinder by lazy {
@@ -48,14 +53,23 @@ class KonanPackageFragment(fqNameString: String,
override fun computeMemberScope(): DeserializedPackageMemberScope { override fun computeMemberScope(): DeserializedPackageMemberScope {
val packageProto = proto.getPackage() val packageProto = proto.getPackage()
return DeserializedPackageMemberScope( this, packageProto, return DeserializedPackageMemberScope( this, packageProto,
nameResolver, /* containerSource = */ null, nameResolver, /* containerSource = */ null,
components, {loadClassNames()} ) components, {loadClassNames()} )
} }
private val classifierNames by lazy {
val result = mutableSetOf<Name>()
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<Name> { private fun loadClassNames(): Collection<Name> {
val classNameList = proto.getClasses().getClassNameList() val classNameList = protoForNames.getClasses().getClassNameList()
val names = classNameList.mapNotNull { val names = classNameList.mapNotNull {
val classId = nameResolver.getClassId(it) val classId = nameResolver.getClassId(it)
@@ -16,10 +16,8 @@
package org.jetbrains.kotlin.backend.konan.serialization package org.jetbrains.kotlin.backend.konan.serialization
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.InteropLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.llvm.base64Decode import org.jetbrains.kotlin.backend.konan.llvm.base64Decode
import org.jetbrains.kotlin.backend.konan.llvm.base64Encode import org.jetbrains.kotlin.backend.konan.llvm.base64Encode
@@ -76,15 +74,17 @@ object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer {
} }
fun createKonanPackageFragmentProvider( fun createKonanPackageFragmentProvider(
reader: KonanLibraryReader,
fragmentNames: List<String>, fragmentNames: List<String>,
packageLoader: (String)->KonanLinkData.PackageFragment,
storageManager: StorageManager, module: ModuleDescriptor, storageManager: StorageManager, module: ModuleDescriptor,
configuration: DeserializationConfiguration, configuration: DeserializationConfiguration): PackageFragmentProvider {
interopLibrary: InteropLibrary?): PackageFragmentProvider {
val packageFragments = fragmentNames.map{ val packageFragments = fragmentNames.map{
KonanPackageFragment(it, packageLoader, storageManager, module) KonanPackageFragment(it, reader, storageManager, module)
} }
val interopLibrary = createInteropLibrary(reader)
val syntheticInteropPackageFragments = val syntheticInteropPackageFragments =
interopLibrary?.createSyntheticPackages(module, packageFragments) ?: emptyList() interopLibrary?.createSyntheticPackages(module, packageFragments) ?: emptyList()
@@ -123,10 +123,10 @@ public fun emptyPackages(libraryData: ByteArray)
= parseModuleHeader(libraryData).emptyPackageList = parseModuleHeader(libraryData).emptyPackageList
internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings,
packageLoader:(String)->ByteArray, library: ByteArray, reader: KonanLibraryReader): ModuleDescriptorImpl {
interopLibrary: InteropLibrary?): ModuleDescriptorImpl {
val libraryProto = parseModuleHeader(reader.moduleHeaderData)
val libraryProto = parseModuleHeader(library)
val moduleName = libraryProto.moduleName val moduleName = libraryProto.moduleName
val storageManager = LockBasedStorageManager() val storageManager = LockBasedStorageManager()
@@ -137,10 +137,10 @@ internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings,
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
val provider = createKonanPackageFragmentProvider( val provider = createKonanPackageFragmentProvider(
libraryProto.packageFragmentNameList, reader,
{it -> parsePackageFragment(packageLoader(it))}, libraryProto.packageFragmentNameList,
storageManager, storageManager,
moduleDescriptor, deserializationConfiguration, interopLibrary) moduleDescriptor, deserializationConfiguration)
moduleDescriptor.initialize(provider) moduleDescriptor.initialize(provider)