[Klib] Deduplicate IrFileEntry list

^KT-73826
diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt
index 62c1e9c..532c77f 100644
--- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt
+++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt
@@ -132,8 +132,8 @@
         }
 
         for ((srcFile, irData) in incrementalResults.irFileData) {
-            val (fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos) = irData
-            irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos)
+            val (fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos, fileEntries) = irData
+            irTranslationResults.put(srcFile, fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos, fileEntries)
         }
     }
 
@@ -298,8 +298,9 @@
         val fqn = input.readArray()
         val fileMetadata = input.readArray()
         val debugInfos = input.readArrayOrNull()
+        val fileEntries = input.readArray()
 
-        return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos)
+        return IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfos, fileEntries)
     }
 }
 
@@ -334,9 +335,10 @@
         fqn: ByteArray,
         newFileMetadata: ByteArray,
         debugInfos: ByteArray?,
+        fileEntries: ByteArray,
     ) {
         this[sourceFile] =
-            IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn, newFileMetadata, debugInfos)
+            IrTranslationResultValue(newFiledata, newTypes, newSignatures, newStrings, newDeclarations, newBodies, fqn, newFileMetadata, debugInfos, fileEntries)
     }
 }
 
diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt
index 00d23bd..c6006a5 100644
--- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt
+++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt
@@ -25,6 +25,7 @@
         fqn: ByteArray,
         fileMetadata: ByteArray,
         debugInfo: ByteArray?,
+        fileEntries: ByteArray,
     ) {
         TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
     }
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 65ac434..02c6104 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
@@ -6,6 +6,7 @@
 package org.jetbrains.kotlin.ir.backend.js.ic
 
 import org.jetbrains.kotlin.backend.common.serialization.*
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile
 import org.jetbrains.kotlin.ir.backend.js.*
 import org.jetbrains.kotlin.library.KotlinLibrary
@@ -55,6 +56,7 @@
                 override fun string(index: Int): ByteArray = library.string(index, it)
                 override fun body(index: Int): ByteArray = err()
                 override fun debugInfo(index: Int): ByteArray? = null
+                override fun fileEntry(index: Int): ByteArray = library.fileEntry(index, it)
             }), null, irInterner)
 
             put(sourceFiles[it], deserializer)
@@ -74,7 +76,7 @@
         val extReg = ExtensionRegistryLite.newInstance()
         val sources = (0 until library.fileCount()).map {
             val fileProto = IrFile.parseFrom(library.file(it).codedInputStream, extReg)
-            fileProto.fileEntry.name
+            ProtoFileEntry.parseFrom(library.fileEntry(fileProto.fileEntry, it)).name
         }
         KotlinSourceFile.fromSources(sources)
     }
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 7316811..3bb2654 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
@@ -52,6 +52,7 @@
     private val indexedStrings = arrayOfNulls<IrArrayMemoryReader>(icData.size)
     private val indexedDebugInfos = arrayOfNulls<IrArrayMemoryReader?>(icData.size)
     private val indexedBodies = arrayOfNulls<IrArrayMemoryReader>(icData.size)
+    private val indexedFileEntries = arrayOfNulls<IrArrayMemoryReader>(icData.size)
 
     override fun irDeclaration(index: Int, fileIndex: Int): ByteArray =
         indexedDeclarations.itemBytes(fileIndex, DeclarationId(index)) {
@@ -83,6 +84,11 @@
             icData[fileIndex].debugInfo?.let { IrArrayMemoryReader(it) }
         }
 
+    override fun fileEntry(index: Int, fileIndex: Int): ByteArray =
+        indexedFileEntries.itemBytes(fileIndex, index) {
+            IrArrayMemoryReader(icData[fileIndex].fileEntries)
+        }
+
     override fun file(index: Int): ByteArray = icData[index].fileData
 
     override fun fileCount(): Int = icData.size
@@ -96,6 +102,8 @@
     override fun declarations(fileIndex: Int): ByteArray = icData[fileIndex].declarations
 
     override fun bodies(fileIndex: Int): ByteArray = icData[fileIndex].bodies
