From 95541da9a186ad38977fb74b0313d126d67d8d0a Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Sun, 2 Apr 2023 12:22:17 +0200 Subject: [PATCH] [K/N] Remove unused default dependencies from klib ^KT-55603 --- .../jetbrains/kotlin/ir/util/SymbolTable.kt | 25 +++++++++------ .../IncrementalCompilationSupport.kt | 4 ++- .../jetbrains/kotlin/backend/konan/Fir2Ir.kt | 31 +++++++++++++++---- .../backend/konan/FirNativeSerializer.kt | 7 +++-- .../backend/konan/driver/phases/Fir2Ir.kt | 4 ++- 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 824f8dd6bb2..720778f60fa 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -1147,23 +1147,28 @@ open class SymbolTable( throw IllegalArgumentException("Unexpected value descriptor: $value") } - private inline fun > FlatSymbolTable.forEachPublicSymbolImpl( + private inline fun > FlatSymbolTable.forEachSymbolImpl( block: (IrSymbol) -> Unit ) { idSigToSymbol.forEach { (_, sym) -> - assert(sym.isPublicApi) block(sym) } } - fun forEachPublicSymbol(block: (IrSymbol) -> Unit) { - classSymbolTable.forEachPublicSymbolImpl { block(it) } - constructorSymbolTable.forEachPublicSymbolImpl { block(it) } - simpleFunctionSymbolTable.forEachPublicSymbolImpl { block(it) } - propertySymbolTable.forEachPublicSymbolImpl { block(it) } - enumEntrySymbolTable.forEachPublicSymbolImpl { block(it) } - typeAliasSymbolTable.forEachPublicSymbolImpl { block(it) } - fieldSymbolTable.forEachPublicSymbolImpl { block(it) } + /** + * This function is quite messy and doesn't have good contract of what exactly is traversed. + * Basic idea is it traverse symbols which can be reasonable referered from other module + * + * Be careful when using it, and avoid it, except really need. + */ + fun forEachDeclarationSymbol(block: (IrSymbol) -> Unit) { + classSymbolTable.forEachSymbolImpl { block(it) } + constructorSymbolTable.forEachSymbolImpl { block(it) } + simpleFunctionSymbolTable.forEachSymbolImpl { block(it) } + propertySymbolTable.forEachSymbolImpl { block(it) } + enumEntrySymbolTable.forEachSymbolImpl { block(it) } + typeAliasSymbolTable.forEachSymbolImpl { block(it) } + fieldSymbolTable.forEachSymbolImpl { block(it) } } } diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt index 6da9c441a39..f20922d2b2e 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.isPublicApi import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.library.IrLibrary @@ -144,7 +145,8 @@ class CurrentModuleWithICDeserializer( override fun init(delegate: IrModuleDeserializer) { val knownBuiltIns = irBuiltIns.knownBuiltins.map { (it as IrSymbolOwner).symbol }.toSet() - symbolTable.forEachPublicSymbol { + symbolTable.forEachDeclarationSymbol { + assert(it.isPublicApi) if (it.descriptor.isDirtyDescriptor()) { // public && non-deserialized should be dirty symbol if (it !in knownBuiltIns) { dirtyDeclarations[it.signature!!] = it diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt index a0223ba0ce0..4ed4f031561 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Fir2Ir.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.isEmpty import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.fir.backend.* @@ -25,10 +25,14 @@ import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories +import org.jetbrains.kotlin.library.metadata.impl.ForwardDeclarationKind import org.jetbrains.kotlin.storage.LockBasedStorageManager internal val KlibFactories = KlibMetadataFactories(::KonanBuiltIns, DynamicTypeDeserializer, PlatformDependentTypeTransformer.None) @@ -39,7 +43,6 @@ internal fun PhaseContext.fir2Ir( val fir2IrExtensions = Fir2IrExtensions.Default var builtInsModule: KotlinBuiltIns? = null - val dependencies = mutableListOf() val resolvedLibraries = config.resolvedLibraries.getFullResolvedList() val configuration = config.configuration @@ -54,7 +57,6 @@ internal fun PhaseContext.fir2Ir( packageAccessHandler = null, lookupTracker = LookupTracker.DO_NOTHING ) - dependencies += moduleDescriptor val isBuiltIns = moduleDescriptor.isNativeStdlib() if (isBuiltIns) builtInsModule = moduleDescriptor.builtIns @@ -64,7 +66,7 @@ internal fun PhaseContext.fir2Ir( librariesDescriptors.forEach { moduleDescriptor -> // Yes, just to all of them. - moduleDescriptor.setDependencies(ArrayList(dependencies)) + moduleDescriptor.setDependencies(ArrayList(librariesDescriptors)) } val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() @@ -92,6 +94,23 @@ internal fun PhaseContext.fir2Ir( "`${irModuleFragment.name}` must be Name.special, since it's required by KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns()" } + val usedPackages = buildSet { + components.symbolTable.forEachDeclarationSymbol { + val p = it.owner as? IrDeclaration ?: return@forEachDeclarationSymbol + val fragment = (p.getPackageFragment() as? IrExternalPackageFragment) ?: return@forEachDeclarationSymbol + add(fragment.fqName) + } + // This packages exists in all platform libraries, but can contain only synthetic declarations. + // These declarations are not really located in klib, so we don't need to depend on klib to use them. + removeAll(ForwardDeclarationKind.values().map { it.packageFqName }) + }.toList() + + + val usedLibraries = librariesDescriptors.zip(resolvedLibraries).filter { (module, _) -> + usedPackages.any { !module.packageFragmentProviderForModuleContentWithoutDependencies.isEmpty(it) } + }.map { it.second }.toSet() + + val symbols = createKonanSymbols(irModuleFragment, components, pluginContext) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) @@ -101,7 +120,7 @@ internal fun PhaseContext.fir2Ir( throw KonanCompilationException("Compilation failed: there were some diagnostics during fir2ir") } - return Fir2IrOutput(input.firResult, symbols, irModuleFragment, components, pluginContext, irActualizationResult) + return Fir2IrOutput(input.firResult, symbols, irModuleFragment, components, pluginContext, irActualizationResult, usedLibraries) } private fun PhaseContext.createKonanSymbols( diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirNativeSerializer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirNativeSerializer.kt index 7d15a2bf585..d9b8bac6c47 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirNativeSerializer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirNativeSerializer.kt @@ -45,13 +45,16 @@ internal fun PhaseContext.firSerializer( configuration.get(CommonConfigurationKeys.METADATA_VERSION) ?: configuration.languageVersionSettings.languageVersion.toMetadataVersion() - val resolvedLibraries = config.resolvedLibraries.getFullResolvedList(TopologicalLibraryOrder) // FIXME KT-55603 + val resolvedLibraries = config.resolvedLibraries.getFullResolvedList(TopologicalLibraryOrder) + val usedResolvedLibraries = resolvedLibraries.filter { + (!it.isDefault && !configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)) || it in input.usedLibraries + } val actualizedFirDeclarations = input.irActualizationResult.extractFirDeclarations() return serializeNativeModule( configuration = configuration, messageLogger = configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, sourceFiles, - resolvedLibraries.map { it.library as KonanLibrary }, + usedResolvedLibraries.map { it.library as KonanLibrary }, input.irModuleFragment, expectDescriptorToSymbol = mutableMapOf() // TODO: expect -> actual mapping ) { file -> diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Fir2Ir.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Fir2Ir.kt index b2d12fb744d..d2b650824a3 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Fir2Ir.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Fir2Ir.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrPluginContext import org.jetbrains.kotlin.fir.pipeline.FirResult import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary internal data class Fir2IrOutput( val firResult: FirResult, @@ -21,7 +22,8 @@ internal data class Fir2IrOutput( val irModuleFragment: IrModuleFragment, val components: Fir2IrComponents, val pluginContext: Fir2IrPluginContext, - val irActualizationResult: IrActualizationResult? + val irActualizationResult: IrActualizationResult?, + val usedLibraries: Set ) internal val Fir2IrPhase = createSimpleNamedCompilerPhase(