Extract common caches

This commit is contained in:
Alexey Tsvetkov
2017-06-26 20:35:41 +03:00
parent 367b9f6664
commit 3ad5e78d77
10 changed files with 229 additions and 197 deletions
@@ -0,0 +1,117 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental
import com.intellij.util.io.EnumeratorStringDescriptor
import org.jetbrains.kotlin.incremental.storage.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.deserialization.supertypes
import java.io.File
/**
* Incremental cache common for JVM and JS
*/
open class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) {
companion object {
private val SUBTYPES = "subtypes"
private val SUPERTYPES = "supertypes"
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
}
private val dependents = arrayListOf<IncrementalCacheCommon>()
fun addDependentCache(cache: IncrementalCacheCommon) {
dependents.add(cache)
}
val thisWithDependentCaches: Iterable<IncrementalCacheCommon> by lazy {
val result = arrayListOf(this)
result.addAll(dependents)
result
}
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
fun getSubtypesOf(className: FqName): Sequence<FqName> =
subtypesMap[className].asSequence()
fun getSourceFileIfClass(fqName: FqName): File? =
classFqNameToSourceMap[fqName]
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
val parents = supertypes.map { nameResolver.getClassId(it.className).asSingleFqName() }
.filter { it.asString() != "kotlin.Any" }
.toSet()
val child = nameResolver.getClassId(proto.fqName).asSingleFqName()
parents.forEach { subtypesMap.add(it, child) }
val removedSupertypes = supertypesMap[child].filter { it !in parents }
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
supertypesMap[child] = parents
classFqNameToSourceMap[child] = srcFile
}
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>) {
if (removedClasses.isEmpty()) return
val removedFqNames = removedClasses.toSet()
for (cache in thisWithDependentCaches) {
val parentsFqNames = hashSetOf<FqName>()
val childrenFqNames = hashSetOf<FqName>()
for (removedFqName in removedFqNames) {
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
cache.supertypesMap.remove(removedFqName)
cache.subtypesMap.remove(removedFqName)
}
for (child in childrenFqNames) {
cache.supertypesMap.removeValues(child, removedFqNames)
}
for (parent in parentsFqNames) {
cache.subtypesMap.removeValues(parent, removedFqNames)
}
}
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
}
protected class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
operator fun set(fqName: FqName, sourceFile: File) {
storage[fqName.asString()] = sourceFile.canonicalPath
}
operator fun get(fqName: FqName): File? =
storage[fqName.asString()]?.let(::File)
fun remove(fqName: FqName) {
storage.remove(fqName.asString())
}
override fun dumpValue(value: String) = value
}
}
@@ -38,8 +38,6 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.Flags
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.deserialization.supertypes
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import org.jetbrains.org.objectweb.asm.*
@@ -53,7 +51,7 @@ open class IncrementalCacheImpl<Target>(
private val targetDataRoot: File,
targetOutputDir: File?,
target: Target
) : BasicMapsOwner(), IncrementalCache {
) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
companion object {
private val PROTO_MAP = "proto"
private val CONSTANTS_MAP = "constants"
@@ -63,19 +61,11 @@ open class IncrementalCacheImpl<Target>(
private val SOURCE_TO_CLASSES = "source-to-classes"
private val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
private val INLINE_FUNCTIONS = "inline-functions"
private val SUBTYPES = "subtypes"
private val SUPERTYPES = "supertypes"
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
}
private val baseDir = File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)
protected val String.storageFile: File
get() = File(baseDir, this + "." + CACHE_EXTENSION)
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
@@ -84,27 +74,13 @@ open class IncrementalCacheImpl<Target>(
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
private val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
// todo: try to use internal names only?
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
private val dependents = arrayListOf<IncrementalCacheImpl<Target>>()
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory: $target" } }
val thisWithDependentCaches: Iterable<IncrementalCacheImpl<Target>> by lazy {
val result = arrayListOf(this)
result.addAll(dependents)
result
}
protected open fun debugLog(message: String) {}
fun addDependentCache(cache: IncrementalCacheImpl<Target>) {
dependents.add(cache)
}
fun markOutputClassesDirty(removedAndCompiledSources: List<File>) {
for (sourceFile in removedAndCompiledSources) {
val classes = sourceToClassesMap[sourceFile]
@@ -121,12 +97,6 @@ open class IncrementalCacheImpl<Target>(
fun classesBySources(sources: Iterable<File>): Iterable<JvmClassName> =
sources.flatMap { sourceToClassesMap[it] }
fun getSubtypesOf(className: FqName): Sequence<FqName> =
subtypesMap[className].asSequence()
fun getSourceFileIfClass(fqName: FqName): File? =
classFqNameToSourceMap[fqName]
fun sourcesByInternalName(internalName: String): Collection<File> =
internalNameToSource[internalName]
@@ -310,7 +280,7 @@ open class IncrementalCacheImpl<Target>(
internalNameToSource.remove(it.internalName)
}
removeAllFromClassStorage(dirtyClasses)
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars })
dirtyOutputClassesMap.clean()
return changesInfo
@@ -555,22 +525,6 @@ open class IncrementalCacheImpl<Target>(
}
}
inner class ClassFqNameToSourceMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
operator fun set(fqName: FqName, sourceFile: File) {
storage[fqName.asString()] = sourceFile.canonicalPath
}
operator fun get(fqName: FqName): File? =
storage[fqName.asString()]?.let(::File)
fun remove(fqName: FqName) {
storage.remove(fqName.asString())
}
override fun dumpValue(value: String) = value
}
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
storage[internalName] = sourceFiles.map { it.canonicalPath }
@@ -588,49 +542,8 @@ open class IncrementalCacheImpl<Target>(
}
private fun addToClassStorage(kotlinClass: LocalFileKotlinClass, srcFile: File) {
val classData = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.data!!, kotlinClass.classHeader.strings!!)
val supertypes = classData.classProto.supertypes(TypeTable(classData.classProto.typeTable))
val parents = supertypes.map { classData.nameResolver.getClassId(it.className).asSingleFqName() }
.filter { it.asString() != "kotlin.Any" }
.toSet()
val child = kotlinClass.classId.asSingleFqName()
parents.forEach { subtypesMap.add(it, child) }
val removedSupertypes = supertypesMap[child].filter { it !in parents }
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
supertypesMap[child] = parents
classFqNameToSourceMap[kotlinClass.className.fqNameForClassNameWithoutDollars] = srcFile
}
private fun removeAllFromClassStorage(removedClasses: Collection<JvmClassName>) {
if (removedClasses.isEmpty()) return
val removedFqNames = removedClasses.map { it.fqNameForClassNameWithoutDollars }.toSet()
for (cache in thisWithDependentCaches) {
val parentsFqNames = hashSetOf<FqName>()
val childrenFqNames = hashSetOf<FqName>()
for (removedFqName in removedFqNames) {
parentsFqNames.addAll(cache.supertypesMap[removedFqName])
childrenFqNames.addAll(cache.subtypesMap[removedFqName])
cache.supertypesMap.remove(removedFqName)
cache.subtypesMap.remove(removedFqName)
}
for (child in childrenFqNames) {
cache.supertypesMap.removeValues(child, removedFqNames)
}
for (parent in parentsFqNames) {
cache.subtypesMap.removeValues(parent, removedFqNames)
}
}
removedFqNames.forEach { classFqNameToSourceMap.remove(it) }
val (nameResolver, proto) = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.data!!, kotlinClass.classHeader.strings!!)
addToClassStorage(proto, nameResolver, srcFile)
}
private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
@@ -29,15 +29,12 @@ import java.io.File
import java.util.*
open class LookupStorage(private val targetDataDir: File) : BasicMapsOwner() {
open class LookupStorage(targetDataDir: File) : BasicMapsOwner(targetDataDir) {
companion object {
private val DELETED_TO_SIZE_TRESHOLD = 0.5
private val MINIMUM_GARBAGE_COLLECTIBLE_SIZE = 10000
}
private val String.storageFile: File
get() = File(targetDataDir, this + "." + CACHE_EXTENSION)
private val countersFile = "counters".storageFile
private val idToFile = registerMap(IdToFileMap("id-to-file".storageFile))
private val fileToId = registerMap(FileToIdMap("file-to-id".storageFile))
@@ -187,8 +187,8 @@ data class DirtyData(
val dirtyClassesFqNames: Collection<FqName> = emptyList()
)
fun <Target> CompilationResult.getDirtyData(
caches: Iterable<IncrementalCacheImpl<Target>>,
fun CompilationResult.getDirtyData(
caches: Iterable<IncrementalCacheCommon>,
reporter: ICReporter
): DirtyData {
val dirtyLookupSymbols = HashSet<LookupSymbol>()
@@ -241,8 +241,8 @@ fun mapLookupSymbolsToFiles(
return dirtyFiles
}
fun <Target> mapClassesFqNamesToFiles(
caches: Iterable<IncrementalCacheImpl<Target>>,
fun mapClassesFqNamesToFiles(
caches: Iterable<IncrementalCacheCommon>,
classesFqNames: Iterable<FqName>,
reporter: ICReporter,
excludes: Set<File> = emptySet()
@@ -265,9 +265,9 @@ fun <Target> mapClassesFqNamesToFiles(
private fun findSrcDirRoot(file: File, roots: Iterable<File>): File? =
roots.firstOrNull { FileUtil.isAncestor(it, file, false) }
fun <Target> withSubtypes(
fun withSubtypes(
typeFqName: FqName,
caches: Iterable<IncrementalCacheImpl<Target>>
caches: Iterable<IncrementalCacheCommon>
): Set<FqName> {
val types = LinkedList(listOf(typeFqName))
val subtypes = hashSetOf<FqName>()
@@ -17,14 +17,18 @@
package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.annotations.TestOnly
import java.io.File
open class BasicMapsOwner {
open class BasicMapsOwner(private val baseDir: File) {
private val maps = arrayListOf<BasicMap<*, *>>()
companion object {
val CACHE_EXTENSION = "tab"
}
protected val String.storageFile: File
get() = File(baseDir, this + "." + CACHE_EXTENSION)
protected fun <K, V, M : BasicMap<K, V>> registerMap(map: M): M {
maps.add(map)
return map
@@ -87,7 +87,7 @@ class LazyStorage<K, V>(
try {
storage?.close()
}
catch (ignored: IOException) {
catch (ignored: Throwable) {
}
PersistentHashMap.deleteFilesStartingWith(storageFile)
@@ -16,59 +16,64 @@
package org.jetbrains.kotlin.incremental
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.modules.TargetId
import java.io.File
class IncrementalCachesManager (
private val targetId: TargetId,
private val cacheDirectory: File,
private val outputDir: File,
private val reporter: ICReporter
abstract class IncrementalCachesManager (
protected val cachesRootDir: File,
protected val reporter: ICReporter
) {
private val incrementalCacheDir = File(cacheDirectory, "increCache.${targetId.name}")
private val lookupCacheDir = File(cacheDirectory, "lookups")
private var incrementalCacheField: GradleIncrementalCacheImpl? = null
private var lookupCacheField: LookupStorage? = null
private val caches = arrayListOf<BasicMapsOwner>()
protected fun <T : BasicMapsOwner> T.registerCache() {
caches.add(this)
}
val incrementalCache: GradleIncrementalCacheImpl
get() {
if (incrementalCacheField == null) {
val targetDataRoot = incrementalCacheDir.apply { mkdirs() }
incrementalCacheField = GradleIncrementalCacheImpl(targetDataRoot, outputDir, targetId, reporter)
}
private val inputSnapshotsCacheDir = File(cachesRootDir, "inputs").apply { mkdirs() }
private val lookupCacheDir = File(cachesRootDir, "lookups").apply { mkdirs() }
return incrementalCacheField!!
}
val lookupCache: LookupStorage
get() {
if (lookupCacheField == null) {
lookupCacheField = LookupStorage(lookupCacheDir.apply { mkdirs() })
}
return lookupCacheField!!
}
val inputsCache: InputsCache = InputsCache(inputSnapshotsCacheDir, reporter).apply { registerCache() }
val lookupCache: LookupStorage = LookupStorage(lookupCacheDir).apply { registerCache() }
fun clean() {
close(flush = false)
cacheDirectory.deleteRecursively()
caches.forEach { it.clean() }
cachesRootDir.deleteRecursively()
}
fun close(flush: Boolean = false) {
incrementalCacheField?.let {
fun close(flush: Boolean = false): Boolean {
var successful = true
for (cache in caches) {
if (flush) {
it.flush(false)
try {
cache.flush(false)
}
catch (e: Throwable) {
successful = false
reporter.report { "Exception when flushing cache ${cache.javaClass}: $e" }
}
}
try {
cache.close()
}
catch (e: Throwable) {
successful = false
reporter.report { "Exception when closing cache ${cache.javaClass}: $e" }
}
it.close()
incrementalCacheField = null
}
lookupCacheField?.let {
if (flush) {
it.flush(false)
}
it.close()
lookupCacheField = null
}
return successful
}
}
class IncrementalJvmCachesManager(
targetId: TargetId,
cacheDirectory: File,
outputDir: File,
reporter: ICReporter
) : IncrementalCachesManager(cacheDirectory, reporter) {
private val jvmCacheFile = File(cacheDirectory, "jvm").apply { mkdirs() }
val jvmCache = IncrementalCacheImpl(jvmCacheFile, outputDir, targetId).apply { registerCache() }
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.incremental
import com.intellij.util.io.PersistentEnumeratorBase
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
@@ -40,7 +39,6 @@ import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.File
import java.io.IOException
import java.util.*
fun makeIncrementally(
@@ -64,7 +62,7 @@ fun makeIncrementally(
sourceRoots.map { JvmSourceRoot(it, null) }.toSet(),
versions, reporter)
compiler.compile(kotlinFiles, args, messageCollector) {
it.incrementalCache.sourceSnapshotMap.compareAndUpdate(sourceFiles)
it.inputsCache.sourceSnapshotMap.compareAndUpdate(sourceFiles)
}
}
}
@@ -107,16 +105,15 @@ class IncrementalJvmCompilerRunner(
getChangedFiles: (IncrementalCachesManager)->ChangedFiles
): ExitCode {
val targetId = TargetId(name = args.moduleName!!, type = "java-production")
var caches = IncrementalCachesManager(targetId, cacheDirectory, File(args.destination), reporter)
var caches = IncrementalJvmCachesManager(targetId, cacheDirectory, File(args.destination), reporter)
fun onError(e: Exception): ExitCode {
fun rebuild(): ExitCode {
caches.clean()
dirtySourcesSinceLastTimeFile.delete()
args.destinationAsFile.deleteRecursively()
// todo: warn?
reporter.report { "Possible cache corruption. Rebuilding. $e" }
// try to rebuild
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
caches = IncrementalCachesManager(targetId, cacheDirectory, args.destinationAsFile, reporter)
caches = IncrementalJvmCachesManager(targetId, cacheDirectory, args.destinationAsFile, reporter)
return compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, CompilationMode.Rebuild, messageCollector)
}
@@ -124,17 +121,24 @@ class IncrementalJvmCompilerRunner(
val javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
val changedFiles = getChangedFiles(caches)
val compilationMode = calculateSourcesToCompile(javaFilesProcessor, caches, changedFiles, args)
compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, compilationMode, messageCollector)
val exitCode = when (compilationMode) {
is CompilationMode.Incremental -> {
compileIncrementally(args, caches, javaFilesProcessor, allKotlinSources, targetId, compilationMode, messageCollector)
}
is CompilationMode.Rebuild -> {
rebuild()
}
}
if (!caches.close(flush = true)) throw RuntimeException("Could not flush caches")
return exitCode
}
catch (e: PersistentEnumeratorBase.CorruptedException) {
onError(e)
}
catch (e: IOException) {
onError(e)
}
finally {
caches.close(flush = true)
reporter.report { "flushed incremental caches" }
catch (e: Exception) {
// todo: warn?
reporter.report { "Possible cache corruption. Rebuilding. $e" }
rebuild()
}
}
@@ -147,15 +151,12 @@ class IncrementalJvmCompilerRunner(
private fun calculateSourcesToCompile(
javaFilesProcessor: ChangedJavaFilesProcessor,
caches: IncrementalCachesManager,
caches: IncrementalJvmCachesManager,
changedFiles: ChangedFiles,
args: K2JVMCompilerArguments
): CompilationMode {
fun rebuild(reason: ()->String): CompilationMode {
reporter.report {"Non-incremental compilation will be performed: ${reason()}"}
caches.clean()
dirtySourcesSinceLastTimeFile.delete()
args.destinationAsFile.deleteRecursively()
return CompilationMode.Rebuild
}
@@ -196,9 +197,9 @@ class IncrementalJvmCompilerRunner(
dirtyFiles.addAll(dirtyFilesFromLookups)
}
val dirtyClassesFqNames = classpathChanges.fqNames.flatMap {withSubtypes(it, listOf(caches.incrementalCache))}
val dirtyClassesFqNames = classpathChanges.fqNames.flatMap { withSubtypes(it, listOf(caches.jvmCache)) }
if (dirtyClassesFqNames.any()) {
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.incrementalCache), dirtyClassesFqNames, reporter)
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.jvmCache), dirtyClassesFqNames, reporter)
dirtyFiles.addAll(dirtyFilesFromFqNames)
}
@@ -250,7 +251,7 @@ class IncrementalJvmCompilerRunner(
private fun compileIncrementally(
args: K2JVMCompilerArguments,
caches: IncrementalCachesManager,
caches: IncrementalJvmCachesManager,
javaFilesProcessor: ChangedJavaFilesProcessor,
allKotlinSources: List<File>,
targetId: TargetId,
@@ -283,9 +284,9 @@ class IncrementalJvmCompilerRunner(
var exitCode = ExitCode.OK
while (dirtySources.any()) {
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
val outdatedClasses = caches.incrementalCache.classesBySources(dirtySources)
caches.incrementalCache.markOutputClassesDirty(dirtySources)
caches.incrementalCache.removeOutputForSourceFiles(dirtySources)
val outdatedClasses = caches.jvmCache.classesBySources(dirtySources)
caches.jvmCache.markOutputClassesDirty(dirtySources)
caches.inputsCache.removeOutputForSourceFiles(dirtySources)
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
@@ -295,7 +296,7 @@ class IncrementalJvmCompilerRunner(
val text = allSourcesToCompile.joinToString(separator = System.getProperty("line.separator")) { it.canonicalPath }
dirtySourcesSinceLastTimeFile.writeText(text)
val compilerOutput = compileChanged(listOf(targetId), sourcesToCompile.toSet(), args, { caches.incrementalCache }, lookupTracker, messageCollector)
val compilerOutput = compileChanged(listOf(targetId), sourcesToCompile.toSet(), args, caches.jvmCache, lookupTracker, messageCollector)
exitCode = compilerOutput.exitCode
val generatedFiles = compilerOutput.generatedFiles
anyClassesCompiled = anyClassesCompiled || generatedFiles.isNotEmpty() || removedKotlinSources.isNotEmpty()
@@ -310,7 +311,7 @@ class IncrementalJvmCompilerRunner(
if (compilationMode is CompilationMode.Incremental) {
val dirtySourcesSet = dirtySources.toHashSet()
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedFiles).filter { it !in dirtySourcesSet }
val additionalDirtyFiles = additionalDirtyFiles(caches.jvmCache, generatedFiles).filter { it !in dirtySourcesSet }
if (additionalDirtyFiles.isNotEmpty()) {
dirtySources.addAll(additionalDirtyFiles)
continue
@@ -318,10 +319,10 @@ class IncrementalJvmCompilerRunner(
}
allGeneratedFiles.addAll(generatedFiles)
caches.incrementalCache.registerOutputForSourceFiles(generatedFiles)
caches.inputsCache.registerOutputForSourceFiles(generatedFiles)
val compilationResult = updateIncrementalCaches(listOf(targetId), generatedFiles,
compiledWithErrors = exitCode != ExitCode.OK,
getIncrementalCache = { caches.incrementalCache })
getIncrementalCache = { caches.jvmCache })
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
@@ -329,13 +330,13 @@ class IncrementalJvmCompilerRunner(
break
}
val (dirtyLookupSymbols, dirtyClassFqNames) = compilationResult.getDirtyData(listOf(caches.incrementalCache), reporter)
val (dirtyLookupSymbols, dirtyClassFqNames) = compilationResult.getDirtyData(listOf(caches.jvmCache), reporter)
val compiledInThisIterationSet = sourcesToCompile.toHashSet()
with (dirtySources) {
clear()
addAll(mapLookupSymbolsToFiles(caches.lookupCache, dirtyLookupSymbols, reporter, excludes = compiledInThisIterationSet))
addAll(mapClassesFqNamesToFiles(listOf(caches.incrementalCache), dirtyClassFqNames, reporter, excludes = compiledInThisIterationSet))
addAll(mapClassesFqNamesToFiles(listOf(caches.jvmCache), dirtyClassFqNames, reporter, excludes = compiledInThisIterationSet))
}
buildDirtyLookupSymbols.addAll(dirtyLookupSymbols)
@@ -364,14 +365,14 @@ class IncrementalJvmCompilerRunner(
}
private fun additionalDirtyFiles(
caches: IncrementalCachesManager,
cache: IncrementalCacheImpl<TargetId>,
generatedFiles: List<GeneratedFile<TargetId>>
): Collection<File> {
val result = HashSet<File>()
fun partsByFacadeName(facadeInternalName: String): List<File> {
val parts = caches.incrementalCache.getStableMultifileFacadeParts(facadeInternalName) ?: emptyList()
return parts.flatMap { caches.incrementalCache.sourcesByInternalName(it) }
val parts = cache.getStableMultifileFacadeParts(facadeInternalName) ?: emptyList()
return parts.flatMap { cache.sourcesByInternalName(it) }
}
for (generatedFile in generatedFiles) {
@@ -382,7 +383,7 @@ class IncrementalJvmCompilerRunner(
when (outputClass.classHeader.kind) {
KotlinClassHeader.Kind.CLASS -> {
val fqName = outputClass.className.fqNameForClassNameWithoutDollars
val cachedSourceFile = caches.incrementalCache.getSourceFileIfClass(fqName)
val cachedSourceFile = cache.getSourceFileIfClass(fqName)
if (cachedSourceFile != null) {
result.add(cachedSourceFile)
@@ -405,7 +406,7 @@ class IncrementalJvmCompilerRunner(
targets: List<TargetId>,
sourcesToCompile: Set<File>,
args: K2JVMCompilerArguments,
getIncrementalCache: (TargetId)->GradleIncrementalCacheImpl,
cache: IncrementalCacheImpl<TargetId>,
lookupTracker: LookupTracker,
messageCollector: MessageCollector
): CompileChangedResults {
@@ -428,7 +429,7 @@ class IncrementalJvmCompilerRunner(
val messageCollector = MessageCollectorWrapper(messageCollector, outputItemCollector)
try {
val incrementalCaches = makeIncrementalCachesMap(targets, { listOf<TargetId>() }, getIncrementalCache, { this })
val incrementalCaches = makeIncrementalCachesMap(targets, { listOf<TargetId>() }, { cache }, { this })
val compilationCanceledStatus = object : CompilationCanceledStatus {
override fun checkCanceled() {
}
@@ -19,18 +19,17 @@ package org.jetbrains.kotlin.incremental
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
import org.jetbrains.kotlin.incremental.storage.StringCollectionExternalizer
import org.jetbrains.kotlin.modules.TargetId
import java.io.File
class GradleIncrementalCacheImpl(
targetDataRoot: File,
targetOutputDir: File?,
target: TargetId,
class InputsCache(
workingDir: File,
private val reporter: ICReporter
) : IncrementalCacheImpl<TargetId>(targetDataRoot, targetOutputDir, target) {
) : BasicMapsOwner(workingDir) {
companion object {
private val SOURCE_TO_OUTPUT_FILES = "source-to-output"
private val SOURCE_SNAPSHOTS = "source-snapshot"
@@ -29,15 +29,14 @@ import java.io.File
/**
* "Global" cache holder. Should be created once per root project.
*/
internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner(), ArtifactDifferenceRegistryProvider {
internal class BuildCacheStorage(private val workingDir: File) : BasicMapsOwner(workingDir), ArtifactDifferenceRegistryProvider {
companion object {
private val OWN_VERSION = 0
private val ARTIFACT_DIFFERENCE = "artifact-difference"
}
private val log = Logging.getLogger(this.javaClass)
private val cachesDir: File = File(workingDir, "caches").apply { mkdirs() }
private val versionFile = File(cachesDir, "version.txt")
private val versionFile = File(workingDir, "version.txt")
private val version = CacheVersion(
OWN_VERSION,
versionFile,
@@ -50,9 +49,6 @@ internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner(), ArtifactD
@Volatile
private var artifactDifferenceRegistry: ArtifactDifferenceRegistryImpl? = null
private val String.storageFile: File
get() = File(cachesDir, this + "." + CACHE_EXTENSION)
@Synchronized
override fun <T> withRegistry(report: (String)->Unit, fn: (ArtifactDifferenceRegistry)->T): T? {
try {
@@ -95,8 +91,8 @@ internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner(), ArtifactD
log.kotlinDebug { "Exception while closing caches: ${e.stackTraceStr}" }
}
cachesDir.deleteRecursively()
cachesDir.mkdirs()
workingDir.deleteRecursively()
workingDir.mkdirs()
versionFile.delete()
}