+
+    override fun fileEntries(fileIndex: Int): ByteArray = icData[fileIndex].fileEntries
 }
 
 class CurrentModuleWithICDeserializer(
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt
index 10080ab..0c78621 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt
@@ -168,7 +168,7 @@
         val inlineFunctionSymbol = runIf(proto.hasInlineFunctionSymbol()) {
             deserializeTypedSymbol<IrFunctionSymbol>(proto.inlineFunctionSymbol, FUNCTION_SYMBOL)
         }
-        val fileEntry = deserializeFileEntry(proto.fileEntry)
+        val fileEntry = deserializeFileEntry(libraryFile.fileEntry(proto.fileEntry))
         return withDeserializedBlock(proto.base) { origin, statements ->
             IrInlinedFunctionBlockImpl(start, end, type, inlineFunctionSymbol, fileEntry, origin, statements)
         }
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt
index 852f35c..1dabca5 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt
@@ -24,9 +24,9 @@
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
-import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 
 class IrFileDeserializer(
     val file: IrFile,
@@ -191,6 +191,7 @@
     abstract fun expressionBody(index: Int): ProtoExpression
     abstract fun statementBody(index: Int): ProtoStatement
     abstract fun debugInfo(index: Int): String?
+    abstract fun fileEntry(index: Int): ProtoFileEntry
 }
 
 abstract class IrLibraryBytesSource {
@@ -200,6 +201,7 @@
     abstract fun string(index: Int): ByteArray
     abstract fun body(index: Int): ByteArray
     abstract fun debugInfo(index: Int): ByteArray?
+    abstract fun fileEntry(index: Int): ByteArray
 }
 
 class IrLibraryFileFromBytes(private val bytesSource: IrLibraryBytesSource) : IrLibraryFile() {
@@ -222,6 +224,8 @@
 
     override fun debugInfo(index: Int): String? = bytesSource.debugInfo(index)?.let { WobblyTF8.decode(it) }
 
+    override fun fileEntry(index: Int): ProtoFileEntry = ProtoFileEntry.parseFrom(bytesSource.fileEntry(index), extensionRegistryLite)
+
     companion object {
         val extensionRegistryLite: ExtensionRegistryLite = ExtensionRegistryLite.newInstance()
     }
@@ -234,13 +238,14 @@
     override fun string(index: Int): ByteArray = klib.string(index, fileIndex)
     override fun body(index: Int): ByteArray = klib.body(index, fileIndex)
     override fun debugInfo(index: Int): ByteArray? = klib.debugInfo(index, fileIndex)
+    override fun fileEntry(index: Int): ByteArray = klib.fileEntry(index, fileIndex)
 }
 
 fun IrLibraryFile.deserializeFqName(fqn: List<Int>): String =
     fqn.joinToString(".", transform = ::string)
 
 fun IrLibraryFile.createFile(module: IrModuleFragment, fileProto: ProtoFile): IrFile {
-    val fileEntry = deserializeFileEntry(fileProto.fileEntry)
+    val fileEntry = deserializeFileEntry(fileEntry(fileProto.fileEntry))
     val fqName = FqName(deserializeFqName(fileProto.fqNameList))
     val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(module.descriptor, fqName)
     val symbol = IrFileSymbolImpl(packageFragmentDescriptor)
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
index 2f304c7..33c9ded 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
@@ -153,6 +153,9 @@
     private val protoStringMap = hashMapOf<String, Int>()
     protected val protoStringArray = arrayListOf<String>()
 
+    private val protoIrFileEntryMap = hashMapOf<ProtoFileEntry, Int>()
+    protected val protoIrFileEntryArray = arrayListOf<ProtoFileEntry>()
+
     // The same signature could be used multiple times in a file
     // so use this index to store signature only once.
     private val protoIdSignatureMap = mutableMapOf<IdSignature, Int>()
@@ -1359,7 +1362,15 @@
 
 // ---------- Top level ------------------------------------------------------
 
-    private fun serializeFileEntry(entry: IrFileEntry, includeLineStartOffsets: Boolean = true): ProtoFileEntry =
+    private fun serializeFileEntry(entry: IrFileEntry, includeLineStartOffsets: Boolean = true): Int {
+        val proto = buildFileEntry(entry, includeLineStartOffsets)
+        return protoIrFileEntryMap.getOrPut(proto) {
+            protoIrFileEntryArray.add(proto)
+            protoIrFileEntryArray.size - 1
+        }
+    }
+
+    private fun buildFileEntry(entry: IrFileEntry, includeLineStartOffsets: Boolean = true): ProtoFileEntry =
         ProtoFileEntry.newBuilder()
             .setName(entry.matchAndNormalizeFilePath())
             .applyIf(includeLineStartOffsets) { addAllLineStartOffset(entry.lineStartOffsetsForSerialization) }
@@ -1495,6 +1506,7 @@
             declarations = IrMemoryDeclarationWriter(topLevelDeclarations).writeIntoMemory(),
             debugInfo = IrMemoryStringWriter(protoDebugInfoArray).writeIntoMemory(),
             backendSpecificMetadata = backendSpecificMetadata(file)?.toByteArray(),
+            fileEntries = IrMemoryArrayWriter(protoIrFileEntryArray.map { it.toByteArray() }).writeIntoMemory(),
         )
     }
 
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/NonLinkingIrInlineFunctionDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/NonLinkingIrInlineFunctionDeserializer.kt
index e554537..34c02c1 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/NonLinkingIrInlineFunctionDeserializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/NonLinkingIrInlineFunctionDeserializer.kt
@@ -19,6 +19,7 @@
 import org.jetbrains.kotlin.ir.symbols.impl.*
 import org.jetbrains.kotlin.ir.util.*
 import org.jetbrains.kotlin.ir.visitors.acceptVoid
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
 import org.jetbrains.kotlin.library.KotlinLibrary
 import org.jetbrains.kotlin.library.metadata.KlibDeserializedContainerSource
