Inline function changed – rebuild all chunk.

Original commit: aa9f7a73c9
This commit is contained in:
Evgeny Gerashchenko
2014-07-01 22:38:35 +04:00
parent 9d428dc2ed
commit 2f72958d25
9 changed files with 91 additions and 18 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.jet.jps.build;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
@@ -237,7 +236,7 @@ public class KotlinBuilder extends ModuleLevelBuilder {
}
cache.clearCacheForRemovedFiles(moduleIdsAndFiles, outDirectories);
boolean significantChanges = false;
IncrementalCacheImpl.RecompilationDecision recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING;
for (SimpleOutputItem outputItem : outputItemCollector.getOutputs()) {
BuildTarget<?> target = null;
@@ -253,17 +252,20 @@ public class KotlinBuilder extends ModuleLevelBuilder {
File outputFile = outputItem.getOutputFile();
if (IncrementalCompilation.ENABLED) {
if (cache.saveFileToCache(target.getId(), sourceFiles, outputFile)) {
significantChanges = true;
}
IncrementalCacheImpl.RecompilationDecision newDecision = cache.saveFileToCache(target.getId(), sourceFiles, outputFile);
recompilationDecision = recompilationDecision.merge(newDecision);
}
outputConsumer.registerOutputFile(target, outputFile, paths(sourceFiles));
}
if (IncrementalCompilation.ENABLED) {
// TODO should mark dependencies as dirty, as well
if (significantChanges) {
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL) {
allCompiledFiles.clear();
return ExitCode.CHUNK_REBUILD_REQUIRED;
}
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.COMPILE_OTHERS) {
// TODO should mark dependencies as dirty, as well
FSOperations.markDirty(context, chunk, new FileFilter() {
@Override
public boolean accept(@NotNull File file) {
@@ -16,6 +16,7 @@
package org.jetbrains.jet.jps.incremental
import org.jetbrains.jet.jps.incremental.IncrementalCacheImpl.RecompilationDecision.*
import java.io.File
import com.intellij.util.io.PersistentHashMap
import java.io.DataOutput
@@ -56,10 +57,10 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
private val inlineFunctionsMap = InlineFunctionsMap()
private val packagePartMap = PackagePartMap()
public fun saveFileToCache(moduleId: String, sourceFiles: Collection<File>, classFile: File): Boolean {
public fun saveFileToCache(moduleId: String, sourceFiles: Collection<File>, classFile: File): RecompilationDecision {
val fileBytes = classFile.readBytes()
val classNameAndHeader = VirtualFileKotlinClass.readClassNameAndHeader(fileBytes)
if (classNameAndHeader == null) return false
if (classNameAndHeader == null) return RecompilationDecision.DO_NOTHING
val (className, header) = classNameAndHeader
val annotationDataEncoded = header.annotationData
@@ -67,10 +68,13 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
val data = BitEncoding.decodeBytes(annotationDataEncoded)
when (header.kind) {
KotlinClassHeader.Kind.PACKAGE_FACADE -> {
return protoMap.put(moduleId, className, data)
return if (protoMap.put(moduleId, className, data)) COMPILE_OTHERS else DO_NOTHING
}
KotlinClassHeader.Kind.CLASS -> {
return inlineFunctionsMap.process(moduleId, sourceFiles.first(), fileBytes) or protoMap.put(moduleId, className, data)
val inlinesChanged = inlineFunctionsMap.process(moduleId, sourceFiles.first(), fileBytes)
val protoChanged = protoMap.put(moduleId, className, data)
return if (inlinesChanged) RECOMPILE_ALL else if (protoChanged) COMPILE_OTHERS else DO_NOTHING
}
else -> {
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}")
@@ -80,10 +84,12 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
packagePartMap.putPackagePartSourceData(moduleId, sourceFiles.first(), className)
return inlineFunctionsMap.process(moduleId, sourceFiles.first(), fileBytes) or constantsMap.process(moduleId, sourceFiles.first(), fileBytes)
val inlinesChanged = inlineFunctionsMap.process(moduleId, sourceFiles.first(), fileBytes)
val constantsChanged = constantsMap.process(moduleId, sourceFiles.first(), fileBytes)
return if (inlinesChanged) RECOMPILE_ALL else if (constantsChanged) COMPILE_OTHERS else DO_NOTHING
}
return false
return DO_NOTHING
}
public fun clearCacheForRemovedFiles(moduleIdsAndFiles: Collection<Pair<String, File>>, outDirectories: Map<String, File>) {
@@ -286,7 +292,7 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
return moduleId + File.pathSeparator + sourceFile.getAbsolutePath()
}
private fun getInlineFunctionsMap(bytes: ByteArray): Map<String, Long> {
private fun getInlineFunctionsMap(bytes: ByteArray): Map<String, Long>? {
val result = HashMap<String, Long>()
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
@@ -315,21 +321,23 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
}, 0)
return result
return if (result.isEmpty()) null else result
}
public fun process(moduleId: String, file: File, bytes: ByteArray): Boolean {
return put(moduleId, file, getInlineFunctionsMap(bytes))
}
private fun put(moduleId: String, file: File, inlineFunctionsMap: Map<String, Long>): Boolean {
private fun put(moduleId: String, file: File, inlineFunctionsMap: Map<String, Long>?): Boolean {
val key = getKey(moduleId, file)
val oldMap = map[key]
if (oldMap == inlineFunctionsMap) {
return false
}
map.put(key, inlineFunctionsMap)
if (inlineFunctionsMap != null) {
map.put(key, inlineFunctionsMap)
}
return true
}
@@ -436,6 +444,16 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache {
map.close()
}
}
enum class RecompilationDecision {
DO_NOTHING
COMPILE_OTHERS
RECOMPILE_ALL
fun merge(other: RecompilationDecision): RecompilationDecision {
return if (other.ordinal() > this.ordinal()) other else this
}
}
}
private object ByteArrayExternalizer: DataExternalizer<ByteArray> {
@@ -105,7 +105,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
public void testIndependentClasses() throws Exception {
doTest("jps-plugin/testData/incremental/independentClasses/");
}
@TestMetadata("inlineFunctionsCircularDependency")
public void testInlineFunctionsCircularDependency() throws Exception {
doTest("jps-plugin/testData/incremental/inlineFunctionsCircularDependency/");
}
@TestMetadata("multiplePackagesModified")
public void testMultiplePackagesModified() throws Exception {
doTest("jps-plugin/testData/incremental/multiplePackagesModified/");
@@ -5,9 +5,11 @@ Compiling files:
src/inline.kt
End of files
Cleaning output files:
out/production/module/inline/Klass.class
out/production/module/usage/UsagePackage-usage-*.class
out/production/module/usage/UsagePackage.class
End of files
Compiling files:
src/inline.kt
src/usage.kt
End of files
@@ -0,0 +1,10 @@
package test
inline fun a(body: () -> Unit) {
println("i'm inline function a")
body()
}
fun main(args: Array<String>) {
b { println("to be inlined") }
}
@@ -0,0 +1,10 @@
package test
inline fun a(body: () -> Unit) {
body()
println("i'm inline function a")
}
fun main(args: Array<String>) {
b { println("to be inlined") }
}
@@ -0,0 +1,7 @@
package test
inline fun b(body: () -> Unit) {
println("I'm inline function b")
body()
a { println("To be inlined from b") }
}
@@ -0,0 +1,16 @@
Cleaning output files:
out/production/module/test/TestPackage-a-*.class
out/production/module/test/TestPackage.class
End of files
Compiling files:
src/a.kt
End of files
Cleaning output files:
out/production/module/test/TestPackage-a-*.class
out/production/module/test/TestPackage-b-*.class
out/production/module/test/TestPackage.class
End of files
Compiling files:
src/a.kt
src/b.kt
End of files
@@ -6,9 +6,12 @@ Compiling files:
src/inline.kt
End of files
Cleaning output files:
out/production/module/inline/InlinePackage-inline-*.class
out/production/module/inline/InlinePackage.class
out/production/module/usage/UsagePackage-usage-*.class
out/production/module/usage/UsagePackage.class
End of files
Compiling files:
src/inline.kt
src/usage.kt
End of files