[JS IR] Refactor signature serializer in JS IR IC infra

This commit is contained in:
Alexander Korepanov
2023-05-08 16:39:47 +02:00
committed by Space Team
parent bb72a8bcb7
commit aef8ece123
2 changed files with 138 additions and 115 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.CodedInputStream
import org.jetbrains.kotlin.protobuf.CodedOutputStream import org.jetbrains.kotlin.protobuf.CodedOutputStream
internal class IdSignatureSerialization(private val library: KotlinLibraryHeader) {
private enum class IdSignatureProtoType(val id: Int) { private enum class IdSignatureProtoType(val id: Int) {
DECLARED_SIGNATURE(0), DECLARED_SIGNATURE(0),
COMMON_SIGNATURE(1), COMMON_SIGNATURE(1),
@@ -16,37 +17,53 @@ private enum class IdSignatureProtoType(val id: Int) {
ACCESSOR_SIGNATURE(3); ACCESSOR_SIGNATURE(3);
} }
internal fun CodedOutputStream.writeIdSignature(signature: IdSignature, signatureToIndexMapper: (IdSignature) -> Int?) { interface IdSignatureICSerializer {
val index = signatureToIndexMapper(signature) fun serializeIdSignature(out: CodedOutputStream, signature: IdSignature)
}
interface IdSignatureICDeserializer {
fun deserializeIdSignature(input: CodedInputStream): IdSignature
fun skipIdSignature(input: CodedInputStream)
}
inner class FileIdSignatureSerialization(srcFile: KotlinSourceFile) : IdSignatureICSerializer, IdSignatureICDeserializer {
private val deserializer by lazy {
library.sourceFileDeserializers[srcFile] ?: notFoundIcError("signature deserializer", library.libraryFile, srcFile)
}
internal val signatureToIndexMapping = hashMapOf<IdSignature, Int>()
override fun serializeIdSignature(out: CodedOutputStream, signature: IdSignature) {
val index = signatureToIndexMapping[signature]
if (index != null) { if (index != null) {
writeInt32NoTag(IdSignatureProtoType.DECLARED_SIGNATURE.id) out.writeInt32NoTag(IdSignatureProtoType.DECLARED_SIGNATURE.id)
writeInt32NoTag(index) out.writeInt32NoTag(index)
return return
} }
when (signature) { when (signature) {
is IdSignature.CommonSignature -> { is IdSignature.CommonSignature -> {
writeInt32NoTag(IdSignatureProtoType.COMMON_SIGNATURE.id) out.writeInt32NoTag(IdSignatureProtoType.COMMON_SIGNATURE.id)
writeStringNoTag(signature.packageFqName) out.writeStringNoTag(signature.packageFqName)
writeStringNoTag(signature.declarationFqName) out.writeStringNoTag(signature.declarationFqName)
val id = signature.id val id = signature.id
if (id != null) { if (id != null) {
writeBoolNoTag(true) out.writeBoolNoTag(true)
writeFixed64NoTag(id) out.writeFixed64NoTag(id)
} else { } else {
writeBoolNoTag(false) out.writeBoolNoTag(false)
} }
writeInt64NoTag(signature.mask) out.writeInt64NoTag(signature.mask)
} }
is IdSignature.CompositeSignature -> { is IdSignature.CompositeSignature -> {
writeInt32NoTag(IdSignatureProtoType.COMPOSITE_SIGNATURE.id) out.writeInt32NoTag(IdSignatureProtoType.COMPOSITE_SIGNATURE.id)
writeIdSignature(signature.container, signatureToIndexMapper) serializeIdSignature(out, signature.container)
writeIdSignature(signature.inner, signatureToIndexMapper) serializeIdSignature(out, signature.inner)
} }
is IdSignature.AccessorSignature -> { is IdSignature.AccessorSignature -> {
writeInt32NoTag(IdSignatureProtoType.ACCESSOR_SIGNATURE.id) out.writeInt32NoTag(IdSignatureProtoType.ACCESSOR_SIGNATURE.id)
writeIdSignature(signature.propertySignature, signatureToIndexMapper) serializeIdSignature(out, signature.propertySignature)
writeIdSignature(signature.accessorSignature, signatureToIndexMapper) serializeIdSignature(out, signature.accessorSignature)
} }
else -> { else -> {
icError("can not write $signature signature") icError("can not write $signature signature")
@@ -54,30 +71,33 @@ internal fun CodedOutputStream.writeIdSignature(signature: IdSignature, signatur
} }
} }
internal fun CodedInputStream.readIdSignature(indexToSignatureMapper: (Int) -> IdSignature): IdSignature { override fun deserializeIdSignature(input: CodedInputStream): IdSignature {
when (val signatureType = readInt32()) { when (val signatureType = input.readInt32()) {
IdSignatureProtoType.DECLARED_SIGNATURE.id -> { IdSignatureProtoType.DECLARED_SIGNATURE.id -> {
return indexToSignatureMapper(readInt32()) val index = input.readInt32()
val signature = deserializer.deserializeIdSignature(index)
signatureToIndexMapping[signature] = index
return signature
} }
IdSignatureProtoType.COMMON_SIGNATURE.id -> { IdSignatureProtoType.COMMON_SIGNATURE.id -> {
val packageFqName = readString() val packageFqName = input.readString()
val declarationFqName = readString() val declarationFqName = input.readString()
val id = if (readBool()) { val id = if (input.readBool()) {
readFixed64() input.readFixed64()
} else { } else {
null null
} }
val mask = readInt64() val mask = input.readInt64()
return IdSignature.CommonSignature(packageFqName, declarationFqName, id, mask) return IdSignature.CommonSignature(packageFqName, declarationFqName, id, mask)
} }
IdSignatureProtoType.COMPOSITE_SIGNATURE.id -> { IdSignatureProtoType.COMPOSITE_SIGNATURE.id -> {
val containerSignature = readIdSignature(indexToSignatureMapper) val containerSignature = deserializeIdSignature(input)
val innerSignature = readIdSignature(indexToSignatureMapper) val innerSignature = deserializeIdSignature(input)
return IdSignature.CompositeSignature(containerSignature, innerSignature) return IdSignature.CompositeSignature(containerSignature, innerSignature)
} }
IdSignatureProtoType.ACCESSOR_SIGNATURE.id -> { IdSignatureProtoType.ACCESSOR_SIGNATURE.id -> {
val propertySignature = readIdSignature(indexToSignatureMapper) val propertySignature = deserializeIdSignature(input)
val accessorSignature = readIdSignature(indexToSignatureMapper) val accessorSignature = deserializeIdSignature(input)
if (accessorSignature !is IdSignature.CommonSignature) { if (accessorSignature !is IdSignature.CommonSignature) {
icError("can not read accessor signature") icError("can not read accessor signature")
} }
@@ -89,29 +109,43 @@ internal fun CodedInputStream.readIdSignature(indexToSignatureMapper: (Int) -> I
} }
} }
internal fun CodedInputStream.skipIdSignature() { override fun skipIdSignature(input: CodedInputStream) {
when (val signatureType = readInt32()) { when (val signatureType = input.readInt32()) {
IdSignatureProtoType.DECLARED_SIGNATURE.id -> { IdSignatureProtoType.DECLARED_SIGNATURE.id -> {
readInt32() input.readInt32()
} }
IdSignatureProtoType.COMMON_SIGNATURE.id -> { IdSignatureProtoType.COMMON_SIGNATURE.id -> {
readString() input.readString()
readString() input.readString()
if (readBool()) { if (input.readBool()) {
readFixed64() input.readFixed64()
} }
readInt64() input.readInt64()
} }
IdSignatureProtoType.COMPOSITE_SIGNATURE.id -> { IdSignatureProtoType.COMPOSITE_SIGNATURE.id -> {
skipIdSignature() skipIdSignature(input)
skipIdSignature() skipIdSignature(input)
} }
IdSignatureProtoType.ACCESSOR_SIGNATURE.id -> { IdSignatureProtoType.ACCESSOR_SIGNATURE.id -> {
skipIdSignature() skipIdSignature(input)
skipIdSignature() skipIdSignature(input)
} }
else -> { else -> {
icError("can not skip signature type $signatureType") icError("can not skip signature type $signatureType")
} }
} }
} }
}
private val fileSerializers = hashMapOf<KotlinSourceFile, FileIdSignatureSerialization>()
fun getIdSignatureDeserializer(srcFile: KotlinSourceFile): IdSignatureICDeserializer {
return fileSerializers.getOrPut(srcFile) { FileIdSignatureSerialization(srcFile) }
}
fun getIdSignatureSerializer(srcFile: KotlinSourceFile, signatureToIndexMapping: Map<IdSignature, Int>): IdSignatureICSerializer {
return fileSerializers.getOrPut(srcFile) {
FileIdSignatureSerialization(srcFile)
}.also { it.signatureToIndexMapping.putAll(signatureToIndexMapping) }
}
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.ir.backend.js.ic package org.jetbrains.kotlin.ir.backend.js.ic
import org.jetbrains.kotlin.backend.common.serialization.IdSignatureDeserializer
import org.jetbrains.kotlin.backend.common.serialization.cityHash64 import org.jetbrains.kotlin.backend.common.serialization.cityHash64
import org.jetbrains.kotlin.backend.common.serialization.FingerprintHash import org.jetbrains.kotlin.backend.common.serialization.FingerprintHash
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
@@ -30,7 +29,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
private val kotlinLibrarySourceFileMetadata = hashMapOf<KotlinSourceFile, KotlinSourceFileMetadata>() private val kotlinLibrarySourceFileMetadata = hashMapOf<KotlinSourceFile, KotlinSourceFileMetadata>()
private val signatureToIndexMappingFromMetadata = hashMapOf<KotlinSourceFile, MutableMap<IdSignature, Int>>() private val idSignatureSerialization = IdSignatureSerialization(library)
private val cacheHeaderFromDisk by lazy(LazyThreadSafetyMode.NONE) { private val cacheHeaderFromDisk by lazy(LazyThreadSafetyMode.NONE) {
cacheHeaderFile.useCodedInputIfExists { cacheHeaderFile.useCodedInputIfExists {
@@ -148,16 +147,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
private fun fetchSourceFileMetadata(srcFile: KotlinSourceFile, loadSignatures: Boolean) = private fun fetchSourceFileMetadata(srcFile: KotlinSourceFile, loadSignatures: Boolean) =
kotlinLibrarySourceFileMetadata.getOrPut(srcFile) { kotlinLibrarySourceFileMetadata.getOrPut(srcFile) {
val signatureToIndexMapping = signatureToIndexMappingFromMetadata.getOrPut(srcFile) { hashMapOf() } val deserializer = idSignatureSerialization.getIdSignatureDeserializer(srcFile)
val deserializer: IdSignatureDeserializer by lazy(LazyThreadSafetyMode.NONE) {
library.sourceFileDeserializers[srcFile] ?: notFoundIcError("signature deserializer", library.libraryFile, srcFile)
}
fun CodedInputStream.deserializeIdSignatureAndSave() = readIdSignature { index ->
val signature = deserializer.deserializeIdSignature(index)
signatureToIndexMapping[signature] = index
signature
}
fun <T> CodedInputStream.readDependencies(signaturesReader: () -> T) = buildMapUntil(readInt32()) { fun <T> CodedInputStream.readDependencies(signaturesReader: () -> T) = buildMapUntil(readInt32()) {
val libFile = KotlinLibraryFile.fromProtoStream(this@readDependencies) val libFile = KotlinLibraryFile.fromProtoStream(this@readDependencies)
@@ -171,12 +161,12 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
fun CodedInputStream.readDirectDependencies() = readDependencies { fun CodedInputStream.readDirectDependencies() = readDependencies {
if (loadSignatures) { if (loadSignatures) {
buildMapUntil(readInt32()) { buildMapUntil(readInt32()) {
val signature = deserializeIdSignatureAndSave() val signature = deserializer.deserializeIdSignature(this@readDirectDependencies)
put(signature, ICHash.fromProtoStream(this@readDirectDependencies)) put(signature, ICHash.fromProtoStream(this@readDirectDependencies))
} }
} else { } else {
repeat(readInt32()) { repeat(readInt32()) {
skipIdSignature() deserializer.skipIdSignature(this@readDirectDependencies)
ICHash.fromProtoStream(this@readDirectDependencies) ICHash.fromProtoStream(this@readDirectDependencies)
} }
emptyMap() emptyMap()
@@ -185,9 +175,9 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
fun CodedInputStream.readInverseDependencies() = readDependencies { fun CodedInputStream.readInverseDependencies() = readDependencies {
if (loadSignatures) { if (loadSignatures) {
buildSetUntil(readInt32()) { add(deserializeIdSignatureAndSave()) } buildSetUntil(readInt32()) { add(deserializer.deserializeIdSignature(this@readInverseDependencies)) }
} else { } else {
repeat(readInt32()) { skipIdSignature() } repeat(readInt32()) { deserializer.skipIdSignature(this@readInverseDependencies) }
emptySet() emptySet()
} }
} }
@@ -204,9 +194,10 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
signatureToIndexMapping: Map<IdSignature, Int> signatureToIndexMapping: Map<IdSignature, Int>
): SourceFileCacheArtifact { ): SourceFileCacheArtifact {
val binaryAstFile = srcFile.getCacheFile(BINARY_AST_SUFFIX) val binaryAstFile = srcFile.getCacheFile(BINARY_AST_SUFFIX)
val headerCacheFile = srcFile.getCacheFile(METADATA_SUFFIX)
val sourceFileMetadata = kotlinLibrarySourceFileMetadata[srcFile] val sourceFileMetadata = kotlinLibrarySourceFileMetadata[srcFile]
?: return SourceFileCacheArtifact.DoNotChangeMetadata(srcFile, binaryAstFile) ?: return SourceFileCacheArtifact.DoNotChangeMetadata(srcFile, binaryAstFile)
val headerCacheFile = srcFile.getCacheFile(METADATA_SUFFIX)
if (sourceFileMetadata.isEmpty()) { if (sourceFileMetadata.isEmpty()) {
return SourceFileCacheArtifact.RemoveMetadata(srcFile, binaryAstFile, headerCacheFile) return SourceFileCacheArtifact.RemoveMetadata(srcFile, binaryAstFile, headerCacheFile)
} }
@@ -214,9 +205,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
return SourceFileCacheArtifact.DoNotChangeMetadata(srcFile, binaryAstFile) return SourceFileCacheArtifact.DoNotChangeMetadata(srcFile, binaryAstFile)
} }
val signatureToIndexMappingSaved = signatureToIndexMappingFromMetadata[srcFile] ?: emptyMap() val serializer = idSignatureSerialization.getIdSignatureSerializer(srcFile, signatureToIndexMapping)
fun CodedOutputStream.serializeIdSignature(signature: IdSignature) =
writeIdSignature(signature) { signatureToIndexMapping[it] ?: signatureToIndexMappingSaved[it] }
fun <T> CodedOutputStream.writeDependencies(depends: KotlinSourceFileMap<T>, signaturesWriter: (T) -> Unit) { fun <T> CodedOutputStream.writeDependencies(depends: KotlinSourceFileMap<T>, signaturesWriter: (T) -> Unit) {
writeInt32NoTag(depends.size) writeInt32NoTag(depends.size)
@@ -233,7 +222,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
fun CodedOutputStream.writeDirectDependencies(depends: KotlinSourceFileMap<Map<IdSignature, ICHash>>) = writeDependencies(depends) { fun CodedOutputStream.writeDirectDependencies(depends: KotlinSourceFileMap<Map<IdSignature, ICHash>>) = writeDependencies(depends) {
writeInt32NoTag(it.size) writeInt32NoTag(it.size)
for ((signature, hash) in it) { for ((signature, hash) in it) {
serializeIdSignature(signature) serializer.serializeIdSignature(this@writeDirectDependencies, signature)
hash.toProtoStream(this) hash.toProtoStream(this)
} }
} }
@@ -241,7 +230,7 @@ internal class IncrementalCache(private val library: KotlinLibraryHeader, val ca
fun CodedOutputStream.writeInverseDependencies(depends: KotlinSourceFileMap<Set<IdSignature>>) = writeDependencies(depends) { fun CodedOutputStream.writeInverseDependencies(depends: KotlinSourceFileMap<Set<IdSignature>>) = writeDependencies(depends) {
writeInt32NoTag(it.size) writeInt32NoTag(it.size)
for (signature in it) { for (signature in it) {
serializeIdSignature(signature) serializer.serializeIdSignature(this@writeInverseDependencies, signature)
} }
} }