@@ -149,7 +150,7 @@
 
         private val dummyFileSymbol = IrFileSymbolImpl().apply {
             IrFileImpl(
-                fileEntry = NaiveSourceBasedFileEntryImpl(fileProto.fileEntry.name),
+                fileEntry = NaiveSourceBasedFileEntryImpl(ProtoFileEntry.parseFrom(library.fileEntry(fileProto.fileEntry, fileIndex)).name),
                 symbol = this,
                 packageFqName = FqName(irInterner.string(fileReader.deserializeFqName(fileProto.fqNameList)))
             )
diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt
index 430e016..a3ef63c 100644
--- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt
+++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt
@@ -652,6 +652,7 @@
                         fqName.toByteArray(),
                         fileMetadata,
                         debugInfo,
+                        fileEntries,
                     )
                 }
             }
@@ -752,6 +753,7 @@
                 declarations,
                 debugInfo,
                 fileMetadata,
+                fileEntries,
             )
         }
         storage.add(KotlinFileSerializedData(metaFile.metadata, irFile))
diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt
index d9f9441..92cd793 100644
--- a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt
+++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt
@@ -29,6 +29,7 @@
 import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
 import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
 import org.jetbrains.kotlin.ir.visitors.acceptVoid
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
@@ -50,7 +51,8 @@
         irProto.signatureList,
         irProto.stringList,
         irProto.bodyList,
-        irProto.debugInfoList
+        irProto.debugInfoList,
+        irProto.fileEntryList,
     )
 
     // Only needed for local signature computation.
@@ -130,7 +132,8 @@
     private val signatures: List<ProtoIdSignature>,
     private val strings: List<String>,
     private val bodies: List<JvmIr.XStatementOrExpression>,
