From 6b61488099ba173d7ba8d0c30fa72e463f465dca Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 16 Dec 2021 16:11:40 +0100 Subject: [PATCH] Implement IC caches changes detection logic over frontend metadata --- .../kotlin/incremental/IncrementalJvmCache.kt | 78 ++++++++++++++++--- .../jvm/deserialization/JvmProtoBufUtil.kt | 8 +- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt index d1bcaac7036..51e065180cc 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.incremental -import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName import com.intellij.util.containers.CollectionFactory import com.intellij.util.io.BooleanDataDescriptor @@ -29,8 +28,11 @@ import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto +import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping +import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -53,6 +55,7 @@ open class IncrementalJvmCache( ), IncrementalCache { companion object { private val PROTO_MAP = "proto" + private val FE_PROTO_MAP = "fe-proto" private val CONSTANTS_MAP = "constants" private val PACKAGE_PARTS = "package-parts" private val MULTIFILE_CLASS_FACADES = "multifile-class-facades" @@ -68,6 +71,7 @@ open class IncrementalJvmCache( override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile)) private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile)) + private val feProtoMap = registerMap(ProtoMap(FE_PROTO_MAP.storageFile)) private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile)) private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile)) private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile)) @@ -193,6 +197,44 @@ open class IncrementalJvmCache( } } + fun saveFrontendClassToCache( + classId: ClassId, + classProto: ProtoBuf.Class, + stringTable: JvmStringTable, + sourceFiles: List?, + changesCollector: ChangesCollector + ) { + + val className = JvmClassName.byClassId(classId) + + if (sourceFiles != null) { + internalNameToSource[className.internalName] = sourceFiles + } + + if (classId.isLocal) return + + val newProtoData = ClassProtoData(classProto, stringTable.toNameResolver()) + addToClassStorage(newProtoData, sourceFiles?.let { sourceFiles.single() }) + + feProtoMap.putAndCollect( + className, + ProtoMapValue( + false, + JvmProtoBufUtil.writeDataBytes(stringTable, classProto), + stringTable.strings.toTypedArray() + ), + newProtoData, + changesCollector + ) + } + + fun collectClassChangesByFeMetadata( + className: JvmClassName, classProto: ProtoBuf.Class, stringTable: JvmStringTable, changesCollector: ChangesCollector + ) { + //class + feProtoMap.check(className, classProto, stringTable, changesCollector) + } + fun saveJavaClassProto(source: File?, serializedJavaClass: SerializedJavaClass, collector: ChangesCollector) { val jvmClassName = JvmClassName.byClassId(serializedJavaClass.classId) javaSourcesProtoMap.process(jvmClassName, serializedJavaClass, collector) @@ -243,6 +285,7 @@ open class IncrementalJvmCache( dirtyClasses.forEach { protoMap.remove(it, changesCollector) + feProtoMap.remove(it, changesCollector) packagePartMap.remove(it) multifileFacadeToParts.remove(it) partToMultifileFacade.remove(it) @@ -292,7 +335,12 @@ open class IncrementalJvmCache( @Synchronized fun process(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) { - return put(kotlinClassInfo, changesCollector) + return putAndCollect( + kotlinClassInfo.className, + kotlinClassInfo.protoMapValue, + kotlinClassInfo.protoData, + changesCollector + ) } // A module mapping (.kotlin_module file) is stored in a cache, @@ -308,14 +356,26 @@ open class IncrementalJvmCache( } @Synchronized - private fun put(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) { - val key = kotlinClassInfo.className.internalName - val oldData = storage[key] - val newData = kotlinClassInfo.protoMapValue - storage[key] = newData + fun putAndCollect( + className: JvmClassName, + newMapValue: ProtoMapValue, + newProtoData: ProtoData, + changesCollector: ChangesCollector + ) { + val key = className.internalName + val oldMapValue = storage[key] + storage[key] = newMapValue - val packageFqName = kotlinClassInfo.className.packageFqName - changesCollector.collectProtoChanges(oldData?.toProtoData(packageFqName), kotlinClassInfo.protoData, packageProtoKey = key) + changesCollector.collectProtoChanges(oldMapValue?.toProtoData(className.packageFqName), newProtoData, packageProtoKey = key) + } + + internal fun check( + className: JvmClassName, classProto: ProtoBuf.Class, stringTable: JvmStringTable, changesCollector: ChangesCollector + ) { + val key = className.internalName + val oldProtoData = storage[key]?.toProtoData(className.packageFqName) + val newProtoData = ClassProtoData(classProto, stringTable.toNameResolver()) + changesCollector.collectProtoChanges(oldProtoData, newProtoData, packageProtoKey = key) } operator fun contains(className: JvmClassName): Boolean = diff --git a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmProtoBufUtil.kt b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmProtoBufUtil.kt index efa08935eea..a492b89edd0 100644 --- a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmProtoBufUtil.kt +++ b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/JvmProtoBufUtil.kt @@ -56,10 +56,14 @@ object JvmProtoBufUtil { */ @JvmStatic fun writeData(message: MessageLite, stringTable: JvmStringTable): Array = - BitEncoding.encodeBytes(ByteArrayOutputStream().apply { + BitEncoding.encodeBytes(writeDataBytes(stringTable, message)) + + @JvmStatic + fun writeDataBytes(stringTable: JvmStringTable, message: MessageLite) = + ByteArrayOutputStream().apply { stringTable.serializeTo(this) message.writeTo(this) - }.toByteArray()) + }.toByteArray() // returns JVM signature in the format: "equals(Ljava/lang/Object;)Z" fun getJvmMethodSignature(