[JS IR] Fix IC invalidation process when symbols are modified
The patch fixes the cases of IC invalidation when symbols are modified: adding and removing inline, data, in, out, suspend qualifiers. For that purpose an extra hash is used. It is written in a direct dependency graph into an IC cache metadata file. For inline functions a transitive hash is used. For non-inline functions, classes, and others a symbol hash is used. The invalidation routine marks the file as dirty (with 'updated imports' state) if hash is modified. ^KT-51083 Fixed ^KT-51088 Fixed ^KT-51090 Fixed ^KT-51099 Fixed
This commit is contained in:
committed by
Space
parent
644447db84
commit
5b4e9e2966
@@ -37,7 +37,7 @@ enum class DirtyFileState(val str: String) {
|
||||
ADDED_FILE("added file"),
|
||||
MODIFIED_IR("modified ir"),
|
||||
UPDATED_EXPORTS("updated exports"),
|
||||
UPDATED_INLINE_IMPORTS("updated inline imports"),
|
||||
UPDATED_IMPORTS("updated imports"),
|
||||
REMOVED_INVERSE_DEPENDS("removed inverse depends"),
|
||||
REMOVED_DIRECT_DEPENDS("removed direct depends"),
|
||||
REMOVED_FILE("removed file")
|
||||
@@ -52,9 +52,7 @@ class CacheUpdater(
|
||||
private val mainArguments: List<String>?,
|
||||
private val executor: CacheExecutor
|
||||
) {
|
||||
private val hashCalculator = InlineFunctionTransitiveHashCalculator()
|
||||
private val transitiveHashes
|
||||
get() = hashCalculator.transitiveHashes
|
||||
private val signatureHashCalculator = IdSignatureHashCalculator()
|
||||
|
||||
private val libraries = loadLibraries(allModules)
|
||||
private val dependencyGraph = buildDependenciesGraph(libraries)
|
||||
@@ -117,26 +115,29 @@ class CacheUpdater(
|
||||
val oldDirectDependencies: KotlinSourceFileMap<*>,
|
||||
|
||||
override val inverseDependencies: KotlinSourceFileMutableMap<MutableSet<IdSignature>> = KotlinSourceFileMutableMap(),
|
||||
override val directDependencies: KotlinSourceFileMutableMap<MutableSet<IdSignature>> = KotlinSourceFileMutableMap(),
|
||||
|
||||
override val importedInlineFunctions: MutableMap<IdSignature, ICHash> = mutableMapOf()
|
||||
override val directDependencies: KotlinSourceFileMutableMap<MutableMap<IdSignature, ICHash>> = KotlinSourceFileMutableMap(),
|
||||
) : KotlinSourceFileMetadata() {
|
||||
fun addInverseDependency(lib: KotlinLibraryFile, src: KotlinSourceFile, signature: IdSignature) =
|
||||
inverseDependencies.addSignature(lib, src, signature)
|
||||
when (val signatures = inverseDependencies[lib, src]) {
|
||||
null -> inverseDependencies[lib, src] = mutableSetOf(signature)
|
||||
else -> signatures += signature
|
||||
}
|
||||
|
||||
fun addDirectDependency(lib: KotlinLibraryFile, src: KotlinSourceFile, signature: IdSignature) =
|
||||
directDependencies.addSignature(lib, src, signature)
|
||||
fun addDirectDependency(lib: KotlinLibraryFile, src: KotlinSourceFile, signature: IdSignature, hash: ICHash) =
|
||||
when (val signatures = directDependencies[lib, src]) {
|
||||
null -> directDependencies[lib, src] = mutableMapOf(signature to hash)
|
||||
else -> signatures[signature] = hash
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdatedDependenciesMetadata(oldMetadata: KotlinSourceFileMetadata) : KotlinSourceFileMetadata() {
|
||||
private val oldInverseDependencies = oldMetadata.inverseDependencies
|
||||
private val newExportedSignatures: Set<IdSignature> by lazy { inverseDependencies.flatSignatures() }
|
||||
|
||||
var importedInlineFunctionsModified = false
|
||||
var importedSignaturesModified = false
|
||||
|
||||
override val inverseDependencies = oldMetadata.inverseDependencies.toMutable()
|
||||
override val directDependencies = oldMetadata.directDependencies.toMutable()
|
||||
override val importedInlineFunctions = oldMetadata.importedInlineFunctions
|
||||
|
||||
override fun getExportedSignatures(): Set<IdSignature> = newExportedSignatures
|
||||
|
||||
@@ -223,8 +224,8 @@ class CacheUpdater(
|
||||
if (dependentFile !in dirtyLibFiles) {
|
||||
val dependentSrcFileMetadata = dependentCache.fetchSourceFileFullMetadata(dependentFile)
|
||||
dependentSrcFileMetadata.directDependencies[libFile, srcFile]?.let {
|
||||
loadingFileExports.inverseDependencies[dependentLib, dependentFile] = it
|
||||
loadingFileExports.allExportedSignatures += it
|
||||
loadingFileExports.inverseDependencies[dependentLib, dependentFile] = it.keys
|
||||
loadingFileExports.allExportedSignatures += it.keys
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,6 +268,7 @@ class CacheUpdater(
|
||||
val maybeImportedSignatures = reachableSignatures.keys.toMutableSet()
|
||||
for ((signature, symbol) in allImplementedSymbols) {
|
||||
if (signature in reachableSignatures) {
|
||||
signatureHashCalculator.addHashForSignatureIfNotExist(signature, symbol)
|
||||
idSignatureToFile[signature] = lib to libSrcFile
|
||||
maybeImportedSignatures.remove(signature)
|
||||
|
||||
@@ -295,8 +297,9 @@ class CacheUpdater(
|
||||
|
||||
for (importedSignature in internalHeader.maybeImportedSignatures) {
|
||||
val (dependencyLib, dependencyFile) = idSignatureToFile[importedSignature] ?: continue
|
||||
internalHeader.addDirectDependency(dependencyLib, dependencyFile, importedSignature)
|
||||
transitiveHashes[importedSignature]?.let { internalHeader.importedInlineFunctions[importedSignature] = it }
|
||||
signatureHashCalculator[importedSignature]?.also { signatureHash ->
|
||||
internalHeader.addDirectDependency(dependencyLib, dependencyFile, importedSignature, signatureHash)
|
||||
} ?: notFoundIcError("signature $importedSignature hash", dependencyLib, dependencyFile)
|
||||
|
||||
updatedMetadata[dependencyLib, dependencyFile]?.also { dependencyMetadata ->
|
||||
dependencyMetadata.addInverseDependency(libFile, srcFile, importedSignature)
|
||||
@@ -339,7 +342,7 @@ class CacheUpdater(
|
||||
continue
|
||||
}
|
||||
val newMetadata = addNewMetadata(dependencyLibFile, dependencySrcFile, dependencySrcMetadata)
|
||||
newMetadata.inverseDependencies[libFile, srcFile] = newSignatures
|
||||
newMetadata.inverseDependencies[libFile, srcFile] = newSignatures.keys
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -367,21 +370,25 @@ class CacheUpdater(
|
||||
private fun KotlinSourceFileMutableMap<UpdatedDependenciesMetadata>.addDependentsWithUpdatedImports(
|
||||
libFile: KotlinLibraryFile, srcFile: KotlinSourceFile, srcFileMetadata: DirtyFileMetadata
|
||||
) {
|
||||
// go through dependent files and check if their inline imports were modified
|
||||
// go through dependent files and check if their imports were modified
|
||||
for ((dependentLibFile, dependentSrcFiles) in srcFileMetadata.inverseDependencies) {
|
||||
val dependentCache = incrementalCaches[dependentLibFile] ?: continue
|
||||
for ((dependentSrcFile, newSignatures) in dependentSrcFiles) {
|
||||
val dependentSrcMetadata = dependentCache.fetchSourceFileFullMetadata(dependentSrcFile)
|
||||
val dependentSignatures = dependentSrcMetadata.directDependencies[libFile, srcFile] ?: emptySet()
|
||||
val importedInlineModified = dependentSrcMetadata.importedInlineFunctions.any {
|
||||
transitiveHashes[it.key]?.let { newHash -> newHash != it.value } ?: (it.key in dependentSignatures)
|
||||
}
|
||||
if (importedInlineModified) {
|
||||
val newMetadata = addNewMetadata(dependentLibFile, dependentSrcFile, dependentSrcMetadata)
|
||||
newMetadata.importedInlineFunctionsModified = true
|
||||
} else if (dependentSignatures != newSignatures) {
|
||||
val newMetadata = addNewMetadata(dependentLibFile, dependentSrcFile, dependentSrcMetadata)
|
||||
newMetadata.directDependencies[libFile, srcFile] = newSignatures
|
||||
val dependentSignatures = dependentSrcMetadata.directDependencies[libFile, srcFile] ?: emptyMap()
|
||||
when {
|
||||
dependentSrcMetadata is DirtyFileMetadata -> continue
|
||||
this[dependentLibFile, dependentSrcFile]?.importedSignaturesModified == true -> continue
|
||||
dependentSignatures.any { signatureHashCalculator[it.key] != it.value } -> {
|
||||
val newMetadata = addNewMetadata(dependentLibFile, dependentSrcFile, dependentSrcMetadata)
|
||||
newMetadata.importedSignaturesModified = true
|
||||
}
|
||||
dependentSignatures.keys != newSignatures -> {
|
||||
val newMetadata = addNewMetadata(dependentLibFile, dependentSrcFile, dependentSrcMetadata)
|
||||
newMetadata.directDependencies[libFile, srcFile] = newSignatures.associateWith {
|
||||
signatureHashCalculator[it] ?: notFoundIcError("signature $it hash", libFile, srcFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,15 +419,15 @@ class CacheUpdater(
|
||||
val cache = getLibIncrementalCache(libFile)
|
||||
|
||||
for ((srcFile, srcFileMetadata) in srcFiles) {
|
||||
val isSignatureUpdated = srcFileMetadata.isExportedSignaturesUpdated()
|
||||
if (isSignatureUpdated || srcFileMetadata.importedInlineFunctionsModified) {
|
||||
val isExportedSignatureUpdated = srcFileMetadata.isExportedSignaturesUpdated()
|
||||
if (isExportedSignatureUpdated || srcFileMetadata.importedSignaturesModified) {
|
||||
// if exported signatures or imported inline functions were modified - rebuild
|
||||
filesToRebuild[srcFile] = srcFileMetadata
|
||||
if (isSignatureUpdated) {
|
||||
if (isExportedSignatureUpdated) {
|
||||
fileStats.addDirtFileStat(srcFile, DirtyFileState.UPDATED_EXPORTS)
|
||||
}
|
||||
if (srcFileMetadata.importedInlineFunctionsModified) {
|
||||
fileStats.addDirtFileStat(srcFile, DirtyFileState.UPDATED_INLINE_IMPORTS)
|
||||
if (srcFileMetadata.importedSignaturesModified) {
|
||||
fileStats.addDirtFileStat(srcFile, DirtyFileState.UPDATED_IMPORTS)
|
||||
}
|
||||
} else {
|
||||
// if signatures and inline functions are the same - just update cache metadata
|
||||
@@ -486,7 +493,7 @@ class CacheUpdater(
|
||||
var lastDirtyFiles: KotlinSourceFileMap<KotlinSourceFileExports> = dirtyFileExports
|
||||
|
||||
while (true) {
|
||||
hashCalculator.updateTransitiveHashes(loadedIr.loadedFragments.values)
|
||||
signatureHashCalculator.updateInlineFunctionTransitiveHashes(loadedIr.loadedFragments.values)
|
||||
|
||||
val dirtyHeaders = rebuildDirtySourceMetadata(loadedIr.linker, loadedIr.loadedFragments, lastDirtyFiles)
|
||||
|
||||
|
||||
+15
@@ -8,6 +8,10 @@ package org.jetbrains.kotlin.ir.backend.js.ic
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CrossModuleReferences
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
@@ -85,6 +89,17 @@ internal fun IrElement.irElementHashForIC() = HashCalculatorForIC().also {
|
||||
)
|
||||
}.finalize()
|
||||
|
||||
internal fun IrSymbol.irSymbolHashForIC() = HashCalculatorForIC().also {
|
||||
it.update(toString())
|
||||
// symbol rendering prints very little information about type parameters
|
||||
// TODO may be it make sense to update rendering?
|
||||
(owner as? IrTypeParametersContainer)?.let { typeParameters ->
|
||||
typeParameters.typeParameters.forEach { typeParameter ->
|
||||
it.update(typeParameter.symbol.toString())
|
||||
}
|
||||
}
|
||||
}.finalize()
|
||||
|
||||
internal fun String.stringHashForIC() = HashCalculatorForIC().also { it.update(this) }.finalize()
|
||||
|
||||
internal fun KotlinLibrary.fingerprint(fileIndex: Int) = HashCalculatorForIC().apply {
|
||||
|
||||
+22
-13
@@ -6,32 +6,33 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
|
||||
class InlineFunctionTransitiveHashCalculator {
|
||||
class IdSignatureHashCalculator {
|
||||
private val flatHashes = mutableMapOf<IrFunction, ICHash>()
|
||||
private val inlineFunctionCallGraph: MutableMap<IrFunction, Set<IrFunction>> = mutableMapOf()
|
||||
private val processingFunctions = mutableSetOf<IrFunction>()
|
||||
private val functionTransitiveHashes = mutableMapOf<IrFunction, ICHash>()
|
||||
private val idSignatureTransitiveHashes = mutableMapOf<IdSignature, ICHash>()
|
||||
|
||||
val transitiveHashes: Map<IdSignature, ICHash>
|
||||
get() = idSignatureTransitiveHashes
|
||||
private val allIdSignatureHashes = mutableMapOf<IdSignature, ICHash>()
|
||||
|
||||
|
||||
private inner class FlatHashCalculator : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) = element.acceptChildren(this, null)
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||
if (declaration.isInline) {
|
||||
@@ -47,11 +48,11 @@ class InlineFunctionTransitiveHashCalculator {
|
||||
}
|
||||
}
|
||||
// go deeper since local inline special declarations (like a reference adaptor) may appear
|
||||
declaration.acceptChildren(this, null)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class CallGraphBuilder : IrElementVisitor<Unit, MutableSet<IrFunction>> {
|
||||
private inner class InlineFunctionCallGraphBuilder : IrElementVisitor<Unit, MutableSet<IrFunction>> {
|
||||
var inlineFunctionCallDepth: Int = 0
|
||||
|
||||
override fun visitElement(element: IrElement, data: MutableSet<IrFunction>) = element.acceptChildren(this, data)
|
||||
@@ -103,7 +104,7 @@ class InlineFunctionTransitiveHashCalculator {
|
||||
functionInlineHash = functionInlineHash.combineWith(getInlineFunctionTransitiveHash(callee))
|
||||
}
|
||||
processingFunctions.remove(f)
|
||||
f.symbol.signature?.let { idSignatureTransitiveHashes[it] = functionInlineHash }
|
||||
f.symbol.signature?.let { allIdSignatureHashes[it] = functionInlineHash }
|
||||
functionInlineHash
|
||||
}
|
||||
|
||||
@@ -117,9 +118,17 @@ class InlineFunctionTransitiveHashCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTransitiveHashes(fragments: Collection<IrModuleFragment>) {
|
||||
fun updateInlineFunctionTransitiveHashes(fragments: Collection<IrModuleFragment>) {
|
||||
fragments.forEach { it.acceptVoid(FlatHashCalculator()) }
|
||||
fragments.forEach { it.acceptChildren(CallGraphBuilder(), mutableSetOf()) }
|
||||
fragments.forEach { it.acceptChildren(InlineFunctionCallGraphBuilder(), mutableSetOf()) }
|
||||
updateTransitiveHashesByCallGraph()
|
||||
}
|
||||
|
||||
fun addHashForSignatureIfNotExist(signature: IdSignature, symbol: IrSymbol) {
|
||||
if (signature !in allIdSignatureHashes) {
|
||||
allIdSignatureHashes[signature] = symbol.irSymbolHashForIC()
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(signature: IdSignature) = allIdSignatureHashes[signature]
|
||||
}
|
||||
+66
-57
@@ -61,16 +61,12 @@ class IncrementalCache(private val library: KotlinLibrary, cachePath: String) {
|
||||
|
||||
private class KotlinSourceFileMetadataFromDisk(
|
||||
override val inverseDependencies: KotlinSourceFileMap<Set<IdSignature>>,
|
||||
override val directDependencies: KotlinSourceFileMap<Set<IdSignature>>,
|
||||
|
||||
override val importedInlineFunctions: Map<IdSignature, ICHash>
|
||||
override val directDependencies: KotlinSourceFileMap<Map<IdSignature, ICHash>>,
|
||||
) : KotlinSourceFileMetadata()
|
||||
|
||||
private object KotlinSourceFileMetadataNotExist : KotlinSourceFileMetadata() {
|
||||
override val inverseDependencies = KotlinSourceFileMap<Set<IdSignature>>(emptyMap())
|
||||
override val directDependencies = KotlinSourceFileMap<Set<IdSignature>>(emptyMap())
|
||||
|
||||
override val importedInlineFunctions = emptyMap<IdSignature, ICHash>()
|
||||
override val directDependencies = KotlinSourceFileMap<Map<IdSignature, ICHash>>(emptyMap())
|
||||
}
|
||||
|
||||
private val kotlinLibrarySourceFileMetadata = mutableMapOf<KotlinSourceFile, KotlinSourceFileMetadata>()
|
||||
@@ -165,46 +161,53 @@ class IncrementalCache(private val library: KotlinLibrary, cachePath: String) {
|
||||
private fun fetchSourceFileMetadata(srcFile: KotlinSourceFile, loadSignatures: Boolean) =
|
||||
kotlinLibrarySourceFileMetadata.getOrPut(srcFile) {
|
||||
val signatureToIndexMapping = signatureToIndexMappingFromMetadata.getOrPut(srcFile) { mutableMapOf() }
|
||||
fun CodedInputStream.deserializeIdSignatureAndSave(deserializer: IdSignatureDeserializer) = readIdSignature { index ->
|
||||
val deserializer: IdSignatureDeserializer by lazy {
|
||||
kotlinLibraryHeader.signatureDeserializers[srcFile] ?: notFoundIcError("signature deserializer", libraryFile, srcFile)
|
||||
}
|
||||
|
||||
fun CodedInputStream.deserializeIdSignatureAndSave() = readIdSignature { index ->
|
||||
val signature = deserializer.deserializeIdSignature(index)
|
||||
signatureToIndexMapping[signature] = index
|
||||
signature
|
||||
}
|
||||
|
||||
val deserializer: IdSignatureDeserializer by lazy {
|
||||
kotlinLibraryHeader.signatureDeserializers[srcFile] ?: notFoundIcError("signature deserializer", libraryFile, srcFile)
|
||||
fun <T> CodedInputStream.readDependencies(signaturesReader: () -> T) = buildMapUntil(readInt32()) {
|
||||
val libraryFile = KotlinLibraryFile.fromProtoStream(this@readDependencies)
|
||||
val depends = buildMapUntil(readInt32()) {
|
||||
val dependencySrcFile = KotlinSourceFile.fromProtoStream(this@readDependencies)
|
||||
put(dependencySrcFile, signaturesReader())
|
||||
}
|
||||
put(libraryFile, depends)
|
||||
}
|
||||
|
||||
fun CodedInputStream.readDirectDependencies() = readDependencies {
|
||||
if (loadSignatures) {
|
||||
buildMapUntil(readInt32()) {
|
||||
val signature = deserializeIdSignatureAndSave()
|
||||
put(signature, ICHash.fromProtoStream(this@readDirectDependencies))
|
||||
}
|
||||
} else {
|
||||
repeat(readInt32()) {
|
||||
skipIdSignature()
|
||||
ICHash.fromProtoStream(this@readDirectDependencies)
|
||||
}
|
||||
emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
fun CodedInputStream.readInverseDependencies() = readDependencies {
|
||||
if (loadSignatures) {
|
||||
buildSetUntil(readInt32()) { add(deserializeIdSignatureAndSave()) }
|
||||
} else {
|
||||
repeat(readInt32()) { skipIdSignature() }
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
srcFile.getCacheFile(METADATA_SUFFIX).useCodedInputIfExists {
|
||||
fun readDependencies() = buildMapUntil(readInt32()) {
|
||||
val libraryFile = KotlinLibraryFile.fromProtoStream(this@useCodedInputIfExists)
|
||||
val depends = buildMapUntil(readInt32()) {
|
||||
val dependencySrcFile = KotlinSourceFile.fromProtoStream(this@useCodedInputIfExists)
|
||||
val dependencySignatures = if (loadSignatures) {
|
||||
buildSetUntil(readInt32()) { add(deserializeIdSignatureAndSave(deserializer)) }
|
||||
} else {
|
||||
repeat(readInt32()) { skipIdSignature() }
|
||||
emptySet()
|
||||
}
|
||||
put(dependencySrcFile, dependencySignatures)
|
||||
}
|
||||
put(libraryFile, depends)
|
||||
}
|
||||
|
||||
val directDependencies = KotlinSourceFileMap(readDependencies())
|
||||
val reverseDependencies = KotlinSourceFileMap(readDependencies())
|
||||
|
||||
val importedInlineFunctions = if (loadSignatures) {
|
||||
buildMapUntil(readInt32()) {
|
||||
val signature = deserializeIdSignatureAndSave(deserializer)
|
||||
val transitiveHash = ICHash.fromProtoStream(this@useCodedInputIfExists)
|
||||
put(signature, transitiveHash)
|
||||
}
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
KotlinSourceFileMetadataFromDisk(reverseDependencies, directDependencies, importedInlineFunctions)
|
||||
val directDependencies = KotlinSourceFileMap(readDirectDependencies())
|
||||
val reverseDependencies = KotlinSourceFileMap(readInverseDependencies())
|
||||
KotlinSourceFileMetadataFromDisk(reverseDependencies, directDependencies)
|
||||
} ?: KotlinSourceFileMetadataNotExist
|
||||
}
|
||||
|
||||
@@ -223,30 +226,36 @@ class IncrementalCache(private val library: KotlinLibrary, cachePath: String) {
|
||||
fun CodedOutputStream.serializeIdSignature(signature: IdSignature) =
|
||||
writeIdSignature(signature) { signatureToIndexMapping[it] ?: signatureToIndexMappingSaved[it] }
|
||||
|
||||
headerCacheFile.useCodedOutput {
|
||||
fun writeDepends(depends: KotlinSourceFileMap<Set<IdSignature>>) {
|
||||
writeInt32NoTag(depends.size)
|
||||
for ((dependencyLibFile, dependencySrcFiles) in depends) {
|
||||
dependencyLibFile.toProtoStream(this)
|
||||
writeInt32NoTag(dependencySrcFiles.size)
|
||||
for ((dependencySrcFile, signatures) in dependencySrcFiles) {
|
||||
dependencySrcFile.toProtoStream(this)
|
||||
writeInt32NoTag(signatures.size)
|
||||
for (signature in signatures) {
|
||||
serializeIdSignature(signature)
|
||||
}
|
||||
}
|
||||
fun <T> CodedOutputStream.writeDependencies(depends: KotlinSourceFileMap<T>, signaturesWriter: (T) -> Unit) {
|
||||
writeInt32NoTag(depends.size)
|
||||
for ((dependencyLibFile, dependencySrcFiles) in depends) {
|
||||
dependencyLibFile.toProtoStream(this)
|
||||
writeInt32NoTag(dependencySrcFiles.size)
|
||||
for ((dependencySrcFile, signatures) in dependencySrcFiles) {
|
||||
dependencySrcFile.toProtoStream(this)
|
||||
signaturesWriter(signatures)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeDepends(sourceFileMetadata.directDependencies)
|
||||
writeDepends(sourceFileMetadata.inverseDependencies)
|
||||
|
||||
writeInt32NoTag(sourceFileMetadata.importedInlineFunctions.size)
|
||||
for ((signature, transitiveHash) in sourceFileMetadata.importedInlineFunctions) {
|
||||
fun CodedOutputStream.writeDirectDependencies(depends: KotlinSourceFileMap<Map<IdSignature, ICHash>>) = writeDependencies(depends) {
|
||||
writeInt32NoTag(it.size)
|
||||
for ((signature, hash) in it) {
|
||||
serializeIdSignature(signature)
|
||||
transitiveHash.toProtoStream(this)
|
||||
hash.toProtoStream(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun CodedOutputStream.writeInverseDependencies(depends: KotlinSourceFileMap<Set<IdSignature>>) = writeDependencies(depends) {
|
||||
writeInt32NoTag(it.size)
|
||||
for (signature in it) {
|
||||
serializeIdSignature(signature)
|
||||
}
|
||||
}
|
||||
|
||||
headerCacheFile.useCodedOutput {
|
||||
writeDirectDependencies(sourceFileMetadata.directDependencies)
|
||||
writeInverseDependencies(sourceFileMetadata.inverseDependencies)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||
import org.jetbrains.kotlin.protobuf.CodedOutputStream
|
||||
import java.io.File
|
||||
|
||||
@JvmInline
|
||||
value class KotlinLibraryFile(val path: String) {
|
||||
@@ -20,6 +21,9 @@ value class KotlinLibraryFile(val path: String) {
|
||||
companion object {
|
||||
fun fromProtoStream(input: CodedInputStream) = KotlinLibraryFile(input.readString())
|
||||
}
|
||||
|
||||
// for debugging purposes only
|
||||
override fun toString(): String = File(path).name
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
@@ -31,6 +35,9 @@ value class KotlinSourceFile(val path: String) {
|
||||
companion object {
|
||||
fun fromProtoStream(input: CodedInputStream) = KotlinSourceFile(input.readString())
|
||||
}
|
||||
|
||||
// for debugging purposes only
|
||||
override fun toString(): String = File(path).name
|
||||
}
|
||||
|
||||
open class KotlinSourceFileMap<out T>(files: Map<KotlinLibraryFile, Map<KotlinSourceFile, T>>) :
|
||||
@@ -94,9 +101,7 @@ abstract class KotlinSourceFileExports {
|
||||
}
|
||||
|
||||
abstract class KotlinSourceFileMetadata : KotlinSourceFileExports() {
|
||||
abstract val directDependencies: KotlinSourceFileMap<Set<IdSignature>>
|
||||
|
||||
abstract val importedInlineFunctions: Map<IdSignature, ICHash>
|
||||
abstract val directDependencies: KotlinSourceFileMap<Map<IdSignature, ICHash>>
|
||||
}
|
||||
|
||||
fun KotlinSourceFileMetadata.isEmpty() = inverseDependencies.isEmpty() && directDependencies.isEmpty() && importedInlineFunctions.isEmpty()
|
||||
fun KotlinSourceFileMetadata.isEmpty() = inverseDependencies.isEmpty() && directDependencies.isEmpty()
|
||||
|
||||
Reference in New Issue
Block a user