-    private val debugInfo: List<String>
+    private val debugInfo: List<String>,
+    private val fileEntries: List<ProtoFileEntry>,
 ) : IrLibraryFile() {
     override fun declaration(index: Int): ProtoDeclaration {
         error("This method is never supposed to be called")
@@ -140,6 +143,7 @@
     override fun signature(index: Int): ProtoIdSignature = signatures[index]
     override fun string(index: Int): String = strings[index]
     override fun debugInfo(index: Int): String = debugInfo[index]
+    override fun fileEntry(index: Int): ProtoFileEntry = fileEntries[index]
 
     override fun expressionBody(index: Int): ProtoExpression =
         bodies[index].also { require(it.hasExpression()) }.expression
diff --git a/compiler/tests-integration/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt b/compiler/tests-integration/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt
index c43e4eb..d9ee25e 100644
--- a/compiler/tests-integration/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt
+++ b/compiler/tests-integration/tests/org/jetbrains/kotlin/klib/FilePathsInKlibTest.kt
@@ -8,6 +8,7 @@
 import org.jetbrains.kotlin.ObsoleteTestInfrastructure
 import org.jetbrains.kotlin.backend.common.CommonKLibResolver
 import org.jetbrains.kotlin.backend.common.serialization.codedInputStream
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile
 import org.jetbrains.kotlin.cli.js.K2JSCompiler
 import org.jetbrains.kotlin.incremental.md5
@@ -44,7 +45,7 @@
         for (i in 0 until fileSize) {
             val fileStream = lib.file(i).codedInputStream
             val fileProto = IrFile.parseFrom(fileStream, extReg)
-            val fileName = fileProto.fileEntry.name
+            val fileName = ProtoFileEntry.parseFrom(lib.fileEntry(fileProto.fileEntry, i)).name//fileProto.fileEntry.name
 
             result.add(fileName)
         }
diff --git a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/impl/LibraryAbiReaderImpl.kt b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/impl/LibraryAbiReaderImpl.kt
index e00c7c3..ef5db90 100644
--- a/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/impl/LibraryAbiReaderImpl.kt
+++ b/compiler/util-klib-abi/src/org/jetbrains/kotlin/library/abi/impl/LibraryAbiReaderImpl.kt
@@ -35,6 +35,7 @@
 import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
 import java.io.File
 import org.jetbrains.kotlin.konan.file.File as KFile
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrClass as ProtoClass
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationBase as ProtoDeclarationBase
@@ -134,7 +135,10 @@
             val packageFQN = fileReader.deserializeFqName(proto.fqNameList)
             packageName = AbiCompoundName(packageFQN)
 
-            val fileName = if (proto.hasFileEntry() && proto.fileEntry.hasName()) proto.fileEntry.name else "<unknown>"
+            val fileName = if (proto.hasFileEntry()) {
+                val fileEntry = ProtoFileEntry.parseFrom(library.fileEntry(proto.fileEntry, fileIndex))
+                if (fileEntry.hasName()) fileEntry.name else "<unknown>"
+            } else "<unknown>"
 
             val fileSignature = FileSignature(
                 id = Any(), // Just an unique object.
diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibrary.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibrary.kt
index 8d57278..4e94d93 100644
--- a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibrary.kt
+++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibrary.kt
@@ -89,6 +89,7 @@
     fun string(index: Int, fileIndex: Int): ByteArray
     fun body(index: Int, fileIndex: Int): ByteArray
     fun debugInfo(index: Int, fileIndex: Int): ByteArray?
+    fun fileEntry(index: Int, fileIndex: Int): ByteArray
     fun file(index: Int): ByteArray
     fun fileCount(): Int
 
@@ -97,6 +98,7 @@
     fun strings(fileIndex: Int): ByteArray
     fun declarations(fileIndex: Int): ByteArray
     fun bodies(fileIndex: Int): ByteArray
+    fun fileEntries(fileIndex: Int): ByteArray
 }
 
 val BaseKotlinLibrary.isNativeStdlib: Boolean
diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryLayout.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryLayout.kt
index b049f29..2295725 100644
--- a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryLayout.kt
+++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryLayout.kt
@@ -70,6 +70,8 @@
         get() = File(irDir, "files.knf")
     val irDebugInfo
         get() = File(irDir, "debugInfo.knd")
+    val irFileEntries
+        get() = File(irDir, "fileEntries.knf")
 
     fun irDeclarations(file: File): File = File(file, "irDeclarations.knd")
     fun irTypes(file: File): File = File(file, "types.knt")
diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryWriter.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryWriter.kt
index e5cf4b7..6c9af50 100644
--- a/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryWriter.kt
+++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/KotlinLibraryWriter.kt
@@ -46,6 +46,7 @@
     val declarations: ByteArray,
     val debugInfo: ByteArray?,
     val backendSpecificMetadata: ByteArray?,
+    val fileEntries: ByteArray,
 )
 
 class SerializedIrModule(val files: Collection<SerializedIrFile>)
\ No newline at end of file
diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryImpl.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryImpl.kt
index ed6e37d..f779dda 100644
--- a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryImpl.kt
+++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryImpl.kt
@@ -109,6 +109,8 @@
 
     override fun debugInfo(index: Int, fileIndex: Int) = debugInfos?.tableItemBytes(fileIndex, index)
 
+    override fun fileEntry(index: Int, fileIndex: Int) = fileEntries.tableItemBytes(fileIndex, index)
+
     override fun file(index: Int) = files.tableItemBytes(index)
 
     private fun loadIrDeclaration(index: Int, fileIndex: Int) =
@@ -150,6 +152,12 @@
         }
     }
 
