[K/N][caches] Added klib hash computing and storing
This commit is contained in:
+5
@@ -25,12 +25,17 @@ internal class CacheStorage(private val generationState: NativeGenerationState)
|
||||
|
||||
fun saveAdditionalCacheInfo() {
|
||||
outputFiles.prepareTempDirectories()
|
||||
saveKlibContentsHash()
|
||||
saveCacheBitcodeDependencies()
|
||||
saveInlineFunctionBodies()
|
||||
saveClassFields()
|
||||
saveEagerInitializedProperties()
|
||||
}
|
||||
|
||||
private fun saveKlibContentsHash() {
|
||||
outputFiles.hashFile!!.writeBytes(generationState.klibHash.toByteArray())
|
||||
}
|
||||
|
||||
private fun saveCacheBitcodeDependencies() {
|
||||
outputFiles.bitcodeDependenciesFile!!.writeLines(
|
||||
DependenciesSerializer.serialize(generationState.dependenciesTracker.immediateBitcodeDependencies))
|
||||
|
||||
+4
@@ -103,6 +103,9 @@ class CachedLibraries(
|
||||
it.absolutePath
|
||||
}
|
||||
|
||||
fun getFileHash(file: String) =
|
||||
File(path).child(file).child(HASH_FILE_NAME).readBytes()
|
||||
|
||||
override fun computeBitcodeDependencies() = perFileBitcodeDependencies.values.flatten()
|
||||
|
||||
override fun computeBinariesPaths() = fileDirs.map {
|
||||
@@ -232,6 +235,7 @@ class CachedLibraries(
|
||||
const val PER_FILE_CACHE_IR_LEVEL_DIR_NAME = "ir"
|
||||
const val PER_FILE_CACHE_BINARY_LEVEL_DIR_NAME = "bin"
|
||||
|
||||
const val HASH_FILE_NAME = "hash"
|
||||
const val BITCODE_DEPENDENCIES_FILE_NAME = "bitcode_deps"
|
||||
const val INLINE_FUNCTION_BODIES_FILE_NAME = "inline_bodies"
|
||||
const val CLASS_FIELDS_FILE_NAME = "class_fields"
|
||||
|
||||
+4
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.FingerprintHash
|
||||
import org.jetbrains.kotlin.backend.common.serialization.Hash128Bits
|
||||
import org.jetbrains.kotlin.backend.konan.driver.BasicPhaseContext
|
||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||
import org.jetbrains.kotlin.backend.konan.driver.utilities.BackendContextHolder
|
||||
@@ -64,6 +66,8 @@ internal class NativeGenerationState(
|
||||
) : BasicPhaseContext(config), BackendContextHolder<Context>, LlvmIrHolder, BitcodePostProcessingContext {
|
||||
val outputFile = outputFiles.mainFileName
|
||||
|
||||
var klibHash: FingerprintHash = FingerprintHash(Hash128Bits(0U, 0U))
|
||||
|
||||
val inlineFunctionBodies = mutableListOf<SerializedInlineFunctionReference>()
|
||||
val classFields = mutableListOf<SerializedClassFields>()
|
||||
val eagerInitializedFiles = mutableListOf<SerializedEagerInitializedFile>()
|
||||
|
||||
+2
@@ -67,6 +67,8 @@ class OutputFiles(val outputName: String, target: KonanTarget, val produce: Comp
|
||||
|
||||
val symbolicInfoFile = "$nativeBinaryFile.dSYM"
|
||||
|
||||
val hashFile = tempCacheDirectory?.child(CachedLibraries.HASH_FILE_NAME)
|
||||
|
||||
val bitcodeDependenciesFile = tempCacheDirectory?.cacheBinaryPart()?.child(CachedLibraries.BITCODE_DEPENDENCIES_FILE_NAME)
|
||||
|
||||
val inlineFunctionBodiesFile = tempCacheDirectory?.cacheIrPart()?.child(CachedLibraries.INLINE_FUNCTION_BODIES_FILE_NAME)
|
||||
|
||||
+44
-33
@@ -5,10 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.SerializedIrFileFingerprint
|
||||
import org.jetbrains.kotlin.backend.common.serialization.SerializedKlibFingerprint
|
||||
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.KonanFqNames
|
||||
import org.jetbrains.kotlin.backend.konan.isExternalObjCClass
|
||||
import org.jetbrains.kotlin.backend.konan.isFunctionInterfaceFile
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -17,54 +20,62 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.library.impl.javaFile
|
||||
|
||||
internal class CacheInfoBuilder(
|
||||
private val generationState: NativeGenerationState,
|
||||
private val moduleDeserializer: KonanIrLinker.KonanPartialModuleDeserializer,
|
||||
private val irModule: IrModuleFragment
|
||||
) {
|
||||
fun build() = irModule.files.forEach { irFile ->
|
||||
var hasEagerlyInitializedProperties = false
|
||||
fun build() {
|
||||
if (!generationState.config.producePerFileCache)
|
||||
generationState.klibHash = SerializedKlibFingerprint(moduleDeserializer.klib.libraryFile.javaFile()).klibFingerprint
|
||||
irModule.files.forEach { irFile ->
|
||||
var hasEagerlyInitializedProperties = false
|
||||
|
||||
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (!declaration.isInterface && !declaration.isLocal
|
||||
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
) {
|
||||
val declaredFields = generationState.context.getLayoutBuilder(declaration).getDeclaredFields(generationState.llvm)
|
||||
generationState.classFields.add(moduleDeserializer.buildClassFields(declaration, declaredFields))
|
||||
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
// Don't need to visit the children here: classes would be all local and wouldn't be handled anyway,
|
||||
// as for functions - both their callees will be handled and inline bodies will be built for the top function.
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (!declaration.isFakeOverride && declaration.isInline && declaration.isExported) {
|
||||
generationState.inlineFunctionBodies.add(moduleDeserializer.buildInlineFunctionReference(declaration))
|
||||
trackCallees(declaration)
|
||||
if (!declaration.isInterface && !declaration.isLocal
|
||||
&& declaration.isExported && declaration.origin != DECLARATION_ORIGIN_FUNCTION_CLASS
|
||||
) {
|
||||
val declaredFields = generationState.context.getLayoutBuilder(declaration).getDeclaredFields(generationState.llvm)
|
||||
generationState.classFields.add(moduleDeserializer.buildClassFields(declaration, declaredFields))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
// Don't need to visit the children here: classes would be all local and wouldn't be handled anyway,
|
||||
// as for functions - both their callees will be handled and inline bodies will be built for the top function.
|
||||
|
||||
if (declaration.parent == irFile
|
||||
&& declaration.hasAnnotation(KonanFqNames.eagerInitialization)
|
||||
) {
|
||||
hasEagerlyInitializedProperties = true
|
||||
if (!declaration.isFakeOverride && declaration.isInline && declaration.isExported) {
|
||||
generationState.inlineFunctionBodies.add(moduleDeserializer.buildInlineFunctionReference(declaration))
|
||||
trackCallees(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (hasEagerlyInitializedProperties)
|
||||
generationState.eagerInitializedFiles.add(moduleDeserializer.buildEagerInitializedFile(irFile))
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (declaration.parent == irFile
|
||||
&& declaration.hasAnnotation(KonanFqNames.eagerInitialization)
|
||||
) {
|
||||
hasEagerlyInitializedProperties = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (hasEagerlyInitializedProperties)
|
||||
generationState.eagerInitializedFiles.add(moduleDeserializer.buildEagerInitializedFile(irFile))
|
||||
|
||||
if (generationState.config.producePerFileCache && !irFile.isFunctionInterfaceFile)
|
||||
generationState.klibHash = SerializedIrFileFingerprint(moduleDeserializer.klib, moduleDeserializer.getKlibFileIndexOf(irFile)).fileFingerprint
|
||||
}
|
||||
}
|
||||
|
||||
private val IrDeclaration.isExported
|
||||
|
||||
+2
@@ -501,6 +501,8 @@ internal class KonanIrLinker(
|
||||
?: error("No file for $idSig")
|
||||
}
|
||||
|
||||
fun getKlibFileIndexOf(irFile: IrFile) = fileDeserializationStates.first { it.file == irFile }.fileIndex
|
||||
|
||||
fun buildInlineFunctionReference(irFunction: IrFunction): SerializedInlineFunctionReference {
|
||||
val signature = irFunction.symbol.signature
|
||||
?: error("No signature for ${irFunction.render()}")
|
||||
|
||||
Reference in New Issue
Block a user