[JS IR IC] Implement fast path invalidation check
Compute library md5 hash and check it first with cached one. If hashes are equal it means that cache is up-to-date and no additional checks are needed - store library hashes (flat + trans) into cache info file - change invalidator return value
This commit is contained in:
@@ -208,7 +208,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
|
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
|
|
||||||
val updated = actualizeCacheForModule(
|
val updateStatus = actualizeCacheForModule(
|
||||||
includes,
|
includes,
|
||||||
outputFilePath,
|
outputFilePath,
|
||||||
configurationJs,
|
configurationJs,
|
||||||
@@ -218,13 +218,10 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
::buildCacheForModuleFiles
|
::buildCacheForModuleFiles
|
||||||
)
|
)
|
||||||
|
|
||||||
if (updated) {
|
if (updateStatus.upToDate) {
|
||||||
messageCollector.report(INFO, "IC per-file cache building duration: ${System.currentTimeMillis() - start}ms")
|
messageCollector.report(INFO, "IC per-file cache up-to-date check duration: ${System.currentTimeMillis() - start}ms")
|
||||||
} else {
|
} else {
|
||||||
messageCollector.report(
|
messageCollector.report(INFO, "IC per-file cache building duration: ${System.currentTimeMillis() - start}ms")
|
||||||
INFO,
|
|
||||||
"IC per-file cache up-to-date check duration: ${System.currentTimeMillis() - start}ms"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return OK
|
return OK
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ fun buildCache(
|
|||||||
|
|
||||||
if (!forceClean) {
|
if (!forceClean) {
|
||||||
val oldCacheInfo = CacheInfo.load(cachePath)
|
val oldCacheInfo = CacheInfo.load(cachePath)
|
||||||
if (oldCacheInfo != null && md5 == oldCacheInfo.md5) return false
|
if (oldCacheInfo != null && md5 == oldCacheInfo.flatHash) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val icDir = File(cachePath)
|
val icDir = File(cachePath)
|
||||||
@@ -57,7 +57,7 @@ fun buildCache(
|
|||||||
|
|
||||||
icData.serializedIcData.writeTo(File(cachePath))
|
icData.serializedIcData.writeTo(File(cachePath))
|
||||||
|
|
||||||
CacheInfo(cachePath, mainModule.libPath, md5).save()
|
CacheInfo(cachePath, mainModule.libPath, md5, 0UL).save()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -117,18 +117,19 @@ fun checkCaches(
|
|||||||
if (c.libPath !in allLibs) error("Missing library: ${c.libPath}")
|
if (c.libPath !in allLibs) error("Missing library: ${c.libPath}")
|
||||||
|
|
||||||
result[c.libPath] = File(c.path).readIcData()
|
result[c.libPath] = File(c.path).readIcData()
|
||||||
md5[c.libPath] = c.md5
|
md5[c.libPath] = c.flatHash
|
||||||
}
|
}
|
||||||
|
|
||||||
return IcCacheInfo(result, md5)
|
return IcCacheInfo(result, md5)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO md5 hash
|
// TODO md5 hash
|
||||||
data class CacheInfo(val path: String, val libPath: String, val md5: ULong) {
|
data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong, var transHash: ULong) {
|
||||||
fun save() {
|
fun save() {
|
||||||
PrintWriter(File(File(path), "info")).use {
|
PrintWriter(File(File(path), "info")).use {
|
||||||
it.println(libPath)
|
it.println(libPath)
|
||||||
it.println(md5.toString(16))
|
it.println(flatHash.toString(16))
|
||||||
|
it.println(transHash.toString(16))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +139,9 @@ data class CacheInfo(val path: String, val libPath: String, val md5: ULong) {
|
|||||||
|
|
||||||
if (!info.exists()) return null
|
if (!info.exists()) return null
|
||||||
|
|
||||||
val (libPath, md5) = info.readLines()
|
val (libPath, flatHash, transHash) = info.readLines()
|
||||||
|
|
||||||
return CacheInfo(path, libPath, md5.toULong(16))
|
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
|||||||
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
|
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.security.MessageDigest
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
||||||
|
|
||||||
private fun KotlinLibrary.fingerprint(fileIndex: Int): Hash {
|
private fun KotlinLibrary.fingerprint(fileIndex: Int): Hash {
|
||||||
@@ -142,7 +143,7 @@ private fun KotlinLibrary.filesAndSigReaders(): List<Pair<String, IdSignatureDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCacheForModule(
|
private fun buildCacheForModule(
|
||||||
libraryPath: String,
|
libraryInfo: CacheInfo,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
irModule: IrModuleFragment,
|
irModule: IrModuleFragment,
|
||||||
deserializer: JsIrLinker,
|
deserializer: JsIrLinker,
|
||||||
@@ -195,7 +196,7 @@ private fun buildCacheForModule(
|
|||||||
|
|
||||||
cacheExecutor.execute(irModule, dependencies, deserializer, configuration, dirtyFiles, cacheConsumer, emptySet(), null) // TODO: main arguments?
|
cacheExecutor.execute(irModule, dependencies, deserializer, configuration, dirtyFiles, cacheConsumer, emptySet(), null) // TODO: main arguments?
|
||||||
|
|
||||||
cacheConsumer.commitLibraryPath(libraryPath)
|
cacheConsumer.commitLibraryPath(libraryInfo.libPath.toCanonicalPath(), libraryInfo.flatHash, libraryInfo.transHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadModules(
|
private fun loadModules(
|
||||||
@@ -268,10 +269,10 @@ private fun createCacheConsumer(path: String): PersistentCacheConsumer {
|
|||||||
return PersistentCacheConsumerImpl(path)
|
return PersistentCacheConsumerImpl(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadCacheInfo(cachePaths: Collection<String>): MutableMap<ModulePath, String> {
|
private fun loadCacheInfo(cachePaths: Collection<String>): MutableMap<ModulePath, CacheInfo> {
|
||||||
val caches = cachePaths.map { CacheInfo.load(it) ?: error("Cannot load IC cache from $it") }
|
val caches = cachePaths.map { CacheInfo.load(it) ?: error("Cannot load IC cache from $it") }
|
||||||
val result = mutableMapOf<ModulePath, String>()
|
val result = mutableMapOf<ModulePath, CacheInfo>()
|
||||||
return caches.associateTo(result) { it.libPath.toCanonicalPath() to it.path }
|
return caches.associateByTo(result) { it.libPath.toCanonicalPath() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLibraries(configuration: CompilerConfiguration, dependencies: Collection<String>): Map<ModulePath, KotlinLibrary> {
|
private fun loadLibraries(configuration: CompilerConfiguration, dependencies: Collection<String>): Map<ModulePath, KotlinLibrary> {
|
||||||
@@ -304,6 +305,76 @@ fun interface CacheExecutor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun File.md5(additional: Iterable<ULong> = emptyList()): ULong {
|
||||||
|
val md5 = MessageDigest.getInstance("MD5")
|
||||||
|
|
||||||
|
for (ul in additional) {
|
||||||
|
md5.update(ul.toLong().toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun File.process(prefix: String = "") {
|
||||||
|
if (isDirectory) {
|
||||||
|
this.listFiles()!!.sortedBy { it.name }.forEach {
|
||||||
|
md5.update((prefix + it.name).toByteArray())
|
||||||
|
it.process(prefix + it.name + "/")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
md5.update(readBytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.process()
|
||||||
|
|
||||||
|
val d = md5.digest()
|
||||||
|
|
||||||
|
return ((d[0].toULong() and 0xFFUL)
|
||||||
|
or ((d[1].toULong() and 0xFFUL) shl 8)
|
||||||
|
or ((d[2].toULong() and 0xFFUL) shl 16)
|
||||||
|
or ((d[3].toULong() and 0xFFUL) shl 24)
|
||||||
|
or ((d[4].toULong() and 0xFFUL) shl 32)
|
||||||
|
or ((d[5].toULong() and 0xFFUL) shl 40)
|
||||||
|
or ((d[6].toULong() and 0xFFUL) shl 48)
|
||||||
|
or ((d[7].toULong() and 0xFFUL) shl 56)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkLibrariesHash(
|
||||||
|
libraries: Map<ModulePath, KotlinLibrary>,
|
||||||
|
dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
||||||
|
icCacheMap: Map<ModulePath, CacheInfo>,
|
||||||
|
modulePath: ModulePath
|
||||||
|
): Boolean {
|
||||||
|
val currentLib = libraries[modulePath] ?: error("1")
|
||||||
|
val currentCache = icCacheMap[modulePath] ?: error("2")
|
||||||
|
|
||||||
|
val flatHash = File(modulePath).md5()
|
||||||
|
|
||||||
|
val dependencies = dependencyGraph[currentLib] ?: error("3")
|
||||||
|
|
||||||
|
var transHash = flatHash
|
||||||
|
|
||||||
|
for (dep in dependencies) {
|
||||||
|
val depCache = icCacheMap[dep.libraryFile.canonicalPath] ?: error("4")
|
||||||
|
transHash += depCache.transHash
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCache.transHash != transHash) {
|
||||||
|
currentCache.flatHash = flatHash
|
||||||
|
currentCache.transHash = transHash
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class CacheUpdateStatus(val upToDate: Boolean) {
|
||||||
|
DIRTY(upToDate = false),
|
||||||
|
NO_DIRTY_FILES(upToDate = true),
|
||||||
|
FAST_PATH(upToDate = true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if caches up-to-date
|
||||||
fun actualizeCacheForModule(
|
fun actualizeCacheForModule(
|
||||||
moduleName: String,
|
moduleName: String,
|
||||||
cachePath: String,
|
cachePath: String,
|
||||||
@@ -312,41 +383,46 @@ fun actualizeCacheForModule(
|
|||||||
icCachePaths: Collection<String>,
|
icCachePaths: Collection<String>,
|
||||||
irFactory: IrFactory,
|
irFactory: IrFactory,
|
||||||
executor: CacheExecutor
|
executor: CacheExecutor
|
||||||
): Boolean {
|
): CacheUpdateStatus {
|
||||||
val icCacheMap: Map<ModulePath, String> = loadCacheInfo(icCachePaths).also {
|
val modulePath = moduleName.toCanonicalPath()
|
||||||
it[moduleName.toCanonicalPath()] = cachePath
|
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL)
|
||||||
|
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths).also {
|
||||||
|
it[modulePath] = cacheInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
val libraries: Map<ModulePath, KotlinLibrary> = loadLibraries(compilerConfiguration, dependencies)
|
val libraries: Map<ModulePath, KotlinLibrary> = loadLibraries(compilerConfiguration, dependencies)
|
||||||
|
|
||||||
val persistentCacheProviders = icCacheMap.map { (lib, cache) ->
|
|
||||||
libraries[lib.toCanonicalPath()]!! to createCacheProvider(cache)
|
|
||||||
}.toMap()
|
|
||||||
|
|
||||||
val nameToKotlinLibrary: Map<ModuleName, KotlinLibrary> = libraries.values.associateBy { it.moduleName }
|
val nameToKotlinLibrary: Map<ModuleName, KotlinLibrary> = libraries.values.associateBy { it.moduleName }
|
||||||
|
|
||||||
val dependencyGraph = libraries.values.associateWith {
|
val dependencyGraph = libraries.values.associateWith {
|
||||||
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
||||||
nameToKotlinLibrary[depName] ?: error("No Library found for $depName")
|
nameToKotlinLibrary[depName] ?: error("No Library found for $depName")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath)) {
|
||||||
|
return CacheUpdateStatus.FAST_PATH // up-to-date
|
||||||
|
}
|
||||||
|
|
||||||
|
val persistentCacheProviders = icCacheMap.map { (lib, cache) ->
|
||||||
|
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.toCanonicalPath()] ?: error("No loaded library found for path $moduleName")
|
||||||
val persistentCacheConsumer = createCacheConsumer(cachePath)
|
val persistentCacheConsumer = createCacheConsumer(cachePath)
|
||||||
|
|
||||||
return actualizeCacheForModule(currentModule, compilerConfiguration, dependencyGraph, persistentCacheProviders, persistentCacheConsumer, irFactory, executor)
|
return actualizeCacheForModule(currentModule, cacheInfo, compilerConfiguration, dependencyGraph, persistentCacheProviders, persistentCacheConsumer, irFactory, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun actualizeCacheForModule(
|
private fun actualizeCacheForModule(
|
||||||
library: KotlinLibrary,
|
library: KotlinLibrary,
|
||||||
|
libraryInfo: CacheInfo,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
dependencyGraph: Map<KotlinLibrary, Collection<KotlinLibrary>>,
|
dependencyGraph: Map<KotlinLibrary, Collection<KotlinLibrary>>,
|
||||||
persistentCacheProviders: Map<KotlinLibrary, PersistentCacheProvider>,
|
persistentCacheProviders: Map<KotlinLibrary, PersistentCacheProvider>,
|
||||||
persistentCacheConsumer: PersistentCacheConsumer,
|
persistentCacheConsumer: PersistentCacheConsumer,
|
||||||
irFactory: IrFactory,
|
irFactory: IrFactory,
|
||||||
cacheExecutor: CacheExecutor
|
cacheExecutor: CacheExecutor
|
||||||
): Boolean {
|
): CacheUpdateStatus {
|
||||||
// 1. Invalidate
|
// 1. Invalidate
|
||||||
val dependencies = dependencyGraph[library]!!
|
val dependencies = dependencyGraph[library]!!
|
||||||
|
|
||||||
@@ -393,7 +469,7 @@ private fun actualizeCacheForModule(
|
|||||||
fileFingerPrints
|
fileFingerPrints
|
||||||
)
|
)
|
||||||
|
|
||||||
if (dirtySet.isEmpty()) return true // up-to-date
|
if (dirtySet.isEmpty()) return CacheUpdateStatus.NO_DIRTY_FILES // up-to-date
|
||||||
|
|
||||||
// 2. Build
|
// 2. Build
|
||||||
|
|
||||||
@@ -431,7 +507,7 @@ private fun actualizeCacheForModule(
|
|||||||
val deserializers = dirtySet.associateWith { currentModuleDeserializer.signatureDeserializerForFile(it).signatureToIndexMapping() }
|
val deserializers = dirtySet.associateWith { currentModuleDeserializer.signatureDeserializerForFile(it).signatureToIndexMapping() }
|
||||||
|
|
||||||
buildCacheForModule(
|
buildCacheForModule(
|
||||||
library.libraryFile.canonicalPath,
|
libraryInfo,
|
||||||
configuration,
|
configuration,
|
||||||
currentIrModule,
|
currentIrModule,
|
||||||
jsIrLinker,
|
jsIrLinker,
|
||||||
@@ -443,7 +519,7 @@ private fun actualizeCacheForModule(
|
|||||||
fileFingerPrints,
|
fileFingerPrints,
|
||||||
cacheExecutor
|
cacheExecutor
|
||||||
)
|
)
|
||||||
return false // invalidated and re-built
|
return CacheUpdateStatus.DIRTY // invalidated and re-built
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rebuildCacheForDirtyFiles(
|
fun rebuildCacheForDirtyFiles(
|
||||||
@@ -525,10 +601,10 @@ fun buildCacheForModuleFiles(
|
|||||||
|
|
||||||
|
|
||||||
fun loadModuleCaches(icCachePaths: Collection<String>): Map<String, ModuleCache> {
|
fun loadModuleCaches(icCachePaths: Collection<String>): Map<String, ModuleCache> {
|
||||||
val icCacheMap: Map<ModulePath, String> = loadCacheInfo(icCachePaths)
|
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths)
|
||||||
|
|
||||||
return icCacheMap.entries.associate { (lib, cache) ->
|
return icCacheMap.entries.associate { (lib, cache) ->
|
||||||
val provider = createCacheProvider(cache)
|
val provider = createCacheProvider(cache.path)
|
||||||
val files = provider.filePaths()
|
val files = provider.filePaths()
|
||||||
lib to ModuleCache(lib, files.associate { f ->
|
lib to ModuleCache(lib, files.associate { f ->
|
||||||
f to FileCache(f, provider.binaryAst(f), provider.dts(f), provider.sourceMap(f))
|
f to FileCache(f, provider.binaryAst(f), provider.dts(f), provider.sourceMap(f))
|
||||||
|
|||||||
+5
-4
@@ -203,7 +203,7 @@ interface PersistentCacheConsumer {
|
|||||||
fun commitSourceMap(path: String, mapData: ByteArray)
|
fun commitSourceMap(path: String, mapData: ByteArray)
|
||||||
fun invalidateForFile(path: String)
|
fun invalidateForFile(path: String)
|
||||||
|
|
||||||
fun commitLibraryPath(libraryPath: String)
|
fun commitLibraryPath(libraryPath: String, flatHash: ULong, transHash: ULong)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = object : PersistentCacheConsumer {
|
val EMPTY = object : PersistentCacheConsumer {
|
||||||
@@ -234,7 +234,7 @@ interface PersistentCacheConsumer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryPath(libraryPath: String) {
|
override fun commitLibraryPath(libraryPath: String, flatHash: ULong, transHash: ULong) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +333,7 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
|
|||||||
commitByteArrayToCacheFile(path, fileSourceMap, mapData)
|
commitByteArrayToCacheFile(path, fileSourceMap, mapData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryPath(libraryPath: String) {
|
override fun commitLibraryPath(libraryPath: String, flatHash: ULong, transHash: ULong) {
|
||||||
val infoFile = File(File(cachePath), "info")
|
val infoFile = File(File(cachePath), "info")
|
||||||
if (infoFile.exists()) {
|
if (infoFile.exists()) {
|
||||||
infoFile.delete()
|
infoFile.delete()
|
||||||
@@ -342,7 +342,8 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
|
|||||||
|
|
||||||
PrintWriter(infoFile).use {
|
PrintWriter(infoFile).use {
|
||||||
it.println(libraryPath)
|
it.println(libraryPath)
|
||||||
it.println("0")
|
it.println(flatHash.toString(16))
|
||||||
|
it.println(transHash.toString(16))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.*
|
|||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
import org.jetbrains.kotlin.ir.backend.js.generateKLib
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ic.CacheUpdateStatus
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.PersistentCacheConsumer
|
import org.jetbrains.kotlin.ir.backend.js.ic.PersistentCacheConsumer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCacheForModule
|
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCacheForModule
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||||
@@ -145,7 +146,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
|
|
||||||
val moduleCacheDir = resolveModuleCache(module, buildDir)
|
val moduleCacheDir = resolveModuleCache(module, buildDir)
|
||||||
|
|
||||||
buildCachesAndCheck(moduleStep.id, configuration, moduleSourceDir, outputKlibFile, moduleCacheDir, dependencies, icCaches, dirtyFiles)
|
buildCachesAndCheck(moduleStep, configuration, moduleSourceDir, outputKlibFile, moduleCacheDir, dependencies, icCaches, dirtyFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +157,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCachesAndCheck(
|
private fun buildCachesAndCheck(
|
||||||
stepId: Int,
|
moduleStep: ModuleInfo.ModuleStep,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
sourceDir: File,
|
sourceDir: File,
|
||||||
moduleKlibFile: File,
|
moduleKlibFile: File,
|
||||||
@@ -176,17 +177,20 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
exportedDeclarations: Set<FqName>,
|
exportedDeclarations: Set<FqName>,
|
||||||
mainArguments: List<String>?,
|
mainArguments: List<String>?,
|
||||||
) {
|
) {
|
||||||
val actualDirtyFiles = invalidatedDirtyFiles?.map { File(it).canonicalPath } ?: sourceDir.filteredKtFiles().map { it.canonicalPath }
|
val actualDirtyFiles =
|
||||||
|
invalidatedDirtyFiles?.map { File(it).canonicalPath } ?: sourceDir.filteredKtFiles().map { it.canonicalPath }
|
||||||
val expectedDirtyFilesCanonical = expectedDirtyFiles.map { it.canonicalPath }
|
val expectedDirtyFilesCanonical = expectedDirtyFiles.map { it.canonicalPath }
|
||||||
|
|
||||||
JUnit4Assertions.assertSameElements(expectedDirtyFilesCanonical, actualDirtyFiles) { "For module $moduleKlibFile at step $stepId" }
|
JUnit4Assertions.assertSameElements(expectedDirtyFilesCanonical, actualDirtyFiles) {
|
||||||
|
"For module $moduleKlibFile at step ${moduleStep.id}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val dependenciesPaths = mutableListOf<String>()
|
val dependenciesPaths = mutableListOf<String>()
|
||||||
dependencies.mapTo(dependenciesPaths) { it.canonicalPath }
|
dependencies.mapTo(dependenciesPaths) { it.canonicalPath }
|
||||||
dependenciesPaths.add(moduleKlibFile.canonicalPath)
|
dependenciesPaths.add(moduleKlibFile.canonicalPath)
|
||||||
|
|
||||||
val upToDate = actualizeCacheForModule(
|
val updateStatus = actualizeCacheForModule(
|
||||||
moduleKlibFile.canonicalPath,
|
moduleKlibFile.canonicalPath,
|
||||||
moduleCacheDir.canonicalPath,
|
moduleCacheDir.canonicalPath,
|
||||||
configuration,
|
configuration,
|
||||||
@@ -196,9 +200,15 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
::dirtyFilesChecker
|
::dirtyFilesChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
JUnit4Assertions.assertEquals(expectedDirtyFiles.isEmpty(), upToDate) {
|
if (StepDirectives.FAST_PATH_UPDATE in moduleStep.directives) {
|
||||||
|
JUnit4Assertions.assertEquals(CacheUpdateStatus.FAST_PATH, updateStatus) {
|
||||||
|
"Cache has to be checked by fast path, instead it $updateStatus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JUnit4Assertions.assertEquals(expectedDirtyFiles.isEmpty(), updateStatus.upToDate) {
|
||||||
val filePaths = expectedDirtyFiles.joinToString(",", "[", "]")
|
val filePaths = expectedDirtyFiles.joinToString(",", "[", "]")
|
||||||
"Up to date is not expected for module $moduleKlibFile at step $stepId. Expected dirtyFiles are $filePaths"
|
"Up to date is not expected for module $moduleKlibFile at step ${moduleStep.id}. Expected dirtyFiles are $filePaths"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.WholeWorldStageController
|
import org.jetbrains.kotlin.ir.backend.js.WholeWorldStageController
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.moduleName
|
import org.jetbrains.kotlin.ir.backend.js.moduleName
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
import org.jetbrains.kotlin.js.test.handlers.JsBoxRunner
|
import org.jetbrains.kotlin.js.test.handlers.JsBoxRunner
|
||||||
@@ -115,7 +114,7 @@ class TestModuleCache(val moduleName: String, val files: MutableMap<String, File
|
|||||||
files.remove(path)
|
files.remove(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitLibraryPath(libraryPath: String) {
|
override fun commitLibraryPath(libraryPath: String, flatHash: ULong, transHash: ULong) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user