Rebuilding dependants fully only when constants/inline functions changed. This is not 100% precise, but it is faster. It is a compromise until we implement preciser incremental compilation.

Original commit: c60797e306
This commit is contained in:
Evgeny Gerashchenko
2014-11-28 16:25:06 +03:00
parent 41522a3b65
commit fadeb20c5c
3 changed files with 43 additions and 16 deletions
@@ -54,9 +54,12 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.jps.model.JpsProject
import java.io.FileFilter
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.*
import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem
import org.jetbrains.kotlin.utils.LibraryUtils
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
import org.jetbrains.jps.incremental.fs.CompilationRound
public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
class object {
@@ -133,7 +136,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
val recompilationDecision: IncrementalCacheImpl.RecompilationDecision
if (JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
recompilationDecision = DO_NOTHING
}
else {
recompilationDecision = updateKotlinIncrementalCache(compilationErrors, dirtyFilesHolder, incrementalCaches, outputsItemsAndTargets)
@@ -149,15 +152,21 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
}
if (IncrementalCompilation.ENABLED) {
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL) {
allCompiledFiles.clear()
val targetsCompletelyMarkedDirty = FSOperations.getTargetsCompletelyMarkedDirty(context)
FSOperations.markDirtyRecursively(context, chunk)
val fileFilter = FileFilter { file ->
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
}
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.COMPILE_OTHERS) {
FSOperations.markDirtyRecursively(context, chunk, { file ->
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
})
when (recompilationDecision) {
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS -> {
allCompiledFiles.clear()
FSOperations.markDirtyRecursively(context, chunk)
}
RECOMPILE_OTHERS_WITH_DEPENDANTS -> {
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, fileFilter)
}
RECOMPILE_OTHERS_IN_CHUNK -> {
FSOperations.markDirty(context, chunk, fileFilter)
}
}
return ADDITIONAL_PASS_REQUIRED
}
@@ -254,7 +263,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
outputsItemsAndTargets: List<Pair<SimpleOutputItem, ModuleBuildTarget>>
): IncrementalCacheImpl.RecompilationDecision {
if (!IncrementalCompilation.ENABLED) {
return IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
return DO_NOTHING
}
for ((target, cache) in incrementalCaches) {
@@ -265,7 +274,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
)
}
var recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
var recompilationDecision = DO_NOTHING
for ((outputItem, target) in outputsItemsAndTargets) {
val newDecision = incrementalCaches[target]!!.saveFileToCache(outputItem.getSourceFiles(), outputItem.getOutputFile())
recompilationDecision = recompilationDecision.merge(newDecision)
@@ -113,26 +113,38 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
val data = BitEncoding.decodeBytes(annotationDataEncoded)
when {
header.isCompatiblePackageFacadeKind() -> {
return if (protoMap.put(className, data)) COMPILE_OTHERS else DO_NOTHING
return if (protoMap.put(className, data)) RECOMPILE_OTHERS_IN_CHUNK else DO_NOTHING
}
header.isCompatibleClassKind() -> {
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
val protoChanged = protoMap.put(className, data)
val constantsChanged = constantsMap.process(className, fileBytes)
return if (inlinesChanged) RECOMPILE_ALL else if (protoChanged || constantsChanged) COMPILE_OTHERS else DO_NOTHING
return when {
inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS
protoChanged -> RECOMPILE_OTHERS_IN_CHUNK
else -> DO_NOTHING
}
}
else -> {
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
}
}
}
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
packagePartMap.putPackagePartSourceData(sourceFiles.first(), className)
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
val constantsChanged = constantsMap.process(className, fileBytes)
return if (inlinesChanged) RECOMPILE_ALL else if (constantsChanged) COMPILE_OTHERS else DO_NOTHING
return when {
inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS
else -> DO_NOTHING
}
}
return DO_NOTHING
@@ -497,8 +509,9 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
enum class RecompilationDecision {
DO_NOTHING
COMPILE_OTHERS
RECOMPILE_ALL
RECOMPILE_OTHERS_IN_CHUNK
RECOMPILE_OTHERS_WITH_DEPENDANTS
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
fun merge(other: RecompilationDecision): RecompilationDecision {
return if (other.ordinal() > this.ordinal()) other else this
@@ -0,0 +1,5 @@
package c
fun c() {
// This file doesn't use anything from module1, so it won't be recompiled after change
}