[K/N] Merged two module deserializers

This commit is contained in:
Igor Chevdar
2022-04-23 14:29:35 +05:00
committed by Space
parent 4531080858
commit 4d2a8f852e
7 changed files with 120 additions and 92 deletions
@@ -13,6 +13,20 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
sealed class CacheDeserializationStrategy {
abstract fun contains(filePath: String): Boolean
object Nothing : CacheDeserializationStrategy() {
override fun contains(filePath: String) = false
}
object WholeModule : CacheDeserializationStrategy() {
override fun contains(filePath: String) = true
}
}
class PartialCacheInfo(val klib: KotlinLibrary, val strategy: CacheDeserializationStrategy)
class CacheSupport(
private val configuration: CompilerConfiguration,
resolvedLibraries: KotlinLibraryResolveResult,
@@ -90,6 +104,10 @@ class CacheSupport(
}
}
internal val libraryToCache = librariesToCache.singleOrNull()?.let {
PartialCacheInfo(it, CacheDeserializationStrategy.WholeModule)
}
internal val preLinkCaches: Boolean =
configuration.get(KonanConfigKeys.PRE_LINK_CACHES, false)
@@ -220,7 +220,6 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
konanKlibDir = File(distribution.klib)
)
val fullExportedNamePrefix: String
get() = configuration.get(KonanConfigKeys.FULL_EXPORTED_NAME_PREFIX) ?: implicitModuleName
@@ -398,6 +397,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
internal val librariesToCache: Set<KotlinLibrary>
get() = cacheSupport.librariesToCache
internal val libraryToCache: PartialCacheInfo?
get() = cacheSupport.libraryToCache
val outputFiles =
OutputFiles(configuration.get(KonanConfigKeys.OUTPUT) ?: cacheSupport.tryGetImplicitOutput(),
target, produce)
@@ -123,6 +123,7 @@ internal fun Context.psiToIr(
exportedDependencies = exportedDependencies,
cachedLibraries = config.cachedLibraries,
lazyIrForCaches = config.lazyIrForCaches,
libraryBeingCached = config.libraryToCache,
unlinkedDeclarationsSupport = unlinkedDeclarationsSupport,
userVisibleIrModulesSupport = config.userVisibleIrModulesSupport
).also { linker ->
@@ -129,7 +129,7 @@ internal val psiToIrPhase = konanUnitPhase(
internal val buildAdditionalCacheInfoPhase = konanUnitPhase(
op = {
irModules.values.single().let { module ->
val moduleDeserializer = irLinker.nonCachedLibraryModuleDeserializers[module.descriptor]
val moduleDeserializer = irLinker.moduleDeserializers[module.descriptor]
if (moduleDeserializer == null) {
require(module.descriptor.isFromInteropLibrary()) { "No module deserializer for ${module.descriptor}" }
} else {
@@ -473,7 +473,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
val moduleDescriptor = packageFragment.packageFragmentDescriptor.containingDeclaration
if (moduleDescriptor.isFromInteropLibrary())
return emptyList()
val moduleDeserializer = context.irLinker.cachedLibraryModuleDeserializers[moduleDescriptor]
val moduleDeserializer = context.irLinker.moduleDeserializers[moduleDescriptor]
?: error("No module deserializer for ${irClass.render()}")
return moduleDeserializer.deserializeClassFields(irClass, outerThisField)
}
@@ -38,7 +38,7 @@ internal class NativeInlineFunctionResolver(override val context: Context) : Def
} else {
// The function is from Lazy IR, get its body from the IR linker.
val moduleDescriptor = packageFragment.packageFragmentDescriptor.containingDeclaration
val moduleDeserializer = context.irLinker.cachedLibraryModuleDeserializers[moduleDescriptor]
val moduleDeserializer = context.irLinker.moduleDeserializers[moduleDescriptor]
?: error("No module deserializer for ${function.render()}")
context.specialDeclarationsFactory.loweredInlineFunctions[function] = moduleDeserializer.deserializeInlineFunction(function)
function
@@ -42,6 +42,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
import org.jetbrains.kotlin.ir.types.*
@@ -322,6 +324,7 @@ internal class KonanIrLinker(
exportedDependencies: List<ModuleDescriptor>,
private val cachedLibraries: CachedLibraries,
private val lazyIrForCaches: Boolean,
private val libraryBeingCached: PartialCacheInfo?,
override val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport,
override val userVisibleIrModulesSupport: UserVisibleIrModulesSupport
) : KotlinIrLinker(currentModule, messageLogger, builtIns, symbolTable, exportedDependencies) {
@@ -341,8 +344,7 @@ internal class KonanIrLinker(
override val fakeOverrideBuilder: FakeOverrideBuilder =
FakeOverrideBuilder(this, symbolTable, KonanManglerIr, IrTypeSystemContextImpl(builtIns), friendModules, KonanFakeOverrideClassFilter)
val nonCachedLibraryModuleDeserializers = mutableMapOf<ModuleDescriptor, KonanModuleDeserializer>()
val cachedLibraryModuleDeserializers = mutableMapOf<ModuleDescriptor, KonanCachedLibraryModuleDeserializer>()
val moduleDeserializers = mutableMapOf<ModuleDescriptor, KonanPartialModuleDeserializer>()
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategyResolver: (String) -> DeserializationStrategy) =
when {
@@ -355,14 +357,14 @@ internal class KonanIrLinker(
klib.isInteropLibrary() -> {
KonanInteropModuleDeserializer(moduleDescriptor, klib, cachedLibraries.isLibraryCached(klib))
}
lazyIrForCaches && cachedLibraries.isLibraryCached(klib) -> {
KonanCachedLibraryModuleDeserializer(moduleDescriptor, klib).also {
cachedLibraryModuleDeserializers[moduleDescriptor] = it
}
}
else -> {
KonanModuleDeserializer(moduleDescriptor, klib, strategyResolver).also {
nonCachedLibraryModuleDeserializers[moduleDescriptor] = it
val deserializationStrategy = when {
klib == libraryBeingCached?.klib -> libraryBeingCached.strategy
lazyIrForCaches && cachedLibraries.isLibraryCached(klib) -> CacheDeserializationStrategy.Nothing
else -> CacheDeserializationStrategy.WholeModule
}
KonanPartialModuleDeserializer(moduleDescriptor, klib, strategyResolver, deserializationStrategy).also {
moduleDeserializers[moduleDescriptor] = it
}
}
}
@@ -401,12 +403,19 @@ internal class KonanIrLinker(
private val InvalidIndex = -1
inner class KonanModuleDeserializer(
inner class KonanPartialModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
klib: KotlinLibrary,
strategyResolver: (String) -> DeserializationStrategy
) : BasicIrModuleDeserializer(this@KonanIrLinker, moduleDescriptor, klib, strategyResolver, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
override val klib: KotlinLibrary,
strategyResolver: (String) -> DeserializationStrategy,
private val cacheDeserializationStrategy: CacheDeserializationStrategy,
containsErrorCode: Boolean = false
) : BasicIrModuleDeserializer(this, moduleDescriptor, klib,
{ fileName ->
if (cacheDeserializationStrategy.contains(fileName))
strategyResolver(fileName)
else DeserializationStrategy.ON_DEMAND
}, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT, containsErrorCode) {
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
fun buildInlineFunctionReference(irFunction: IrFunction): SerializedInlineFunctionReference {
val signature = irFunction.symbol.signature
@@ -562,76 +571,6 @@ internal class KonanIrLinker(
}
})
}
}
private inner class KonanInteropModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
override val klib: KotlinLibrary,
private val isLibraryCached: Boolean
) : IrModuleDeserializer(moduleDescriptor, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
init {
require(klib.isInteropLibrary())
}
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinderImpl(
moduleDescriptor, KonanManglerDesc,
DescriptorByIdSignatureFinderImpl.LookupMode.MODULE_ONLY
)
private fun IdSignature.isInteropSignature() = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test()
override fun contains(idSig: IdSignature): Boolean {
if (idSig.isPubliclyVisible) {
if (idSig.isInteropSignature()) {
// TODO: add descriptor cache??
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null
}
}
return false
}
private fun DeclarationDescriptor.isCEnumsOrCStruct(): Boolean = cenumsProvider.isCEnumOrCStruct(this)
private val fileMap = mutableMapOf<PackageFragmentDescriptor, IrFile>()
private fun getIrFile(packageFragment: PackageFragmentDescriptor): IrFile = fileMap.getOrPut(packageFragment) {
IrFileImpl(NaiveSourceBasedFileEntryImpl(IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName), packageFragment).also {
moduleFragment.files.add(it)
}
}
private fun resolveCEnumsOrStruct(descriptor: DeclarationDescriptor, idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val file = getIrFile(descriptor.findPackage())
return cenumsProvider.getDeclaration(descriptor, idSig, file, symbolKind).symbol
}
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: return null
// If library is cached we don't need to create an IrClass for struct or enum.
if (!isLibraryCached && descriptor.isCEnumsOrCStruct()) return resolveCEnumsOrStruct(descriptor, idSig, symbolKind)
val symbolOwner = stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner
return symbolOwner.symbol
}
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
override val kind get() = IrModuleDeserializerKind.DESERIALIZED
}
inner class KonanCachedLibraryModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
override val klib: KotlinLibrary
) : BasicIrModuleDeserializer(this@KonanIrLinker, moduleDescriptor, klib,
{ _ -> DeserializationStrategy.ON_DEMAND },
klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT
) {
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinderImpl(
moduleDescriptor, KonanManglerDesc,
@@ -655,14 +594,22 @@ internal class KonanIrLinker(
}
}
override fun contains(idSig: IdSignature) =
deserializedSymbols.containsKey(idSig) ||
idSig.isPubliclyVisible && descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null
override fun contains(idSig: IdSignature): Boolean =
super.contains(idSig) || deserializedSymbols.containsKey(idSig) ||
cacheDeserializationStrategy != CacheDeserializationStrategy.WholeModule
&& idSig.isPubliclyVisible && descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null
val descriptorSignatures = mutableMapOf<DeclarationDescriptor, IdSignature>()
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
super.tryDeserializeIrSymbol(idSig, symbolKind)?.let { return it }
deserializedSymbols[idSig]?.let { return it }
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: return null
descriptorSignatures[descriptor] = idSig
return (stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner).symbol
}
@@ -687,7 +634,7 @@ internal class KonanIrLinker(
)
}
val signature = function.symbol.signature
val signature = function.symbol.signature ?: descriptorSignatures[function.descriptor]
?: error("No signature for ${function.render()}")
val inlineFunctionReference = inlineFunctionReferences[signature]
?: error("No inline function reference for ${function.render()}, sig = ${signature.render()}")
@@ -819,6 +766,66 @@ internal class KonanIrLinker(
}
}
private inner class KonanInteropModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
override val klib: KotlinLibrary,
private val isLibraryCached: Boolean
) : IrModuleDeserializer(moduleDescriptor, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
init {
require(klib.isInteropLibrary())
}
private val descriptorByIdSignatureFinder = DescriptorByIdSignatureFinderImpl(
moduleDescriptor, KonanManglerDesc,
DescriptorByIdSignatureFinderImpl.LookupMode.MODULE_ONLY
)
private fun IdSignature.isInteropSignature() = IdSignature.Flags.IS_NATIVE_INTEROP_LIBRARY.test()
override fun contains(idSig: IdSignature): Boolean {
if (idSig.isPubliclyVisible) {
if (idSig.isInteropSignature()) {
// TODO: add descriptor cache??
return descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) != null
}
}
return false
}
private fun DeclarationDescriptor.isCEnumsOrCStruct(): Boolean = cenumsProvider.isCEnumOrCStruct(this)
private val fileMap = mutableMapOf<PackageFragmentDescriptor, IrFile>()
private fun getIrFile(packageFragment: PackageFragmentDescriptor): IrFile = fileMap.getOrPut(packageFragment) {
IrFileImpl(NaiveSourceBasedFileEntryImpl(IrProviderForCEnumAndCStructStubs.cTypeDefinitionsFileName), packageFragment).also {
moduleFragment.files.add(it)
}
}
private fun resolveCEnumsOrStruct(descriptor: DeclarationDescriptor, idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
val file = getIrFile(descriptor.findPackage())
return cenumsProvider.getDeclaration(descriptor, idSig, file, symbolKind).symbol
}
override fun tryDeserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol? {
val descriptor = descriptorByIdSignatureFinder.findDescriptorBySignature(idSig) ?: return null
// If library is cached we don't need to create an IrClass for struct or enum.
if (!isLibraryCached && descriptor.isCEnumsOrCStruct()) return resolveCEnumsOrStruct(descriptor, idSig, symbolKind)
val symbolOwner = stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner
return symbolOwner.symbol
}
override fun deserializedSymbolNotFound(idSig: IdSignature): Nothing = error("No descriptor found for $idSig")
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
override val kind get() = IrModuleDeserializerKind.DESERIALIZED
}
private inner class KonanForwardDeclarationModuleDeserializer(moduleDescriptor: ModuleDescriptor) : IrModuleDeserializer(moduleDescriptor, KotlinAbiVersion.CURRENT) {
init {
require(moduleDescriptor.isForwardDeclarationModule)