[JS KLIB IC] Implement incremental cache for IR
This commit is contained in:
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.incremental
|
|||||||
|
|
||||||
import com.intellij.util.io.DataExternalizer
|
import com.intellij.util.io.DataExternalizer
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
||||||
|
import org.jetbrains.kotlin.incremental.js.IrTranslationResultValue
|
||||||
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
|
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
|
||||||
import org.jetbrains.kotlin.incremental.storage.*
|
import org.jetbrains.kotlin.incremental.storage.*
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
@@ -40,6 +41,7 @@ open class IncrementalJsCache(
|
|||||||
) : AbstractIncrementalCache<FqName>(cachesDir, pathConverter) {
|
) : AbstractIncrementalCache<FqName>(cachesDir, pathConverter) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TRANSLATION_RESULT_MAP = "translation-result"
|
private const val TRANSLATION_RESULT_MAP = "translation-result"
|
||||||
|
private const val IR_TRANSLATION_RESULT_MAP = "ir-translation-result"
|
||||||
private const val INLINE_FUNCTIONS = "inline-functions"
|
private const val INLINE_FUNCTIONS = "inline-functions"
|
||||||
private const val HEADER_FILE_NAME = "header.meta"
|
private const val HEADER_FILE_NAME = "header.meta"
|
||||||
private const val PACKAGE_META_FILE = "packages-meta"
|
private const val PACKAGE_META_FILE = "packages-meta"
|
||||||
@@ -50,6 +52,7 @@ open class IncrementalJsCache(
|
|||||||
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile, pathConverter))
|
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile, pathConverter))
|
||||||
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||||
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, pathConverter))
|
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, pathConverter))
|
||||||
|
private val irTranslationResults = registerMap(IrTranslationResultMap(IR_TRANSLATION_RESULT_MAP.storageFile, pathConverter))
|
||||||
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, pathConverter))
|
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, pathConverter))
|
||||||
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile))
|
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile))
|
||||||
|
|
||||||
@@ -108,6 +111,11 @@ open class IncrementalJsCache(
|
|||||||
for ((packageName, metadata) in incrementalResults.packageMetadata) {
|
for ((packageName, metadata) in incrementalResults.packageMetadata) {
|
||||||
packageMetadata.put(packageName, metadata)
|
packageMetadata.put(packageName, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ((srcFile, irData) in incrementalResults.irFileData) {
|
||||||
|
val (fileData, symbols, types, strings, declarations, bodies, fqn) = irData
|
||||||
|
irTranslationResults.put(srcFile, fileData, symbols, types, strings, declarations, bodies, fqn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerOutputForFile(srcFile: File, name: FqName) {
|
private fun registerOutputForFile(srcFile: File, name: FqName) {
|
||||||
@@ -118,6 +126,7 @@ open class IncrementalJsCache(
|
|||||||
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||||
dirtySources.forEach {
|
dirtySources.forEach {
|
||||||
translationResults.remove(it, changesCollector)
|
translationResults.remove(it, changesCollector)
|
||||||
|
irTranslationResults.remove(it)
|
||||||
inlineFunctions.remove(it)
|
inlineFunctions.remove(it)
|
||||||
}
|
}
|
||||||
removeAllFromClassStorage(dirtyOutputClassesMap.getDirtyOutputClasses(), changesCollector)
|
removeAllFromClassStorage(dirtyOutputClassesMap.getDirtyOutputClasses(), changesCollector)
|
||||||
@@ -140,6 +149,16 @@ open class IncrementalJsCache(
|
|||||||
put(fqNameString, packageMetadata[fqNameString]!!)
|
put(fqNameString, packageMetadata[fqNameString]!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun nonDirtyIrParts(): Map<File, IrTranslationResultValue> =
|
||||||
|
hashMapOf<File, IrTranslationResultValue>().apply {
|
||||||
|
for (file in irTranslationResults.keys()) {
|
||||||
|
|
||||||
|
if (file !in dirtySources) {
|
||||||
|
put(file, irTranslationResults[file]!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
||||||
@@ -202,6 +221,67 @@ private class TranslationResultMap(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object IrTranslationResultValueExternalizer : DataExternalizer<IrTranslationResultValue> {
|
||||||
|
override fun save(output: DataOutput, value: IrTranslationResultValue) {
|
||||||
|
output.writeArray(value.fileData)
|
||||||
|
output.writeArray(value.symbols)
|
||||||
|
output.writeArray(value.types)
|
||||||
|
output.writeArray(value.strings)
|
||||||
|
output.writeArray(value.declarations)
|
||||||
|
output.writeArray(value.bodies)
|
||||||
|
output.writeArray(value.fqn)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun DataOutput.writeArray(array: ByteArray) {
|
||||||
|
writeInt(array.size)
|
||||||
|
write(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun DataInput.readArray(): ByteArray {
|
||||||
|
val dataSize = readInt()
|
||||||
|
val filedata = ByteArray(dataSize)
|
||||||
|
readFully(filedata)
|
||||||
|
return filedata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(input: DataInput): IrTranslationResultValue {
|
||||||
|
val fileData = input.readArray()
|
||||||
|
val symbols = input.readArray()
|
||||||
|
val types = input.readArray()
|
||||||
|
val strings = input.readArray()
|
||||||
|
val declarations = input.readArray()
|
||||||
|
val bodies = input.readArray()
|
||||||
|
val fqn = input.readArray()
|
||||||
|
|
||||||
|
return IrTranslationResultValue(fileData, symbols, types, strings, declarations, bodies, fqn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IrTranslationResultMap(
|
||||||
|
storageFile: File,
|
||||||
|
private val pathConverter: FileToPathConverter
|
||||||
|
) :
|
||||||
|
BasicStringMap<IrTranslationResultValue>(storageFile, IrTranslationResultValueExternalizer) {
|
||||||
|
override fun dumpValue(value: IrTranslationResultValue): String =
|
||||||
|
"Filedata: ${value.fileData.md5()}, Symbols: ${value.symbols.md5()}, Types: ${value.types.md5()}, Strings: ${value.strings.md5()}, Declarations: ${value.declarations.md5()}, Bodies: ${value.bodies.md5()}"
|
||||||
|
|
||||||
|
fun put(sourceFile: File, newFiledata: ByteArray, newSymbols: ByteArray, newTypes: ByteArray, newStrings: ByteArray, newDeclarations: ByteArray, newBodies: ByteArray, fqn: ByteArray) {
|
||||||
|
storage[pathConverter.toPath(sourceFile)] =
|
||||||
|
IrTranslationResultValue(newFiledata, newSymbols, newTypes, newStrings, newDeclarations, newBodies, fqn)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(sourceFile: File): IrTranslationResultValue? =
|
||||||
|
storage[pathConverter.toPath(sourceFile)]
|
||||||
|
|
||||||
|
fun keys(): Collection<File> =
|
||||||
|
storage.keys.map { pathConverter.toFile(it) }
|
||||||
|
|
||||||
|
fun remove(sourceFile: File) {
|
||||||
|
val path = pathConverter.toPath(sourceFile)
|
||||||
|
storage.remove(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
|
fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
|
||||||
val classes = hashMapOf<ClassId, ProtoData>()
|
val classes = hashMapOf<ClassId, ProtoData>()
|
||||||
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, JsSerializerProtocol.extensionRegistry)
|
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, JsSerializerProtocol.extensionRegistry)
|
||||||
|
|||||||
+3
@@ -21,4 +21,7 @@ class IncrementalDataProviderFromCache(private val cache: IncrementalJsCache) :
|
|||||||
|
|
||||||
override val packageMetadata: Map<String, ByteArray>
|
override val packageMetadata: Map<String, ByteArray>
|
||||||
get() = cache.packageMetadata()
|
get() = cache.packageMetadata()
|
||||||
|
|
||||||
|
override val serializedIrFiles: Map<File, IrTranslationResultValue>
|
||||||
|
get() = cache.nonDirtyIrParts()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,15 @@ import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
|
|||||||
import org.jetbrains.kotlin.daemon.common.Profiler
|
import org.jetbrains.kotlin.daemon.common.Profiler
|
||||||
import org.jetbrains.kotlin.daemon.common.withMeasure
|
import org.jetbrains.kotlin.daemon.common.withMeasure
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
|
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
|
||||||
|
import org.jetbrains.kotlin.incremental.js.IrTranslationResultValue
|
||||||
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
|
import org.jetbrains.kotlin.incremental.js.TranslationResultValue
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class RemoteIncrementalDataProvider(val facade: CompilerCallbackServicesFacade, val rpcProfiler: Profiler) :
|
class RemoteIncrementalDataProvider(val facade: CompilerCallbackServicesFacade, val rpcProfiler: Profiler) :
|
||||||
IncrementalDataProvider {
|
IncrementalDataProvider {
|
||||||
|
override val serializedIrFiles: Map<File, IrTranslationResultValue>
|
||||||
|
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||||
|
|
||||||
override val headerMetadata: ByteArray
|
override val headerMetadata: ByteArray
|
||||||
get() = rpcProfiler.withMeasure(this) {
|
get() = rpcProfiler.withMeasure(this) {
|
||||||
facade.incrementalDataProvider_getHeaderMetadata()
|
facade.incrementalDataProvider_getHeaderMetadata()
|
||||||
|
|||||||
@@ -15,6 +15,18 @@ import java.io.File
|
|||||||
|
|
||||||
class RemoteIncrementalResultsConsumer(val facade: CompilerCallbackServicesFacade, eventManager: EventManager, val rpcProfiler: Profiler) :
|
class RemoteIncrementalResultsConsumer(val facade: CompilerCallbackServicesFacade, eventManager: EventManager, val rpcProfiler: Profiler) :
|
||||||
IncrementalResultsConsumer {
|
IncrementalResultsConsumer {
|
||||||
|
override fun processIrFile(
|
||||||
|
sourceFile: File,
|
||||||
|
fileData: ByteArray,
|
||||||
|
symbols: ByteArray,
|
||||||
|
types: ByteArray,
|
||||||
|
strings: ByteArray,
|
||||||
|
declarations: ByteArray,
|
||||||
|
bodies: ByteArray,
|
||||||
|
fqn: ByteArray
|
||||||
|
) {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
eventManager.
|
eventManager.
|
||||||
|
|||||||
+1
-1
@@ -123,7 +123,7 @@ abstract class AbstractJsLookupTrackerTest : AbstractLookupTrackerTest() {
|
|||||||
if (header != null) {
|
if (header != null) {
|
||||||
register(
|
register(
|
||||||
IncrementalDataProvider::class.java,
|
IncrementalDataProvider::class.java,
|
||||||
IncrementalDataProviderImpl(header!!, packageParts, JsMetadataVersion.INSTANCE.toArray(), emptyMap()) // TODO pass correct metadata
|
IncrementalDataProviderImpl(header!!, packageParts, JsMetadataVersion.INSTANCE.toArray(), emptyMap(), emptyMap()) // TODO pass correct metadata
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.jps.incremental
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private val NORMAL_VERSION = 12
|
private val NORMAL_VERSION = 13
|
||||||
private val NORMAL_VERSION_FILE_NAME = "format-version.txt"
|
private val NORMAL_VERSION_FILE_NAME = "format-version.txt"
|
||||||
|
|
||||||
fun localCacheVersionManager(dataRoot: File, isCachesEnabled: Boolean) =
|
fun localCacheVersionManager(dataRoot: File, isCachesEnabled: Boolean) =
|
||||||
|
|||||||
@@ -31,11 +31,14 @@ interface IncrementalDataProvider {
|
|||||||
|
|
||||||
/** gets non-dirty package metadata from previous compilation */
|
/** gets non-dirty package metadata from previous compilation */
|
||||||
val packageMetadata: Map<String, ByteArray>
|
val packageMetadata: Map<String, ByteArray>
|
||||||
|
|
||||||
|
val serializedIrFiles: Map<File, IrTranslationResultValue>
|
||||||
}
|
}
|
||||||
|
|
||||||
class IncrementalDataProviderImpl(
|
class IncrementalDataProviderImpl(
|
||||||
override val headerMetadata: ByteArray,
|
override val headerMetadata: ByteArray,
|
||||||
override val compiledPackageParts: Map<File, TranslationResultValue>,
|
override val compiledPackageParts: Map<File, TranslationResultValue>,
|
||||||
override val metadataVersion: IntArray,
|
override val metadataVersion: IntArray,
|
||||||
override val packageMetadata: Map<String, ByteArray>
|
override val packageMetadata: Map<String, ByteArray>,
|
||||||
|
override val serializedIrFiles: Map<File, IrTranslationResultValue>
|
||||||
) : IncrementalDataProvider
|
) : IncrementalDataProvider
|
||||||
|
|||||||
+29
-1
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.js
|
package org.jetbrains.kotlin.incremental.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
@@ -42,6 +41,17 @@ interface IncrementalResultsConsumer {
|
|||||||
fun processInlineFunctions(functions: Collection<JsInlineFunctionHash>)
|
fun processInlineFunctions(functions: Collection<JsInlineFunctionHash>)
|
||||||
|
|
||||||
fun processPackageMetadata(packageName: String, metadata: ByteArray)
|
fun processPackageMetadata(packageName: String, metadata: ByteArray)
|
||||||
|
|
||||||
|
fun processIrFile(
|
||||||
|
sourceFile: File,
|
||||||
|
fileData: ByteArray,
|
||||||
|
symbols: ByteArray,
|
||||||
|
types: ByteArray,
|
||||||
|
strings: ByteArray,
|
||||||
|
declarations: ByteArray,
|
||||||
|
bodies: ByteArray,
|
||||||
|
fqn: ByteArray
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class JsInlineFunctionHash(val sourceFilePath: String, val fqName: String, val inlineFunctionMd5Hash: Long): Serializable
|
class JsInlineFunctionHash(val sourceFilePath: String, val fqName: String, val inlineFunctionMd5Hash: Long): Serializable
|
||||||
@@ -108,6 +118,24 @@ class IncrementalResultsConsumerImpl : IncrementalResultsConsumer {
|
|||||||
override fun processPackageMetadata(packageName: String, metadata: ByteArray) {
|
override fun processPackageMetadata(packageName: String, metadata: ByteArray) {
|
||||||
_packageMetadata[packageName] = metadata
|
_packageMetadata[packageName] = metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class IrFileData(fileData: ByteArray, symbols: ByteArray, types: ByteArray, strings: ByteArray, bodies: ByteArray, declarations: ByteArray)
|
||||||
|
private val _irFileData = hashMapOf<File, IrTranslationResultValue>()
|
||||||
|
val irFileData: Map<File, IrTranslationResultValue>
|
||||||
|
get() = _irFileData
|
||||||
|
|
||||||
|
override fun processIrFile(
|
||||||
|
sourceFile: File,
|
||||||
|
fileData: ByteArray,
|
||||||
|
symbols: ByteArray,
|
||||||
|
types: ByteArray,
|
||||||
|
strings: ByteArray,
|
||||||
|
declarations: ByteArray,
|
||||||
|
bodies: ByteArray,
|
||||||
|
fqn: ByteArray
|
||||||
|
) {
|
||||||
|
_irFileData[sourceFile] = IrTranslationResultValue(fileData, symbols, types, strings, declarations, bodies, fqn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ByteArray.md5(): Long {
|
private fun ByteArray.md5(): Long {
|
||||||
|
|||||||
@@ -18,3 +18,13 @@ package org.jetbrains.kotlin.incremental.js
|
|||||||
|
|
||||||
data class TranslationResultValue(val metadata: ByteArray, val binaryAst: ByteArray, val inlineData: ByteArray)
|
data class TranslationResultValue(val metadata: ByteArray, val binaryAst: ByteArray, val inlineData: ByteArray)
|
||||||
|
|
||||||
|
|
||||||
|
data class IrTranslationResultValue(
|
||||||
|
val fileData: ByteArray,
|
||||||
|
val symbols: ByteArray,
|
||||||
|
val types: ByteArray,
|
||||||
|
val strings: ByteArray,
|
||||||
|
val declarations: ByteArray,
|
||||||
|
val bodies: ByteArray,
|
||||||
|
val fqn: ByteArray
|
||||||
|
)
|
||||||
|
|||||||
@@ -654,7 +654,7 @@ abstract class BasicBoxTest(
|
|||||||
if (header != null) {
|
if (header != null) {
|
||||||
configuration.put(
|
configuration.put(
|
||||||
JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER,
|
JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER,
|
||||||
IncrementalDataProviderImpl(header, incrementalData.translatedFiles, JsMetadataVersion.INSTANCE.toArray(), incrementalData.packageMetadata)
|
IncrementalDataProviderImpl(header, incrementalData.translatedFiles, JsMetadataVersion.INSTANCE.toArray(), incrementalData.packageMetadata, emptyMap())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user