+    private val fileEntries: IrMultiArrayFileReader by lazy {
+        IrMultiArrayFileReader(access.realFiles {
+            it.irFileEntries
+        })
+    }
+
     private val files: IrArrayFileReader by lazy {
         IrArrayFileReader(access.realFiles {
             it.irFiles
@@ -175,6 +183,10 @@
     override fun bodies(fileIndex: Int): ByteArray {
         return bodies.tableItemBytes(fileIndex)
     }
+
+    override fun fileEntries(fileIndex: Int): ByteArray {
+        return fileEntries.tableItemBytes(fileIndex)
+    }
 }
 
 class IrPerFileLibraryImpl(_access: IrLibraryAccess<IrKotlinLibraryLayout>) : IrLibraryImpl(_access) {
@@ -260,6 +272,17 @@
         return dataReader?.tableItemBytes(index)
     }
 
+    private val fileToIrFileEntryMap = mutableMapOf<Int, IrArrayFileReader>()
+    override fun fileEntry(index: Int, fileIndex: Int): ByteArray {
+        val dataReader = fileToIrFileEntryMap.getOrPut(fileIndex) {
+            val fileDirectory = directories[fileIndex]
+            IrArrayFileReader(access.realFiles {
+                it.irStrings(fileDirectory)
+            })
+        }
+        return dataReader.tableItemBytes(index)
+    }
+
     override fun file(index: Int): ByteArray {
         return access.realFiles {
             it.irFile(directories[index]).readBytes()
@@ -289,6 +312,10 @@
     override fun bodies(fileIndex: Int): ByteArray {
         TODO("Not yet implemented")
     }
+
+    override fun fileEntries(fileIndex: Int): ByteArray {
+        TODO("Not yet implemented")
+    }
 }
 
 class KotlinLibraryImpl(
diff --git a/js/js.config/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt b/js/js.config/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt
index 0fd3703..2f0c82f 100644
--- a/js/js.config/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt
+++ b/js/js.config/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt
@@ -38,6 +38,7 @@
         fqn: ByteArray,
         fileMetadata: ByteArray,
         debugInfo: ByteArray?,
+        fileEntries: ByteArray,
     )
 }
 
@@ -86,7 +87,8 @@
         fqn: ByteArray,
         fileMetadata: ByteArray,
         debugInfo: ByteArray?,
+        fileEntries: ByteArray,
     ) {
-        _irFileData[sourceFile] = IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfo)
+        _irFileData[sourceFile] = IrTranslationResultValue(fileData, types, signatures, strings, declarations, bodies, fqn, fileMetadata, debugInfo, fileEntries)
     }
 }
diff --git a/js/js.config/src/org/jetbrains/kotlin/incremental/js/TranslationResultValue.kt b/js/js.config/src/org/jetbrains/kotlin/incremental/js/TranslationResultValue.kt
index 5dcba55..de20d07 100644
--- a/js/js.config/src/org/jetbrains/kotlin/incremental/js/TranslationResultValue.kt
+++ b/js/js.config/src/org/jetbrains/kotlin/incremental/js/TranslationResultValue.kt
@@ -28,4 +28,5 @@
     val fqn: ByteArray,
     val fileMetadata: ByteArray,
     val debugInfo: ByteArray?,
