[JS IR] Pass forward -Xir-property-lazy-initialization option

Pass forward -Xir-property-lazy-initialization option
for the incremental cache.

^KT-50175 Fixed
This commit is contained in:
Alexander Korepanov
2022-01-13 20:59:21 +03:00
committed by Space
parent 2f853175c7
commit 59173baf5a
17 changed files with 156 additions and 43 deletions
@@ -56,7 +56,6 @@ class JsIrBackendContext(
override val scriptMode: Boolean = false,
override val es6mode: Boolean = false,
val dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
propertyLazyInitialization: Boolean = false,
val baseClassIntoMetadata: Boolean = false,
val safeExternalBoolean: Boolean = false,
val safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
@@ -141,7 +140,7 @@ class JsIrBackendContext(
override val reflectionSymbols: ReflectionSymbols get() = intrinsics.reflectionSymbols
override val propertyLazyInitialization: PropertyLazyInitialization = PropertyLazyInitialization(
enabled = propertyLazyInitialization,
enabled = configuration.getBoolean(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION),
eagerInitialization = symbolTable.referenceClass(getJsInternalClass("EagerInitialization"))
)
@@ -51,7 +51,6 @@ fun compile(
exportedDeclarations: Set<FqName> = emptySet(),
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
es6mode: Boolean = false,
propertyLazyInitialization: Boolean,
verifySignatures: Boolean = true,
baseClassIntoMetadata: Boolean = false,
safeExternalBoolean: Boolean = false,
@@ -76,7 +75,6 @@ fun compile(
exportedDeclarations,
dceRuntimeDiagnostic,
es6mode,
propertyLazyInitialization,
baseClassIntoMetadata,
safeExternalBoolean,
safeExternalBooleanDiagnostic,
@@ -97,7 +95,6 @@ fun compileIr(
exportedDeclarations: Set<FqName>,
dceRuntimeDiagnostic: RuntimeDiagnostic?,
es6mode: Boolean,
propertyLazyInitialization: Boolean,
baseClassIntoMetadata: Boolean,
safeExternalBoolean: Boolean,
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
@@ -123,7 +120,6 @@ fun compileIr(
configuration,
es6mode = es6mode,
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
propertyLazyInitialization = propertyLazyInitialization,
baseClassIntoMetadata = baseClassIntoMetadata,
safeExternalBoolean = safeExternalBoolean,
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
@@ -42,7 +42,6 @@ fun compileWithIC(
es6mode: Boolean = false,
multiModule: Boolean = false,
relativeRequirePath: Boolean = false,
propertyLazyInitialization: Boolean = false,
verifySignatures: Boolean = true,
baseClassIntoMetadata: Boolean = false,
lowerPerModule: Boolean = false,
@@ -67,7 +66,6 @@ fun compileWithIC(
configuration,
es6mode = es6mode,
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
propertyLazyInitialization = propertyLazyInitialization,
baseClassIntoMetadata = baseClassIntoMetadata,
safeExternalBoolean = safeExternalBoolean,
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
@@ -9,12 +9,13 @@ import java.io.File
import java.io.PrintWriter
// TODO md5 hash
data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong, var transHash: ULong) {
data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong, var transHash: ULong, var configHash: ULong) {
fun save() {
PrintWriter(File(File(path), "info")).use {
it.println(libPath)
it.println(flatHash.toString(16))
it.println(transHash.toString(16))
it.println(configHash.toString(16))
}
}
@@ -24,9 +25,11 @@ data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong,
if (!info.exists()) return null
val (libPath, flatHash, transHash) = info.readLines()
val (libPath, flatHash, transHash, configHash) = info.readLines()
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16))
// safe cast for the backward compatibility with the cache from the previous compiler versions
val configHashULong = configHash.toULongOrNull(16) ?: 0UL
return CacheInfo(path, libPath, flatHash.toULong(16), transHash.toULong(16), configHashULong)
}
}
}
@@ -51,7 +51,8 @@ private fun invalidateCacheForModule(
cacheProvider: PersistentCacheProvider,
cacheConsumer: PersistentCacheConsumer,
signatureResolver: (String, Int) -> IdSignature,
fileFingerPrints: MutableMap<String, Hash>
fileFingerPrints: MutableMap<String, Hash>,
configUpdated: Boolean
): Pair<Set<String>, Collection<String>> {
val dirtyFiles = mutableSetOf<String>()
@@ -64,7 +65,7 @@ private fun invalidateCacheForModule(
// 2. calculate new fingerprints
val fileNewFingerprint = library.fingerprint(index)
if (fileOldFingerprint != fileNewFingerprint) {
if (fileOldFingerprint != fileNewFingerprint || configUpdated) {
fileFingerPrints[file] = fileNewFingerprint
cachedInlineHashesForFile.remove(file)
@@ -203,9 +204,25 @@ private fun buildCacheForModule(
// TODO: actual way of building a cache could change in future
cacheExecutor.execute(irModule, dependencies, deserializer, configuration, dirtyFiles, deletedFiles, cacheConsumer, emptySet(), mainArguments)
cacheExecutor.execute(
irModule,
dependencies,
deserializer,
configuration,
dirtyFiles,
deletedFiles,
cacheConsumer,
emptySet(),
mainArguments
)
cacheConsumer.commitLibraryInfo(libraryInfo.libPath.toCanonicalPath(), libraryInfo.flatHash, libraryInfo.transHash, irModule.name.asString())
cacheConsumer.commitLibraryInfo(
libraryInfo.libPath.toCanonicalPath(),
libraryInfo.flatHash,
libraryInfo.transHash,
libraryInfo.configHash,
irModule.name.asString()
)
}
private fun loadModules(
@@ -315,24 +332,11 @@ fun interface CacheExecutor {
)
}
private fun File.md5(): ULong {
private fun calcMD5(feeder: (MessageDigest) -> Unit): ULong {
val md5 = MessageDigest.getInstance("MD5")
fun File.process(prefix: String = "") {
if (isDirectory) {
this.listFiles()!!.sortedBy { it.name }.forEach {
md5.update((prefix + it.name).toByteArray())
it.process(prefix + it.name + "/")
}
} else {
md5.update(readBytes())
}
}
this.process()
feeder(md5)
val d = md5.digest()
return ((d[0].toULong() and 0xFFUL)
or ((d[1].toULong() and 0xFFUL) shl 8)
or ((d[2].toULong() and 0xFFUL) shl 16)
@@ -344,6 +348,30 @@ private fun File.md5(): ULong {
)
}
private fun File.md5(): ULong {
fun File.process(md5: MessageDigest, prefix: String = "") {
if (isDirectory) {
this.listFiles()!!.sortedBy { it.name }.forEach {
md5.update((prefix + it.name).toByteArray())
it.process(md5, prefix + it.name + "/")
}
} else {
md5.update(readBytes())
}
}
return calcMD5 { this.process(it) }
}
private fun CompilerConfiguration.calcMD5(): ULong {
val importantBooleanSettingKeys = listOf(JSConfigurationKeys.PROPERTY_LAZY_INITIALIZATION)
return calcMD5 {
for (key in importantBooleanSettingKeys) {
it.update(key.toString().toByteArray())
it.update(getBoolean(key).toString().toByteArray())
}
}
}
private fun checkLibrariesHash(
libraries: Map<ModulePath, KotlinLibrary>,
dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
@@ -391,8 +419,9 @@ fun actualizeCacheForModule(
mainArguments: List<String>?,
executor: CacheExecutor
): CacheUpdateStatus {
val configMD5 = compilerConfiguration.calcMD5()
val modulePath = moduleName.toCanonicalPath()
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL)
val cacheInfo = CacheInfo.load(cachePath) ?: CacheInfo(cachePath, modulePath, 0UL, 0UL, configMD5)
val icCacheMap: Map<ModulePath, CacheInfo> = loadCacheInfo(icCachePaths).also {
it[modulePath] = cacheInfo
}
@@ -405,7 +434,9 @@ fun actualizeCacheForModule(
}
}
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath)) {
val configUpdated = configMD5 != cacheInfo.configHash
cacheInfo.configHash = configMD5
if (checkLibrariesHash(libraries, dependencyGraph, icCacheMap, modulePath) && !configUpdated) {
return CacheUpdateStatus.FAST_PATH // up-to-date
}
@@ -425,7 +456,8 @@ fun actualizeCacheForModule(
persistentCacheConsumer,
irFactory,
mainArguments,
executor
executor,
configUpdated
)
}
@@ -439,7 +471,8 @@ private fun actualizeCacheForModule(
persistentCacheConsumer: PersistentCacheConsumer,
irFactory: IrFactory,
mainArguments: List<String>?,
cacheExecutor: CacheExecutor
cacheExecutor: CacheExecutor,
configUpdated: Boolean
): CacheUpdateStatus {
// 1. Invalidate
val dependencies = dependencyGraph[library]!!
@@ -486,7 +519,8 @@ private fun actualizeCacheForModule(
currentLibraryCacheProvider,
persistentCacheConsumer,
signatureResolver,
fileFingerPrints
fileFingerPrints,
configUpdated
)
if (dirtySet.isEmpty()) return CacheUpdateStatus.NO_DIRTY_FILES // up-to-date
@@ -582,7 +616,7 @@ fun rebuildCacheForDirtyFiles(
val currentIrModule = irModules.find { it.second == library }?.first!!
cacheConsumer.commitLibraryInfo(library.libraryFile.path.toCanonicalPath(), 0UL, 0UL, currentIrModule.name.asString())
cacheConsumer.commitLibraryInfo(library.libraryFile.path.toCanonicalPath(), 0UL, 0UL, 0UL, currentIrModule.name.asString())
buildCacheForModuleFiles(
currentIrModule,