From ec71fe20e2371feabf93be3a2b9da55a5a77a9fe Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Tue, 24 Oct 2023 11:39:08 +0200 Subject: [PATCH] [JS IR] Fix file name clashes during JS BE invalidation --- .../kotlin/ir/backend/js/ic/CacheUpdater.kt | 41 +++++++++------- .../kotlin/ir/backend/js/ic/ICUtils.kt | 9 +++- .../js/ic/IdSignatureHashCalculator.kt | 2 +- .../ir/backend/js/ic/IdSignatureSource.kt | 17 ++++--- .../ir/backend/js/ic/IncrementalCache.kt | 2 +- .../ir/backend/js/ic/JsIrLinkerLoader.kt | 34 ++++++++++---- .../ir/backend/js/ic/KotlinLibraryHeader.kt | 5 +- .../backend/js/ic/KotlinSourceFileMetadata.kt | 47 +++++++++++++++---- .../js/lower/serialization/ir/JsIrLinker.kt | 16 ++++++- .../incremental/AbstractInvalidationTest.kt | 2 +- 10 files changed, 123 insertions(+), 52 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/CacheUpdater.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/CacheUpdater.kt index 21adb178211..7f78d1b5314 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/CacheUpdater.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/CacheUpdater.kt @@ -273,11 +273,11 @@ class CacheUpdater( symbolCanBeExported = true } if (symbolCanBeExported) { - idSignatureToFile[signature] = IdSignatureSource(libFile, fileSymbolProvider.irFile, symbol) + idSignatureToFile[signature] = IdSignatureSource(libFile, fileSymbolProvider, symbol) } } - val libSrcFile = KotlinSourceFile(fileSymbolProvider.irFile) + val libSrcFile = fileSymbolProvider.srcFile if (libSrcFile in dirtySrcFiles) { val metadata = incrementalCache.fetchSourceFileFullMetadata(libSrcFile) this[libFile, libSrcFile] = DirtyFileMetadata(maybeImportedSignatures, metadata.directDependencies) @@ -296,10 +296,10 @@ class CacheUpdater( for (importedSignature in allImportedSignatures) { val dependency = idSignatureToFile[importedSignature] ?: continue signatureHashCalculator[importedSignature]?.also { signatureHash -> - addDirectDependency(dependency.lib, dependency.src, importedSignature, signatureHash) - } ?: notFoundIcError("signature $importedSignature hash", dependency.lib, dependency.src) + addDirectDependency(dependency.lib, dependency.srcFile, importedSignature, signatureHash) + } ?: notFoundIcError("signature $importedSignature hash", dependency.lib, dependency.srcFile) - updatedMetadata[dependency.lib, dependency.src]?.also { dependencyMetadata -> + updatedMetadata[dependency.lib, dependency.srcFile]?.also { dependencyMetadata -> dependencyMetadata.addInverseDependency(libFile, srcFile, importedSignature) } } @@ -328,7 +328,7 @@ class CacheUpdater( signatures.forEach { signature -> val signatureSrc = idSignatureToFile[signature] val dependencyLib = signatureSrc?.lib ?: libFile - val dependencyFile = signatureSrc?.src ?: srcFile + val dependencyFile = signatureSrc?.srcFile ?: srcFile updatedMetadata[dependencyLib, dependencyFile]?.also { dependencyMetadata -> dependencyMetadata.addInverseDependency(dependentLibFile, dependentSrcFile, signature) } @@ -590,14 +590,16 @@ class CacheUpdater( val libFile = KotlinLibraryFile(library) val incrementalCache = getLibIncrementalCache(libFile) val providers = loadedIr.getSignatureProvidersForLib(libFile) - val signatureToIndexMapping = providers.associate { KotlinSourceFile(it.irFile) to it.getSignatureToIndexMapping() } + val signatureToIndexMapping = providers.associate { it.srcFile to it.getSignatureToIndexMapping() } val cacheArtifact = incrementalCache.buildAndCommitCacheArtifact(signatureToIndexMapping, stubbedSignatures) val libFragment = loadedIr.loadedFragments[libFile] ?: notFoundIcError("loaded fragment", libFile) + val sourceNames = loadedIr.getIrFileNames(libFragment) val sourceFilesFromCache = cacheArtifact.getSourceFiles() for (irFile in libFragment.files) { - if (KotlinSourceFile(irFile) !in sourceFilesFromCache) { + val srcName = sourceNames[irFile] ?: notFoundIcError("source file name", libFile, irFile) + if (srcName !in sourceFilesFromCache) { // IC doesn't support cases when extra IrFiles (which don't exist in klib) are added into IrModuleFragment icError("file ${irFile.fileEntry.name} is absent in incremental cache and klib", libFile) } @@ -623,16 +625,17 @@ class CacheUpdater( private fun compileDirtyFiles( compilerForIC: JsIrCompilerICInterface, - loadedFragments: Map, + loadedIr: LoadedJsIr, dirtyFiles: Map> ): MutableList JsIrProgramFragments>> = stopwatch.measure("Processing IR - lowering") { val dirtyFilesForCompiling = mutableListOf() val dirtyFilesForRestoring = mutableListOf>() - for ((libFile, libFragment) in loadedFragments) { + for ((libFile, libFragment) in loadedIr.loadedFragments) { val dirtySrcFiles = dirtyFiles[libFile] ?: continue + val sourceNames = loadedIr.getIrFileNames(libFragment) for (irFile in libFragment.files) { - val srcFile = KotlinSourceFile(irFile) + val srcFile = sourceNames[irFile] ?: notFoundIcError("source file name", libFile, irFile) if (srcFile in dirtySrcFiles) { dirtyFilesForCompiling += irFile dirtyFilesForRestoring += libFile to srcFile @@ -640,7 +643,7 @@ class CacheUpdater( } } - val fragmentGenerators = compilerForIC.compile(loadedFragments.values, dirtyFilesForCompiling) + val fragmentGenerators = compilerForIC.compile(loadedIr.loadedFragments.values, dirtyFilesForCompiling) dirtyFilesForRestoring.mapIndexedTo(ArrayList(dirtyFilesForRestoring.size)) { i, libFileAndSrcFile -> Triple(libFileAndSrcFile.first, libFileAndSrcFile.second, fragmentGenerators[i]) @@ -649,7 +652,7 @@ class CacheUpdater( private data class IrForDirtyFilesAndCompiler( val incrementalCacheArtifacts: Map, - val loadedFragments: Map, + val loadedIr: LoadedJsIr, val dirtyFiles: Map>, val irCompiler: JsIrCompilerICInterface ) @@ -726,7 +729,7 @@ class CacheUpdater( val incrementalCachesArtifacts = updater.buildAndCommitCacheArtifacts(loadedIr) stopwatch.stop() - return IrForDirtyFilesAndCompiler(incrementalCachesArtifacts, loadedIr.loadedFragments, dirtyFiles, compilerForIC) + return IrForDirtyFilesAndCompiler(incrementalCachesArtifacts, loadedIr, dirtyFiles, compilerForIC) } private data class FragmentGenerators( @@ -736,11 +739,11 @@ class CacheUpdater( ) private fun loadIrAndMakeIrFragmentGenerators(): FragmentGenerators { - val (incrementalCachesArtifacts, irFragments, dirtyFiles, irCompiler) = loadIrForDirtyFilesAndInitCompiler() + val (incrementalCachesArtifacts, loadedIr, dirtyFiles, irCompiler) = loadIrForDirtyFilesAndInitCompiler() - val moduleNames = irFragments.entries.associate { it.key to it.value.name.asString() } + val moduleNames = loadedIr.loadedFragments.entries.associate { it.key to it.value.name.asString() } - val rebuiltFragmentGenerators = compileDirtyFiles(irCompiler, irFragments, dirtyFiles) + val rebuiltFragmentGenerators = compileDirtyFiles(irCompiler, loadedIr, dirtyFiles) return FragmentGenerators(incrementalCachesArtifacts, moduleNames, rebuiltFragmentGenerators) } @@ -784,7 +787,9 @@ fun rebuildCacheForDirtyFiles( } val libFile = KotlinLibraryFile(library) - val dirtySrcFiles = dirtyFiles?.memoryOptimizedMap { KotlinSourceFile(it) } ?: KotlinLoadedLibraryHeader(library, internationService).sourceFileFingerprints.keys + val dirtySrcFiles = dirtyFiles?.let { + KotlinSourceFile.fromSources(it.toList()) + } ?: KotlinLoadedLibraryHeader(library, internationService).sourceFileFingerprints.keys val modifiedFiles = mapOf(libFile to dirtySrcFiles.associateWith { emptyMetadata }) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ICUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ICUtils.kt index 835a71a1ecf..cd6f318a511 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ICUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ICUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.ic +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.CodedOutputStream @@ -43,8 +44,8 @@ internal inline fun CodedInputStream.ifTrue(then: () -> T): T? { return if (readBool()) then() else null } -internal fun icError(what: String, libFile: KotlinLibraryFile? = null, srcFile: KotlinSourceFile? = null): Nothing { - val filePath = listOfNotNull(libFile?.path, srcFile?.path).joinToString(":") { File(it).name } +internal fun icError(what: String, libFile: KotlinLibraryFile? = null, srcFile: KotlinSourceFile? = null, irFile: IrFile? = null): Nothing { + val filePath = listOfNotNull(libFile?.path, (srcFile?.path ?: irFile?.fileEntry?.name)).joinToString(":") { File(it).name } val msg = if (filePath.isEmpty()) what else "$what for $filePath" error("IC internal error: $msg") } @@ -53,6 +54,10 @@ internal fun notFoundIcError(what: String, libFile: KotlinLibraryFile? = null, s icError("can not find $what", libFile, srcFile) } +internal fun notFoundIcError(what: String, libFile: KotlinLibraryFile, irFile: IrFile): Nothing { + icError("can not find $what", libFile, irFile = irFile) +} + internal inline fun buildSetUntil(to: Int, builderAction: MutableSet.(Int) -> Unit): Set { return newHashSetWithExpectedSize(to).apply { repeat(to) { builderAction(it) } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt index 979ddb1b7c3..3de73db62ea 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureHashCalculator.kt @@ -88,7 +88,7 @@ internal class IdSignatureHashCalculator(private val icHasher: ICHasher) { } private fun IrSymbol.calculateSymbolHash(): ICHash { - var srcIrFile = signature?.let { sig -> idSignatureSources[sig]?.srcIrFile } + var srcIrFile = signature?.let { sig -> idSignatureSources[sig]?.irFile } if (srcIrFile == null) { var parentDeclaration = (owner as? IrDeclaration)?.parent while (parentDeclaration is IrDeclaration) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureSource.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureSource.kt index 8da49483bc6..b104450db48 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureSource.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IdSignatureSource.kt @@ -14,11 +14,14 @@ import org.jetbrains.kotlin.ir.util.resolveFakeOverride internal class IdSignatureSource( val lib: KotlinLibraryFile, - val srcIrFile: IrFile, + private val fileSignatureProvider: FileSignatureProvider, val symbol: IrSymbol ) { - val src: KotlinSourceFile - get() = KotlinSourceFile(srcIrFile) + val irFile: IrFile + get() = fileSignatureProvider.irFile + + val srcFile: KotlinSourceFile + get() = fileSignatureProvider.srcFile } internal fun addParentSignatures( @@ -31,7 +34,7 @@ internal fun addParentSignatures( fun addAllParents(sig: IdSignature) { val signatureSrc = idSignatureToFile[sig] ?: return - if (signatureSrc.lib == importerLibFile && signatureSrc.src == importerSrcFile) { + if (signatureSrc.lib == importerLibFile && signatureSrc.srcFile == importerSrcFile) { return } if (allSignatures.add(sig)) { @@ -100,12 +103,12 @@ private fun collectImplementedSymbol(deserializedSymbols: Map abstract fun getReachableSignatures(): Set abstract fun getImplementedSymbols(): Map - class DeserializedFromKlib(private val fileDeserializer: IrFileDeserializer) : FileSignatureProvider(fileDeserializer.file) { + class DeserializedFromKlib(private val fileDeserializer: IrFileDeserializer, srcFile: KotlinSourceFile) : FileSignatureProvider(fileDeserializer.file, srcFile) { override fun getSignatureToIndexMapping(): Map { return fileDeserializer.symbolDeserializer.signatureDeserializer.signatureToIndexMapping() } @@ -127,7 +130,7 @@ internal sealed class FileSignatureProvider(val irFile: IrFile) { } } - class GeneratedFunctionTypeInterface(file: IrFile) : FileSignatureProvider(file) { + class GeneratedFunctionTypeInterface(file: IrFile, srcFile: KotlinSourceFile) : FileSignatureProvider(file, srcFile) { private val allSignatures = run { val topLevelSymbols = buildMap { for (declaration in irFile.declarations) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IncrementalCache.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IncrementalCache.kt index 3dae416bdd3..4fffee9dd30 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IncrementalCache.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/IncrementalCache.kt @@ -86,7 +86,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca private fun KotlinSourceFile.getCacheFile(suffix: String): File { val pathHash = path.cityHash64String() - return File(cacheDir, "${File(path).name}.$pathHash.$suffix") + return File(cacheDir, "${File(path).name}.$id.$pathHash.$suffix") } fun buildAndCommitCacheArtifact( diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt index 3a3893fc4e0..8c2c9cba273 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/JsIrLinkerLoader.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.backend.js.JsFactories import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc import org.jetbrains.kotlin.ir.declarations.IrFactory +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.descriptors.IrDescriptorBasedFunctionFactory import org.jetbrains.kotlin.ir.linkage.partial.partialLinkageConfig @@ -42,21 +43,25 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager internal data class LoadedJsIr( val loadedFragments: Map, private val linker: JsIrLinker, - private val functionTypeInterfacePackages: FunctionTypeInterfacePackages + private val functionTypeInterfacePackages: FunctionTypeInterfacePackages, ) { private val signatureProvidersImpl = hashMapOf>() - private fun collectSignatureProviders(irModule: IrModuleFragment): List { + private val irFileSourceNames = hashMapOf>() + + private fun collectSignatureProviders(lib: KotlinLibraryFile, irModule: IrModuleFragment): List { val moduleDeserializer = linker.moduleDeserializer(irModule.descriptor) val deserializers = moduleDeserializer.fileDeserializers() val providers = ArrayList(deserializers.size) + val sourceFiles = getIrFileNames(irModule) for (fileDeserializer in deserializers) { val irFile = fileDeserializer.file + val sourceFile = sourceFiles[irFile] ?: notFoundIcError("source file name", lib, irFile) if (functionTypeInterfacePackages.isFunctionTypeInterfacePackageFile(irFile)) { - providers += FileSignatureProvider.GeneratedFunctionTypeInterface(irFile) + providers += FileSignatureProvider.GeneratedFunctionTypeInterface(irFile, sourceFile) } else { - providers += FileSignatureProvider.DeserializedFromKlib(fileDeserializer) + providers += FileSignatureProvider.DeserializedFromKlib(fileDeserializer, sourceFile) } } @@ -66,7 +71,7 @@ internal data class LoadedJsIr( fun getSignatureProvidersForLib(lib: KotlinLibraryFile): List { return signatureProvidersImpl.getOrPut(lib) { val irFragment = loadedFragments[lib] ?: notFoundIcError("loaded fragment", lib) - collectSignatureProviders(irFragment) + collectSignatureProviders(lib, irFragment) } } @@ -81,6 +86,17 @@ internal data class LoadedJsIr( fun collectSymbolsReplacedWithStubs(): Set { return linker.partialLinkageSupport.collectAllStubbedSymbols() } + + fun getIrFileNames(fragment: IrModuleFragment): Map { + return irFileSourceNames.getOrPut(fragment) { + val files = linker.getDeserializedFilesInKlibOrder(fragment) + val names = files.map { it.fileEntry.name } + val sourceFiles = KotlinSourceFile.fromSources(names) + files.indices.associate { + files[it] to sourceFiles[it] + } + } + } } internal class JsIrLinkerLoader( @@ -88,7 +104,7 @@ internal class JsIrLinkerLoader( private val dependencyGraph: Map>, private val mainModuleFriends: Collection, private val irFactory: IrFactory, - private val stubbedSignatures: Set + private val stubbedSignatures: Set, ) { private val mainLibrary = dependencyGraph.keys.lastOrNull() ?: notFoundIcError("main library") @@ -97,7 +113,7 @@ internal class JsIrLinkerLoader( val symbolTable: SymbolTable, val typeTranslator: TypeTranslatorImpl, val irBuiltIns: IrBuiltInsOverDescriptors, - val linker: JsIrLinker + val linker: JsIrLinker, ) { val functionTypeInterfacePackages = FunctionTypeInterfacePackages() @@ -183,9 +199,9 @@ internal class JsIrLinkerLoader( module == mainLibrary -> DeserializationStrategy.ALL else -> DeserializationStrategy.EXPLICITLY_EXPORTED } - val modified = modifiedFiles[libraryFile] ?: emptyMap() + val modified = modifiedFiles[libraryFile]?.keys?.mapTo(hashSetOf()) { it.path } ?: emptySet() libraryFile to linkerContext.linker.deserializeIrModuleHeader(descriptor, module, { - when (KotlinSourceFile(it)) { + when (it) { in modified -> modifiedStrategy else -> DeserializationStrategy.WITH_INLINE_BODIES } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinLibraryHeader.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinLibraryHeader.kt index df62f475a58..107531a37db 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinLibraryHeader.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinLibraryHeader.kt @@ -66,10 +66,11 @@ internal class KotlinLoadedLibraryHeader( private val sourceFiles by lazy(LazyThreadSafetyMode.NONE) { val extReg = ExtensionRegistryLite.newInstance() - Array(library.fileCount()) { + val sources = (0 until library.fileCount()).map { val fileProto = IrFile.parseFrom(library.file(it).codedInputStream, extReg) - KotlinSourceFile(fileProto.fileEntry.name) + fileProto.fileEntry.name } + KotlinSourceFile.fromSources(sources) } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinSourceFileMetadata.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinSourceFileMetadata.kt index 85e6c7d36e0..261378a09c8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinSourceFileMetadata.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/KotlinSourceFileMetadata.kt @@ -26,18 +26,45 @@ value class KotlinLibraryFile(val path: String) { override fun toString(): String = File(path).name } -@JvmInline -value class KotlinSourceFile(val path: String) { - constructor(irFile: IrFile) : this(irFile.fileEntry.name) +class KotlinSourceFile private constructor(val path: String, val id: Int) { + fun toProtoStream(out: CodedOutputStream) { + out.writeStringNoTag(path) + out.writeInt32NoTag(id) + } - fun toProtoStream(out: CodedOutputStream) = out.writeStringNoTag(path) + override fun hashCode(): Int { + return path.hashCode() xor id + } - companion object { - fun fromProtoStream(input: CodedInputStream) = KotlinSourceFile(input.readString()) + override fun equals(other: Any?): Boolean { + return other is KotlinSourceFile && other.path == path && other.id == id } // for debugging purposes only - override fun toString(): String = File(path).name + override fun toString(): String = "${File(path).name}${if (id != 0) ".$id" else ""}" + + companion object { + fun fromProtoStream(input: CodedInputStream): KotlinSourceFile { + val path = input.readString() + val fileIndex = input.readInt32() + return KotlinSourceFile(path, fileIndex) + } + + /** + * Source file paths in one module may clash; + * for example, common and platform parts of the module could have files with the same root paths. + * @param sources is a list of the module sources and must be in the same order as they appear in the klib. + * @return a list of [KotlinSourceFile] containing the file path and the unique id in case of a clash + */ + fun fromSources(sources: List): List { + val counters = hashMapOf() + return sources.map { fileName -> + val id = counters[fileName] ?: 0 + counters[fileName] = id + 1 + KotlinSourceFile(fileName, id) + } + } + } } open class KotlinSourceFileMap(files: Map>) : @@ -54,7 +81,7 @@ open class KotlinSourceFileMap(files: Map( - private val files: MutableMap> = hashMapOf() + private val files: MutableMap> = hashMapOf(), ) : KotlinSourceFileMap(files) { operator fun set(libFile: KotlinLibraryFile, sourceFile: KotlinSourceFile, data: T) = getOrPutFiles(libFile).put(sourceFile, data) @@ -126,7 +153,7 @@ internal class DirtyFileExports : KotlinSourceFileExports() { internal class DirtyFileMetadata( val maybeImportedSignatures: Collection, - val oldDirectDependencies: KotlinSourceFileMap<*> + val oldDirectDependencies: KotlinSourceFileMap<*>, ) : KotlinSourceFileMetadata() { override val inverseDependencies: KotlinSourceFileMutableMap> = KotlinSourceFileMutableMap() override val directDependencies: KotlinSourceFileMutableMap> = KotlinSourceFileMutableMap() @@ -161,7 +188,7 @@ internal class UpdatedDependenciesMetadata(oldMetadata: KotlinSourceFileMetadata } internal fun KotlinSourceFileMutableMap.addNewMetadata( - libFile: KotlinLibraryFile, srcFile: KotlinSourceFile, oldMetadata: KotlinSourceFileMetadata + libFile: KotlinLibraryFile, srcFile: KotlinSourceFile, oldMetadata: KotlinSourceFileMetadata, ) = this[libFile, srcFile] ?: UpdatedDependenciesMetadata(oldMetadata).also { this[libFile, srcFile] = it } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt index f8fa3e54bb5..3af6ba2dd80 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.builders.TranslationPluginContext +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl import org.jetbrains.kotlin.ir.util.* @@ -18,6 +19,7 @@ import org.jetbrains.kotlin.library.IrLibrary import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.containsErrorCode +import org.jetbrains.kotlin.utils.memoryOptimizedMap class JsIrLinker( private val currentModule: ModuleDescriptor?, messageLogger: IrMessageLogger, builtIns: IrBuiltIns, symbolTable: SymbolTable, @@ -67,8 +69,16 @@ class JsIrLinker( } } + private val deserializedFilesInKlibOrder = mutableMapOf>() + private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategyResolver: (String) -> DeserializationStrategy, libraryAbiVersion: KotlinAbiVersion, allowErrorCode: Boolean) : - BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategyResolver, libraryAbiVersion, allowErrorCode, false) + BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategyResolver, libraryAbiVersion, allowErrorCode, true) { + + override fun init(delegate: IrModuleDeserializer) { + super.init(delegate) + deserializedFilesInKlibOrder[moduleFragment] = fileDeserializationStates.memoryOptimizedMap { it.file } + } + } override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection): IrModuleDeserializer { val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies) @@ -91,6 +101,10 @@ class JsIrLinker( return deserializersForModules[moduleDescriptor.name.asString()] ?: error("Deserializer for $moduleDescriptor not found") } + fun getDeserializedFilesInKlibOrder(fragment: IrModuleFragment): List { + return deserializedFilesInKlibOrder[fragment] ?: emptyList() + } + class JsFePluginContext( override val moduleDescriptor: ModuleDescriptor, override val symbolTable: ReferenceSymbolTable, diff --git a/js/js.tests/test/org/jetbrains/kotlin/incremental/AbstractInvalidationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/incremental/AbstractInvalidationTest.kt index 2f3e3622d66..bae9eb25007 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/incremental/AbstractInvalidationTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/incremental/AbstractInvalidationTest.kt @@ -242,7 +242,7 @@ abstract class AbstractInvalidationTest( for ((srcFile, dirtyStats) in updateStatus) { for (dirtyStat in dirtyStats) { if (dirtyStat != DirtyFileState.NON_MODIFIED_IR) { - got.getOrPut(dirtyStat.str) { mutableSetOf() }.add(File(srcFile.path).name) + got.getOrPut(dirtyStat.str) { mutableSetOf() }.add(srcFile.toString()) } } }