Implement IC caches changes detection logic over frontend metadata

This commit is contained in:
Ilya Chernikov
2021-12-16 16:11:40 +01:00
committed by teamcity
parent 3ca4fe5f9e
commit 6b61488099
2 changed files with 75 additions and 11 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.incremental package org.jetbrains.kotlin.incremental
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
import com.intellij.util.containers.CollectionFactory import com.intellij.util.containers.CollectionFactory
import com.intellij.util.io.BooleanDataDescriptor 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.header.KotlinClassHeader
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto 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.BitEncoding
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping 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.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -53,6 +55,7 @@ open class IncrementalJvmCache(
), IncrementalCache { ), IncrementalCache {
companion object { companion object {
private val PROTO_MAP = "proto" private val PROTO_MAP = "proto"
private val FE_PROTO_MAP = "fe-proto"
private val CONSTANTS_MAP = "constants" private val CONSTANTS_MAP = "constants"
private val PACKAGE_PARTS = "package-parts" private val PACKAGE_PARTS = "package-parts"
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades" private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
@@ -68,6 +71,7 @@ open class IncrementalJvmCache(
override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile)) override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
private val protoMap = registerMap(ProtoMap(PROTO_MAP.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 constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile)) private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.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<File>?,
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) { fun saveJavaClassProto(source: File?, serializedJavaClass: SerializedJavaClass, collector: ChangesCollector) {
val jvmClassName = JvmClassName.byClassId(serializedJavaClass.classId) val jvmClassName = JvmClassName.byClassId(serializedJavaClass.classId)
javaSourcesProtoMap.process(jvmClassName, serializedJavaClass, collector) javaSourcesProtoMap.process(jvmClassName, serializedJavaClass, collector)
@@ -243,6 +285,7 @@ open class IncrementalJvmCache(
dirtyClasses.forEach { dirtyClasses.forEach {
protoMap.remove(it, changesCollector) protoMap.remove(it, changesCollector)
feProtoMap.remove(it, changesCollector)
packagePartMap.remove(it) packagePartMap.remove(it)
multifileFacadeToParts.remove(it) multifileFacadeToParts.remove(it)
partToMultifileFacade.remove(it) partToMultifileFacade.remove(it)
@@ -292,7 +335,12 @@ open class IncrementalJvmCache(
@Synchronized @Synchronized
fun process(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) { 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, // A module mapping (.kotlin_module file) is stored in a cache,
@@ -308,14 +356,26 @@ open class IncrementalJvmCache(
} }
@Synchronized @Synchronized
private fun put(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) { fun putAndCollect(
val key = kotlinClassInfo.className.internalName className: JvmClassName,
val oldData = storage[key] newMapValue: ProtoMapValue,
val newData = kotlinClassInfo.protoMapValue newProtoData: ProtoData,
storage[key] = newData changesCollector: ChangesCollector
) {
val key = className.internalName
val oldMapValue = storage[key]
storage[key] = newMapValue
val packageFqName = kotlinClassInfo.className.packageFqName changesCollector.collectProtoChanges(oldMapValue?.toProtoData(className.packageFqName), newProtoData, packageProtoKey = key)
changesCollector.collectProtoChanges(oldData?.toProtoData(packageFqName), kotlinClassInfo.protoData, 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 = operator fun contains(className: JvmClassName): Boolean =
@@ -56,10 +56,14 @@ object JvmProtoBufUtil {
*/ */
@JvmStatic @JvmStatic
fun writeData(message: MessageLite, stringTable: JvmStringTable): Array<String> = fun writeData(message: MessageLite, stringTable: JvmStringTable): Array<String> =
BitEncoding.encodeBytes(ByteArrayOutputStream().apply { BitEncoding.encodeBytes(writeDataBytes(stringTable, message))
@JvmStatic
fun writeDataBytes(stringTable: JvmStringTable, message: MessageLite) =
ByteArrayOutputStream().apply {
stringTable.serializeTo(this) stringTable.serializeTo(this)
message.writeTo(this) message.writeTo(this)
}.toByteArray()) }.toByteArray()
// returns JVM signature in the format: "equals(Ljava/lang/Object;)Z" // returns JVM signature in the format: "equals(Ljava/lang/Object;)Z"
fun getJvmMethodSignature( fun getJvmMethodSignature(