IncrementalCacheImpl: do not recompile other files if all changes are private

Original commit: b3659486d9
This commit is contained in:
Michael Nedzelsky
2015-07-23 00:00:01 +03:00
parent d41a3e205c
commit 010d721b38
@@ -25,6 +25,7 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager
import org.jetbrains.jps.incremental.storage.PathStringDescriptor
import org.jetbrains.jps.incremental.storage.StorageOwner
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.jps.build.KotlinBuilder
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS
@@ -38,7 +39,11 @@ import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import org.jetbrains.kotlin.serialization.deserialization.visibility
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.org.objectweb.asm.*
import java.io.*
@@ -150,14 +155,14 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
val decision = when {
header.isCompatiblePackageFacadeKind() ->
getRecompilationDecision(
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!)),
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!), isPackage = true),
constantsChanged = false,
inlinesChanged = false
)
header.isCompatibleClassKind() ->
when (header.classKind!!) {
JvmAnnotationNames.KotlinClass.Kind.CLASS -> getRecompilationDecision(
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!)),
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!), isPackage = false),
constantsChanged = constantsMap.process(className, fileBytes),
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
)
@@ -299,13 +304,18 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
ByteArrayExternalizer
)
public fun put(className: JvmClassName, data: ByteArray): Boolean {
public fun put(className: JvmClassName, data: ByteArray, isPackage: Boolean): Boolean {
val key = className.getInternalName()
val oldData = storage[key]
if (Arrays.equals(data, oldData)) {
return false
}
storage.put(key, data)
if (oldData != null && isOpenPartNotChanged(oldData, data, isPackage)) {
return false
}
return true
}
@@ -320,6 +330,53 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
override fun dumpValue(value: ByteArray): String {
return java.lang.Long.toHexString(value.md5())
}
private fun isOpenPartNotChanged(oldData: ByteArray, newData: ByteArray, isPackageFacade: Boolean): Boolean {
if (isPackageFacade) {
return isPackageFacadeOpenPartNotChanged(oldData, newData)
}
else {
return isClassOpenPartNotChanged(oldData, newData)
}
}
private fun isPackageFacadeOpenPartNotChanged(oldData: ByteArray, newData: ByteArray): Boolean {
val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData)
val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData)
val compareObject = ProtoCompareGenerated(oldPackageData.nameResolver, newPackageData.nameResolver)
return compareObject.checkEquals(oldPackageData.packageProto, newPackageData.packageProto)
}
private fun isClassOpenPartNotChanged(oldData: ByteArray, newData: ByteArray): Boolean {
val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData)
val newClassData = JvmProtoBufUtil.readClassDataFrom(newData)
val compareObject = object : ProtoCompareGenerated(oldClassData.nameResolver, newClassData.nameResolver) {
override fun checkEqualsClassMember(old: ProtoBuf.Class, new: ProtoBuf.Class): Boolean =
checkEquals(old.memberList, new.memberList)
override fun checkEqualsClassSecondaryConstructor(old: ProtoBuf.Class, new: ProtoBuf.Class): Boolean =
checkEquals(old.secondaryConstructorList, new.secondaryConstructorList)
private fun checkEquals(oldList: List<ProtoBuf.Callable>, newList: List<ProtoBuf.Callable>): Boolean {
val oldListFiltered = oldList.filter { !it.isPrivate() }
val newListFiltered = newList.filter { !it.isPrivate() }
if (oldListFiltered.size() != newListFiltered.size()) return false
for (i in oldListFiltered.indices) {
if (!checkEquals(oldListFiltered[i], newListFiltered[i])) return false
}
return true
}
private fun ProtoBuf.Callable.isPrivate(): Boolean = Visibilities.isPrivate(visibility(Flags.VISIBILITY.get(flags)))
}
return compareObject.checkEquals(oldClassData.classProto, newClassData.classProto)
}
}
private inner class ConstantsMap : BasicMap<Map<String, Any>>() {