+    val fileEntries: ByteArray,
 )
\ No newline at end of file
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt
index 2fa0886..e971997 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CacheSupport.kt
@@ -18,6 +18,7 @@
 import org.jetbrains.kotlin.library.metadata.resolver.KotlinLibraryResolveResult
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
 
 class FileWithFqName(val filePath: String, val fqName: String)
@@ -28,7 +29,7 @@
     }
     return fileProtos.mapIndexed { index, proto ->
         val fileReader = IrLibraryFileFromBytes(IrKlibBytesSource(this, index))
-        FileWithFqName(proto.fileEntry.name, fileReader.deserializeFqName(proto.fqNameList))
+        FileWithFqName(fileReader.fileEntry(proto.fileEntry).name, fileReader.deserializeFqName(proto.fqNameList))
     }
 }
 
@@ -36,7 +37,7 @@
     val fileProtos = Array<ProtoFile>(fileCount()) {
         ProtoFile.parseFrom(file(it).codedInputStream, ExtensionRegistryLite.newInstance())
     }
-    val filePathToIndex = fileProtos.withIndex().associate { it.value.fileEntry.name to it.index }
+    val filePathToIndex = fileProtos.withIndex().associate { ProtoFileEntry.parseFrom(fileEntry(it.value.fileEntry, it.index)).name to it.index }
     return filePaths.map { filePath ->
         val index = filePathToIndex[filePath] ?: error("No file with path $filePath is found in klib $libraryName")
         val fileReader = IrLibraryFileFromBytes(IrKlibBytesSource(this, index))
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt
index 1d8e4c0..747ec75 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt
@@ -7,6 +7,7 @@
 
 import com.intellij.openapi.project.Project
 import org.jetbrains.kotlin.backend.common.serialization.codedInputStream
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile
 import org.jetbrains.kotlin.backend.konan.driver.DynamicCompilerDriver
 import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -87,7 +88,7 @@
                     val lib = createKonanLibrary(File(libPath), "default", null, true)
                     (0 until lib.fileCount()).map { fileIndex ->
                         val proto = IrFile.parseFrom(lib.file(fileIndex).codedInputStream, ExtensionRegistryLite.newInstance())
-                        proto.fileEntry.name
+                        ProtoFileEntry.parseFrom(lib.fileEntry(proto.fileEntry, fileIndex)).name
                     }
                 }
                 else -> null
diff --git a/kotlin-native/klib/src/org/jetbrains/kotlin/cli/klib/IrSignaturesExtractor.kt b/kotlin-native/klib/src/org/jetbrains/kotlin/cli/klib/IrSignaturesExtractor.kt
index 7f37519..b2b3107 100644
--- a/kotlin-native/klib/src/org/jetbrains/kotlin/cli/klib/IrSignaturesExtractor.kt
+++ b/kotlin-native/klib/src/org/jetbrains/kotlin/cli/klib/IrSignaturesExtractor.kt
@@ -15,6 +15,7 @@
 import org.jetbrains.kotlin.metadata.ProtoBuf
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
+import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration
 import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclarationBase as ProtoDeclarationBase
@@ -41,7 +42,10 @@
 
         private val signatureDeserializer: IdSignatureDeserializer = run {
             val packageFQN = fileReader.deserializeFqName(fileProto.fqNameList)
-            val fileName = if (fileProto.hasFileEntry() && fileProto.fileEntry.hasName()) fileProto.fileEntry.name else "<unknown>"
+            val fileName = if (fileProto.hasFileEntry()) {
+                val fileEntry = ProtoFileEntry.parseFrom(library.fileEntry(fileProto.fileEntry, fileIndex))
+                if (fileEntry.hasName()) fileEntry.name else "<unknown>"
+            } else "<unknown>"
 
             val fileSignature = IdSignature.FileSignature(
                     id = Any(), // Just an unique object.