rra/ilgonmic/ic-to-compiler
[JS IR] Fix compilation in tests [JS IR] Fix test after migrating IC to compiler [JS IR] Fix memory leak [JS IR] Move js ic to compiler Merge-request: KT-MR-5673 Merged-by: Ilya Goncharov <Ilya.Goncharov@jetbrains.com>
This commit is contained in:
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.incremental.js.IncrementalNextRoundChecker
|
||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
||||
import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCacheForModule
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCaches
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.buildCacheForModuleFiles
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.loadModuleCaches
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
@@ -196,9 +196,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
// TODO: Handle non-empty main call arguments
|
||||
val mainCallArguments = if (K2JsArgumentConstants.NO_CALL == arguments.main) null else emptyList<String>()
|
||||
|
||||
val icCaches = configureLibraries(arguments.cacheDirectories)
|
||||
val cacheDirectories = configureLibraries(arguments.cacheDirectories)
|
||||
|
||||
if (arguments.irBuildCache) {
|
||||
val icCaches = if (cacheDirectories.isNotEmpty()) {
|
||||
messageCollector.report(INFO, "")
|
||||
messageCollector.report(INFO, "Building cache:")
|
||||
messageCollector.report(INFO, "to: ${outputFilePath}")
|
||||
@@ -209,24 +209,22 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
|
||||
val start = System.currentTimeMillis()
|
||||
|
||||
val updateStatus = actualizeCacheForModule(
|
||||
actualizeCaches(
|
||||
includes,
|
||||
outputFilePath,
|
||||
configurationJs,
|
||||
libraries,
|
||||
icCaches,
|
||||
IrFactoryImplForJsIC(WholeWorldStageController()),
|
||||
cacheDirectories,
|
||||
{ IrFactoryImplForJsIC(WholeWorldStageController()) },
|
||||
mainCallArguments,
|
||||
::buildCacheForModuleFiles
|
||||
)
|
||||
|
||||
if (updateStatus.upToDate) {
|
||||
messageCollector.report(INFO, "IC per-file cache up-to-date check duration: ${System.currentTimeMillis() - start}ms")
|
||||
} else {
|
||||
messageCollector.report(INFO, "IC per-file cache building duration: ${System.currentTimeMillis() - start}ms")
|
||||
::buildCacheForModuleFiles,
|
||||
) { updateStatus ->
|
||||
if (updateStatus.upToDate) {
|
||||
messageCollector.report(INFO, "IC per-file cache up-to-date check duration: ${System.currentTimeMillis() - start}ms")
|
||||
} else {
|
||||
messageCollector.report(INFO, "IC per-file cache building duration: ${System.currentTimeMillis() - start}ms")
|
||||
}
|
||||
}
|
||||
return OK
|
||||
}
|
||||
} else emptyList()
|
||||
|
||||
// Run analysis if main module is sources
|
||||
lateinit var sourceModule: ModulesStructure
|
||||
|
||||
@@ -31,5 +31,15 @@ data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong,
|
||||
val configHashULong = configHash.toULongOrNull(16) ?: 0UL
|
||||
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16), configHashULong)
|
||||
}
|
||||
|
||||
fun loadOrCreate(
|
||||
path: String,
|
||||
moduleName: String,
|
||||
flatHash: ULong = 0UL,
|
||||
transHash: ULong = 0UL,
|
||||
configHash: ULong = 0UL
|
||||
): CacheInfo {
|
||||
return load(path) ?: CacheInfo(path, moduleName, flatHash, transHash, configHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,9 @@ import java.security.MessageDigest
|
||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
||||
|
||||
private fun KotlinLibrary.fingerprint(fileIndex: Int): Hash {
|
||||
return ((((types(fileIndex).md5() * 31) + signatures(fileIndex).md5()) * 31 + strings(fileIndex).md5()) * 31 + declarations(fileIndex).md5()) * 31 + bodies(fileIndex).md5()
|
||||
return ((((types(fileIndex).md5() * 31) + signatures(fileIndex).md5()) * 31 + strings(fileIndex).md5()) * 31 + declarations(fileIndex).md5()) * 31 + bodies(
|
||||
fileIndex
|
||||
).md5()
|
||||
}
|
||||
|
||||
private fun invalidateCacheForModule(
|
||||
@@ -295,7 +297,7 @@ private fun createCacheConsumer(path: String): PersistentCacheConsumer {
|
||||
return PersistentCacheConsumerImpl(path)
|
||||
}
|
||||
|
||||
private fun loadCacheInfo(cachePaths: Collection<String>): MutableMap<ModulePath, CacheInfo> {
|
||||
fun loadCacheInfo(cachePaths: Collection<String>): MutableMap<ModulePath, CacheInfo> {
|
||||
val caches = cachePaths.map { CacheInfo.load(it) ?: error("Cannot load IC cache from $it") }
|
||||
val result = mutableMapOf<ModulePath, CacheInfo>()
|
||||
return caches.associateByTo(result) { it.libPath.toCanonicalPath() }
|
||||
@@ -311,7 +313,7 @@ private fun loadLibraries(configuration: CompilerConfiguration, dependencies: Co
|
||||
return allResolvedDependencies.getFullList().associateBy { it.libraryFile.path.toCanonicalPath() }
|
||||
}
|
||||
|
||||
private fun String.toCanonicalPath(): String = File(this).canonicalPath
|
||||
fun String.toCanonicalPath(): String = File(this).canonicalPath
|
||||
|
||||
typealias ModuleName = String
|
||||
typealias ModulePath = String
|
||||
@@ -408,35 +410,101 @@ enum class CacheUpdateStatus(val upToDate: Boolean) {
|
||||
|
||||
}
|
||||
|
||||
fun actualizeCaches(
|
||||
includes: String,
|
||||
compilerConfiguration: CompilerConfiguration,
|
||||
dependencies: Collection<ModulePath>,
|
||||
icCachePaths: Collection<String>,
|
||||
irFactory: () -> IrFactory,
|
||||
mainArguments: List<String>?,
|
||||
executor: CacheExecutor,
|
||||
callback: (CacheUpdateStatus) -> Unit
|
||||
): List<String> {
|
||||
val (libraries, dependencyGraph, configMD5) = CacheConfiguration(dependencies, compilerConfiguration)
|
||||
val cacheMap = libraries.values.zip(icCachePaths).toMap()
|
||||
|
||||
val icCacheMap: MutableMap<ModulePath, CacheInfo> = mutableMapOf<ModulePath, CacheInfo>()
|
||||
val resultCaches = mutableListOf<String>()
|
||||
|
||||
val visitedLibraries = mutableSetOf<KotlinLibrary>()
|
||||
fun visitDependency(library: KotlinLibrary) {
|
||||
if (library in visitedLibraries) return
|
||||
visitedLibraries.add(library)
|
||||
|
||||
val libraryDeps = dependencyGraph[library] ?: error("Unknown library ${library.libraryName}")
|
||||
libraryDeps.forEach { visitDependency(it) }
|
||||
|
||||
val cachePath = cacheMap[library] ?: error("Unknown cache for library ${library.libraryName}")
|
||||
resultCaches.add(cachePath)
|
||||
|
||||
val moduleName = library.libraryFile.path.toCanonicalPath()
|
||||
val cacheInfo = CacheInfo.loadOrCreate(cachePath, moduleName, configHash = configMD5)
|
||||
icCacheMap[moduleName] = cacheInfo
|
||||
|
||||
val updateStatus = actualizeCacheForModule(
|
||||
moduleName = moduleName,
|
||||
cachePath = cachePath,
|
||||
compilerConfiguration = compilerConfiguration,
|
||||
configMD5 = configMD5,
|
||||
libraries = libraries,
|
||||
dependencyGraph = dependencyGraph,
|
||||
icCacheMap = icCacheMap,
|
||||
irFactory = irFactory(),
|
||||
mainArguments = mainArguments,
|
||||
executor = executor
|
||||
)
|
||||
callback(updateStatus)
|
||||
}
|
||||
|
||||
val canonicalIncludes = includes.toCanonicalPath()
|
||||
val mainLibrary = libraries[canonicalIncludes] ?: error("Main library not found in libraries: $canonicalIncludes")
|
||||
visitDependency(mainLibrary)
|
||||
return resultCaches
|
||||
}
|
||||
|
||||
class CacheConfiguration(
|
||||
private val dependencies: Collection<ModulePath>,
|
||||
val compilerConfiguration: CompilerConfiguration
|
||||
) {
|
||||
val libraries: Map<ModulePath, KotlinLibrary> = loadLibraries(compilerConfiguration, dependencies)
|
||||
|
||||
val dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>
|
||||
get() {
|
||||
val nameToKotlinLibrary: Map<ModuleName, KotlinLibrary> = libraries.values.associateBy { it.moduleName }
|
||||
|
||||
return libraries.values.associateWith {
|
||||
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
||||
nameToKotlinLibrary[depName] ?: error("No Library found for $depName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val configMD5
|
||||
get() = compilerConfiguration.calcMD5()
|
||||
|
||||
operator fun component1() = libraries
|
||||
operator fun component2() = dependencyGraph
|
||||
operator fun component3() = configMD5
|
||||
}
|
||||
|
||||
// Returns true if caches up-to-date
|
||||
fun actualizeCacheForModule(
|
||||
moduleName: String,
|
||||
cachePath: String,
|
||||
compilerConfiguration: CompilerConfiguration,
|
||||
dependencies: Collection<ModulePath>,
|
||||
icCachePaths: Collection<String>,
|
||||
configMD5: ULong,
|
||||
libraries: Map<ModulePath, KotlinLibrary>,
|
||||
dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
||||
icCacheMap: Map<ModulePath, CacheInfo>,
|
||||
irFactory: IrFactory,
|
||||
mainArguments: List<String>?,
|
||||
executor: CacheExecutor
|
||||
): CacheUpdateStatus {
|
||||
val configMD5 = compilerConfiguration.calcMD5()
|
||||
val modulePath = moduleName.toCanonicalPath()
|
||||
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL, configMD5)
|
||||
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths).also {
|
||||
it[modulePath] = cacheInfo
|
||||
}
|
||||
|
||||
val libraries: Map<ModulePath, KotlinLibrary> = loadLibraries(compilerConfiguration, dependencies)
|
||||
val nameToKotlinLibrary: Map<ModuleName, KotlinLibrary> = libraries.values.associateBy { it.moduleName }
|
||||
val dependencyGraph = libraries.values.associateWith {
|
||||
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
||||
nameToKotlinLibrary[depName] ?: error("No Library found for $depName")
|
||||
}
|
||||
}
|
||||
val cacheInfo = icCacheMap[moduleName] ?: error("Cache for $moduleName not found")
|
||||
|
||||
val configUpdated = configMD5 != cacheInfo.configHash
|
||||
cacheInfo.configHash = configMD5
|
||||
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath) && !configUpdated) {
|
||||
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, moduleName) && !configUpdated) {
|
||||
return CacheUpdateStatus.FAST_PATH // up-to-date
|
||||
}
|
||||
|
||||
@@ -444,7 +512,7 @@ fun actualizeCacheForModule(
|
||||
libraries[lib.toCanonicalPath()]!! to createCacheProvider(cache.path)
|
||||
}.toMap()
|
||||
|
||||
val currentModule = libraries[moduleName.toCanonicalPath()] ?: error("No loaded library found for path $moduleName")
|
||||
val currentModule = libraries[moduleName] ?: error("No loaded library found for path $moduleName")
|
||||
val persistentCacheConsumer = createCacheConsumer(cachePath)
|
||||
|
||||
return actualizeCacheForModule(
|
||||
|
||||
Reference in New Issue
Block a user