Rewritten unneeded library purge machinery.

This commit is contained in:
Alexander Gorshenev
2017-10-17 17:12:56 +03:00
committed by alexander-gorshenev
parent 6382215b9d
commit bddada22e5
7 changed files with 56 additions and 46 deletions
@@ -49,7 +49,7 @@ internal fun produceOutput(context: Context) {
val output = context.config.outputName
val libraryName = context.config.moduleId
val neededLibraries
= context.config.immediateLibraries.purgeUnneeded()
= context.config.librariesWithDependencies
val abiVersion = context.config.currentAbiVersion
val target = context.config.targetManager.target
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
@@ -80,8 +80,4 @@ internal fun produceOutput(context: Context) {
}
}
internal fun List<KonanLibraryReader>.purgeUnneeded(): List<KonanLibraryReader> {
return this.map {
if (!it.isNeededForLink && it.isDefaultLink) null else it
}.filterNotNull()
}
@@ -1297,7 +1297,7 @@ internal object EscapeAnalysis {
val isStdlib = context.config.configuration[KonanConfigKeys.NOSTDLIB] == true
val externalFunctionEAResults = mutableMapOf<String, FunctionEscapeAnalysisResult>()
context.config.libraries.forEach { library ->
context.config.librariesWithDependencies.forEach { library ->
val libraryEscapeAnalysis = library.escapeAnalysis
if (libraryEscapeAnalysis != null) {
DEBUG_OUTPUT(0) {
@@ -1338,4 +1338,4 @@ internal object EscapeAnalysis {
}
}
}
}
}
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.backend.konan
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.konan.descriptors.createForwardDeclarationsModule
import org.jetbrains.kotlin.backend.konan.library.*
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
import org.jetbrains.kotlin.backend.konan.library.impl.*
import org.jetbrains.kotlin.backend.konan.util.profile
import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent
import org.jetbrains.kotlin.backend.konan.util.suffixIfNot
@@ -92,8 +92,13 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
}
}
val libraries: List<LibraryReaderImpl> by lazy {
// Accessing this field before resolve is a bad idea.
// purgeUnneeded() only works correctly after we have
// completed resolve and successfully marked package files
// as needed or not needed.
val librariesWithDependencies: List<KonanLibraryReader> by lazy {
resolver.resolveLibrariesRecursive(immediateLibraries, targetManager.target, currentAbiVersion)
immediateLibraries.purgeUnneeded().withResolvedDependencies()
}
private val loadedDescriptors = loadLibMetadata()
@@ -109,6 +114,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
val allMetadata = mutableListOf<ModuleDescriptorImpl>()
val specifics = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!
val libraries = immediateLibraries.withResolvedDependencies()
for (klib in libraries) {
profile("Loading ${klib.libraryName}") {
// MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor.
@@ -235,7 +235,7 @@ internal class LinkStage(val context: Context) {
private val debug = config.get(KonanConfigKeys.DEBUG) ?: false
private val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
private val emitted = context.bitcodeFileName
private val libraries = context.config.libraries.purgeUnneeded()
private val libraries = context.config.librariesWithDependencies
private fun MutableList<String>.addNonEmpty(elements: List<String>) {
addAll(elements.filter { !it.isEmpty() })
}
@@ -26,10 +26,9 @@ interface KonanLibraryReader {
val bitcodePaths: List<String>
val includedPaths: List<String>
val linkerOpts: List<String>
val dependencies: List<String>
val unresolvedDependencies: List<String>
val escapeAnalysis: ByteArray?
val isNeededForLink: Boolean get() = true
val isDefaultLink: Boolean get() = false
val manifestProperties: Properties
val moduleHeaderData: ByteArray
fun packageMetadata(fqName: String): ByteArray
@@ -49,7 +49,7 @@ fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List<String>,
removeDuplicates: Boolean = true): List<LibraryReaderImpl> {
val defaultLibraries = defaultLinks(nostdlib = noStdLib, noDefaultLibs = noDefaultLibs).map {
LibraryReaderImpl(it, abiVersion, target, isDefaultLink = true)
LibraryReaderImpl(it, abiVersion, target)
}
val userProvidedLibraries = libraryNames
@@ -65,33 +65,40 @@ fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List<String>,
fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<LibraryReaderImpl>,
target: KonanTarget,
abiVersion: Int): List<LibraryReaderImpl> {
val result = mutableMapOf<File, LibraryReaderImpl>()
result.putAll(immediateLibraries.map { it.libraryFile.absoluteFile to it })
var newDependencies: Map<File, LibraryReaderImpl> = result
abiVersion: Int) {
val cache = mutableMapOf<File, LibraryReaderImpl>()
cache.putAll(immediateLibraries.map { it.libraryFile.absoluteFile to it })
var newDependencies = cache.values.toList()
do {
val defaultOverrides = mutableSetOf<File>()
newDependencies = newDependencies.values.asSequence()
.flatMap { it.dependencies.asSequence() }
.map { resolve(it).absoluteFile }
.onEach {
if (result[it]?.isDefaultLink == true) {
defaultOverrides.add(it)
}
}
.filter { it !in result }
.map { it to LibraryReaderImpl(it, abiVersion, target) }.toMap()
result.putAll(newDependencies)
// If there is a default link in immediateLibraries,
// and we get the same library as a dependency,
// the resultant surviving library should not be a defaultLink anymore.
defaultOverrides.forEach {
result[it] = LibraryReaderImpl(it, abiVersion, target)
}
newDependencies = newDependencies.map { library: LibraryReaderImpl ->
library.unresolvedDependencies
.map { resolve(it).absoluteFile }
.map {
if (it in cache) {
library.resolvedDependencies.add(cache[it]!!)
null
} else {
val reader = LibraryReaderImpl(it, abiVersion, target)
cache.put(it,reader)
library.resolvedDependencies.add(reader)
reader
}
}.filterNotNull()
} .flatten()
} while (newDependencies.isNotEmpty())
return result.values.toList()
}
fun List<LibraryReaderImpl>.withResolvedDependencies(): List<LibraryReaderImpl> {
val result = mutableSetOf<LibraryReaderImpl>()
result.addAll(this)
var newDependencies = result.toList()
do {
newDependencies = newDependencies
.map { it -> it.resolvedDependencies } .flatten()
.filter { it !in result }
result.addAll(newDependencies)
} while (newDependencies.isNotEmpty())
return result.toList()
}
fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List<String>,
@@ -99,17 +106,16 @@ fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List<String>,
abiVersion: Int = 1,
noStdLib: Boolean = false,
noDefaultLibs: Boolean = false): List<LibraryReaderImpl> {
return resolveLibrariesRecursive(
resolveImmediateLibraries(
val immediateLibraries = resolveImmediateLibraries(
libraryNames = libraryNames,
target = target,
abiVersion = abiVersion,
noStdLib = noStdLib,
noDefaultLibs = noDefaultLibs,
removeDuplicates = true
),
target, abiVersion
)
)
resolveLibrariesRecursive(immediateLibraries, target, abiVersion)
return immediateLibraries.withResolvedDependencies()
}
class KonanLibrarySearchPathResolver(
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.konan.target.KonanTarget
class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
val target: KonanTarget? = null, override val isDefaultLink: Boolean = false)
val target: KonanTarget? = null)
: KonanLibraryReader {
// For the zipped libraries inPlace gives files from zip file system
@@ -68,9 +68,11 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
override val linkerOpts: List<String>
get() = manifestProperties.propertyList("linkerOpts", target!!.detailedName)
override val dependencies: List<String>
override val unresolvedDependencies: List<String>
get() = manifestProperties.propertyList("dependencies")
val resolvedDependencies = mutableListOf<LibraryReaderImpl>()
override val moduleHeaderData: ByteArray by lazy {
reader.loadSerializedModule()
}
@@ -96,3 +98,4 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
}
internal fun <T: KonanLibraryReader> List<T>.purgeUnneeded(): List<T> = this.filter{ it.isNeededForLink }