[JS IR] Use topological order for loading klibs in JS IR IC
Generally, the library order doesn't matter. However, after lowering we need to post process lowered klibs in topological order: - commit incremental cache artifacts, - produce JS AST. The patch uses an ability of the Kotlin library resolver to load klibs in topological order and drops its reimplementation from IC infrastructure. There is one side effect: klibs which are not reachable from the main module, will produce their JS. This should be more correct than just ignoring them.
This commit is contained in:
committed by
Space Team
parent
ec6a7094e6
commit
8cde0a81bc
@@ -659,12 +659,12 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
|
|
||||||
val artifacts = cacheUpdater.actualizeCaches()
|
val artifacts = cacheUpdater.actualizeCaches()
|
||||||
messageCollector.report(INFO, "IC rebuilt overall time: ${System.currentTimeMillis() - start}ms")
|
messageCollector.report(INFO, "IC rebuilt overall time: ${System.currentTimeMillis() - start}ms")
|
||||||
for ((event, duration) in cacheUpdater.getStopwatchLaps()) {
|
for ((event, duration) in cacheUpdater.getStopwatchLastLaps()) {
|
||||||
messageCollector.report(INFO, " $event: ${(duration / 1e6).toInt()}ms")
|
messageCollector.report(INFO, " $event: ${(duration / 1e6).toInt()}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
var libIndex = 0
|
var libIndex = 0
|
||||||
for ((libFile, srcFiles) in cacheUpdater.getDirtyFileStats()) {
|
for ((libFile, srcFiles) in cacheUpdater.getDirtyFileLastStats()) {
|
||||||
val (msg, showFiles) = when {
|
val (msg, showFiles) = when {
|
||||||
srcFiles.values.all { it.contains(DirtyFileState.ADDED_FILE) } -> "fully rebuilt due to clean build" to false
|
srcFiles.values.all { it.contains(DirtyFileState.ADDED_FILE) } -> "fully rebuilt due to clean build" to false
|
||||||
srcFiles.values.all { it.contains(DirtyFileState.MODIFIED_CONFIG) } -> "fully rebuilt due to config modification" to false
|
srcFiles.values.all { it.contains(DirtyFileState.MODIFIED_CONFIG) } -> "fully rebuilt due to config modification" to false
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||||
import org.jetbrains.kotlin.library.KLIB_PROPERTY_DEPENDS
|
import org.jetbrains.kotlin.library.KLIB_PROPERTY_DEPENDS
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
|
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.util.EnumSet
|
import java.util.EnumSet
|
||||||
|
|
||||||
fun interface JsIrCompilerICInterface {
|
fun interface JsIrCompilerICInterface {
|
||||||
@@ -48,31 +48,24 @@ enum class DirtyFileState(val str: String) {
|
|||||||
|
|
||||||
class CacheUpdater(
|
class CacheUpdater(
|
||||||
mainModule: String,
|
mainModule: String,
|
||||||
allModules: Collection<String>,
|
private val allModules: Collection<String>,
|
||||||
private val icCacheRootDir: String,
|
private val icCacheRootDir: String,
|
||||||
private val compilerConfiguration: CompilerConfiguration,
|
private val compilerConfiguration: CompilerConfiguration,
|
||||||
private val irFactory: () -> IrFactory,
|
private val irFactory: () -> IrFactory,
|
||||||
private val mainArguments: List<String>?,
|
private val mainArguments: List<String>?,
|
||||||
private val compilerInterfaceFactory: JsIrCompilerICInterfaceFactory
|
private val compilerInterfaceFactory: JsIrCompilerICInterfaceFactory
|
||||||
) {
|
) {
|
||||||
private val stopwatch = StopwatchIC().apply { startNext("Loading klibs") }
|
private val stopwatch = StopwatchIC()
|
||||||
|
|
||||||
private val libraries = loadLibraries(allModules)
|
|
||||||
private val dependencyGraph = buildDependenciesGraph(libraries)
|
|
||||||
private val configHash = compilerConfiguration.configHashForIC()
|
|
||||||
|
|
||||||
private val mainLibraryFile = KotlinLibraryFile(File(mainModule).canonicalPath)
|
|
||||||
private val mainLibrary = libraries[mainLibraryFile] ?: notFoundIcError("main library", mainLibraryFile)
|
|
||||||
|
|
||||||
private val dirtyFileStats = KotlinSourceFileMutableMap<EnumSet<DirtyFileState>>()
|
private val dirtyFileStats = KotlinSourceFileMutableMap<EnumSet<DirtyFileState>>()
|
||||||
|
|
||||||
init {
|
private val configHash = compilerConfiguration.configHashForIC()
|
||||||
stopwatch.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDirtyFileStats(): KotlinSourceFileMap<EnumSet<DirtyFileState>> = dirtyFileStats
|
private val mainLibraryFile = KotlinLibraryFile(File(mainModule).canonicalPath)
|
||||||
|
|
||||||
fun getStopwatchLaps() = stopwatch.laps
|
fun getDirtyFileLastStats(): KotlinSourceFileMap<EnumSet<DirtyFileState>> = dirtyFileStats
|
||||||
|
|
||||||
|
fun getStopwatchLastLaps() = stopwatch.laps
|
||||||
|
|
||||||
private fun MutableMap<KotlinSourceFile, EnumSet<DirtyFileState>>.addDirtFileStat(srcFile: KotlinSourceFile, state: DirtyFileState) {
|
private fun MutableMap<KotlinSourceFile, EnumSet<DirtyFileState>>.addDirtFileStat(srcFile: KotlinSourceFile, state: DirtyFileState) {
|
||||||
when (val stats = this[srcFile]) {
|
when (val stats = this[srcFile]) {
|
||||||
@@ -81,44 +74,41 @@ class CacheUpdater(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLibraries(allModules: Collection<String>): Map<KotlinLibraryFile, KotlinLibrary> {
|
|
||||||
val repositories = compilerConfiguration[JSConfigurationKeys.REPOSITORIES] ?: emptyList()
|
|
||||||
val allResolvedDependencies = jsResolveLibraries(allModules, repositories, compilerConfiguration.resolverLogger)
|
|
||||||
return allResolvedDependencies.getFullList().associateBy { KotlinLibraryFile(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildDependenciesGraph(libraries: Map<KotlinLibraryFile, KotlinLibrary>): Map<KotlinLibrary, List<KotlinLibrary>> {
|
|
||||||
val nameToKotlinLibrary = libraries.values.associateBy { it.moduleName }
|
|
||||||
return libraries.values.associateWith {
|
|
||||||
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
|
||||||
nameToKotlinLibrary[depName] ?: notFoundIcError("library $depName")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> mapLibrariesInOrder(f: (KotlinLibraryFile) -> T): List<T> {
|
|
||||||
val visited = HashSet<KotlinLibrary>(libraries.size)
|
|
||||||
val result = ArrayList<T>(libraries.size)
|
|
||||||
fun visitLibrary(lib: KotlinLibrary) {
|
|
||||||
if (visited.add(lib)) {
|
|
||||||
dependencyGraph[lib]?.forEach(::visitLibrary)
|
|
||||||
result += f(KotlinLibraryFile(lib))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visitLibrary(mainLibrary)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class CacheUpdaterInternal {
|
private inner class CacheUpdaterInternal {
|
||||||
val signatureHashCalculator = IdSignatureHashCalculator()
|
val signatureHashCalculator = IdSignatureHashCalculator()
|
||||||
|
|
||||||
private val incrementalCaches = run {
|
// libraries in topological order: [stdlib, ..., main]
|
||||||
val md5 = MessageDigest.getInstance("MD5")
|
val libraryDependencies = stopwatch.measure("Resolving and loading klib dependencies") {
|
||||||
libraries.entries.associate { (libFile, lib) ->
|
val repositories = compilerConfiguration[JSConfigurationKeys.REPOSITORIES] ?: emptyList()
|
||||||
|
val allResolvedDependencies = jsResolveLibraries(allModules, repositories, compilerConfiguration.resolverLogger)
|
||||||
|
|
||||||
|
val libraries = allResolvedDependencies.getFullList(TopologicalLibraryOrder).let { resolvedLibraries ->
|
||||||
|
val mainLibraryIndex = resolvedLibraries.indexOfLast {
|
||||||
|
KotlinLibraryFile(it) == mainLibraryFile
|
||||||
|
}.takeIf { it >= 0 } ?: notFoundIcError("main library", mainLibraryFile)
|
||||||
|
|
||||||
|
when (mainLibraryIndex) {
|
||||||
|
resolvedLibraries.lastIndex -> resolvedLibraries
|
||||||
|
else -> resolvedLibraries.filterIndexedTo(ArrayList(resolvedLibraries.size)) { index, _ ->
|
||||||
|
index != mainLibraryIndex
|
||||||
|
}.apply { add(resolvedLibraries[mainLibraryIndex]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val nameToKotlinLibrary = libraries.associateBy { it.moduleName }
|
||||||
|
|
||||||
|
libraries.associateWith {
|
||||||
|
it.manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true).map { depName ->
|
||||||
|
nameToKotlinLibrary[depName] ?: notFoundIcError("library $depName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val incrementalCaches = stopwatch.measure("Incremental cache - initializing") {
|
||||||
|
libraryDependencies.keys.associate { lib ->
|
||||||
|
val libFile = KotlinLibraryFile(lib)
|
||||||
val file = File(libFile.path)
|
val file = File(libFile.path)
|
||||||
val hash = md5.digest(file.absolutePath.encodeToByteArray()).joinToString("", transform = { "%02x".format(it) })
|
libFile to IncrementalCache(lib, File(icCacheRootDir, "${file.absolutePath.stringHashForIC()}.${file.name}"))
|
||||||
libFile to IncrementalCache(lib, File(icCacheRootDir, "${file.name}.$hash"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,7 +501,8 @@ class CacheUpdater(
|
|||||||
jsIrLinker: JsIrLinker,
|
jsIrLinker: JsIrLinker,
|
||||||
loadedFragments: Map<KotlinLibraryFile, IrModuleFragment>
|
loadedFragments: Map<KotlinLibraryFile, IrModuleFragment>
|
||||||
): Map<KotlinLibraryFile, IncrementalCacheArtifact> {
|
): Map<KotlinLibraryFile, IncrementalCacheArtifact> {
|
||||||
return mapLibrariesInOrder { libFile ->
|
return libraryDependencies.keys.associate { library ->
|
||||||
|
val libFile = KotlinLibraryFile(library)
|
||||||
val incrementalCache = getLibIncrementalCache(libFile)
|
val incrementalCache = getLibIncrementalCache(libFile)
|
||||||
val libFragment = loadedFragments[libFile] ?: notFoundIcError("loaded fragment", libFile)
|
val libFragment = loadedFragments[libFile] ?: notFoundIcError("loaded fragment", libFile)
|
||||||
val moduleDeserializer = jsIrLinker.moduleDeserializer(libFragment.descriptor)
|
val moduleDeserializer = jsIrLinker.moduleDeserializer(libFragment.descriptor)
|
||||||
@@ -520,7 +511,7 @@ class CacheUpdater(
|
|||||||
KotlinSourceFile(it.file) to it.symbolDeserializer.signatureDeserializer.signatureToIndexMapping()
|
KotlinSourceFile(it.file) to it.symbolDeserializer.signatureDeserializer.signatureToIndexMapping()
|
||||||
}
|
}
|
||||||
libFile to incrementalCache.buildIncrementalCacheArtifact(signatureToIndexMapping)
|
libFile to incrementalCache.buildIncrementalCacheArtifact(signatureToIndexMapping)
|
||||||
}.toMap()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,50 +519,40 @@ class CacheUpdater(
|
|||||||
incrementalCacheArtifacts: Map<KotlinLibraryFile, IncrementalCacheArtifact>,
|
incrementalCacheArtifacts: Map<KotlinLibraryFile, IncrementalCacheArtifact>,
|
||||||
moduleNames: Map<KotlinLibraryFile, String>,
|
moduleNames: Map<KotlinLibraryFile, String>,
|
||||||
rebuiltFileFragments: KotlinSourceFileMap<JsIrProgramFragment>
|
rebuiltFileFragments: KotlinSourceFileMap<JsIrProgramFragment>
|
||||||
): List<ModuleArtifact> {
|
): List<ModuleArtifact> = stopwatch.measure("Incremental cache - committing artifacts") {
|
||||||
stopwatch.startNext("Incremental cache - committing artifacts")
|
incrementalCacheArtifacts.map { (libFile, incrementalCacheArtifact) ->
|
||||||
|
|
||||||
val artifacts = mapLibrariesInOrder { libFile ->
|
|
||||||
val incrementalCacheArtifact = incrementalCacheArtifacts[libFile] ?: notFoundIcError("cache artifact", libFile)
|
|
||||||
val library = libraries[libFile] ?: notFoundIcError("library", libFile)
|
|
||||||
incrementalCacheArtifact.buildModuleArtifactAndCommitCache(
|
incrementalCacheArtifact.buildModuleArtifactAndCommitCache(
|
||||||
moduleName = moduleNames[libFile] ?: notFoundIcError("module name", libFile),
|
moduleName = moduleNames[libFile] ?: notFoundIcError("module name", libFile),
|
||||||
externalModuleName = library.jsOutputName,
|
|
||||||
rebuiltFileFragments = rebuiltFileFragments[libFile] ?: emptyMap()
|
rebuiltFileFragments = rebuiltFileFragments[libFile] ?: emptyMap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
stopwatch.stop()
|
|
||||||
return artifacts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compileDirtyFiles(
|
private fun compileDirtyFiles(
|
||||||
compilerForIC: JsIrCompilerICInterface,
|
compilerForIC: JsIrCompilerICInterface,
|
||||||
loadedFragments: Map<KotlinLibraryFile, IrModuleFragment>,
|
loadedFragments: Map<KotlinLibraryFile, IrModuleFragment>,
|
||||||
dirtyFiles: Map<KotlinLibraryFile, Set<KotlinSourceFile>>
|
dirtyFiles: Map<KotlinLibraryFile, Set<KotlinSourceFile>>
|
||||||
): MutableList<Triple<KotlinLibraryFile, KotlinSourceFile, () -> JsIrProgramFragment>> {
|
): MutableList<Triple<KotlinLibraryFile, KotlinSourceFile, () -> JsIrProgramFragment>> =
|
||||||
stopwatch.startNext("Processing IR - lowering")
|
stopwatch.measure("Processing IR - lowering") {
|
||||||
|
val dirtyFilesForCompiling = mutableListOf<IrFile>()
|
||||||
val dirtyFilesForCompiling = mutableListOf<IrFile>()
|
val dirtyFilesForRestoring = mutableListOf<Pair<KotlinLibraryFile, KotlinSourceFile>>()
|
||||||
val dirtyFilesForRestoring = mutableListOf<Pair<KotlinLibraryFile, KotlinSourceFile>>()
|
for ((libFile, libFragment) in loadedFragments) {
|
||||||
for ((libFile, libFragment) in loadedFragments) {
|
val dirtySrcFiles = dirtyFiles[libFile] ?: continue
|
||||||
val dirtySrcFiles = dirtyFiles[libFile] ?: continue
|
for (irFile in libFragment.files) {
|
||||||
for (irFile in libFragment.files) {
|
val srcFile = KotlinSourceFile(irFile)
|
||||||
val srcFile = KotlinSourceFile(irFile)
|
if (srcFile in dirtySrcFiles) {
|
||||||
if (srcFile in dirtySrcFiles) {
|
dirtyFilesForCompiling += irFile
|
||||||
dirtyFilesForCompiling += irFile
|
dirtyFilesForRestoring += libFile to srcFile
|
||||||
dirtyFilesForRestoring += libFile to srcFile
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val fragmentGenerators = compilerForIC.compile(loadedFragments.values, dirtyFilesForCompiling, mainArguments)
|
val fragmentGenerators = compilerForIC.compile(loadedFragments.values, dirtyFilesForCompiling, mainArguments)
|
||||||
|
|
||||||
stopwatch.stop()
|
dirtyFilesForRestoring.mapIndexedTo(ArrayList(dirtyFilesForRestoring.size)) { i, libFileAndSrcFile ->
|
||||||
return dirtyFilesForRestoring.mapIndexedTo(ArrayList(dirtyFilesForRestoring.size)) { i, libFileAndSrcFile ->
|
Triple(libFileAndSrcFile.first, libFileAndSrcFile.second, fragmentGenerators[i])
|
||||||
Triple(libFileAndSrcFile.first, libFileAndSrcFile.second, fragmentGenerators[i])
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private data class IrForDirtyFilesAndCompiler(
|
private data class IrForDirtyFilesAndCompiler(
|
||||||
val incrementalCacheArtifacts: Map<KotlinLibraryFile, IncrementalCacheArtifact>,
|
val incrementalCacheArtifacts: Map<KotlinLibraryFile, IncrementalCacheArtifact>,
|
||||||
@@ -581,9 +562,6 @@ class CacheUpdater(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private fun loadIrForDirtyFilesAndInitCompiler(): IrForDirtyFilesAndCompiler {
|
private fun loadIrForDirtyFilesAndInitCompiler(): IrForDirtyFilesAndCompiler {
|
||||||
dirtyFileStats.clear()
|
|
||||||
|
|
||||||
stopwatch.startNext("Incremental cache - initializing")
|
|
||||||
val updater = CacheUpdaterInternal()
|
val updater = CacheUpdaterInternal()
|
||||||
|
|
||||||
stopwatch.startNext("Modified files - checking hashes and collecting")
|
stopwatch.startNext("Modified files - checking hashes and collecting")
|
||||||
@@ -593,7 +571,7 @@ class CacheUpdater(
|
|||||||
val dirtyFileExports = updater.collectExportedSymbolsForDirtyFiles(modifiedFiles)
|
val dirtyFileExports = updater.collectExportedSymbolsForDirtyFiles(modifiedFiles)
|
||||||
|
|
||||||
stopwatch.startNext("Modified files - loading and linking IR")
|
stopwatch.startNext("Modified files - loading and linking IR")
|
||||||
val jsIrLinkerLoader = JsIrLinkerLoader(compilerConfiguration, mainLibrary, dependencyGraph, irFactory())
|
val jsIrLinkerLoader = JsIrLinkerLoader(compilerConfiguration, updater.libraryDependencies, irFactory())
|
||||||
var loadedIr = jsIrLinkerLoader.loadIr(dirtyFileExports)
|
var loadedIr = jsIrLinkerLoader.loadIr(dirtyFileExports)
|
||||||
|
|
||||||
var iterations = 0
|
var iterations = 0
|
||||||
@@ -630,8 +608,8 @@ class CacheUpdater(
|
|||||||
}
|
}
|
||||||
|
|
||||||
stopwatch.startNext("Processing IR - initializing backend context")
|
stopwatch.startNext("Processing IR - initializing backend context")
|
||||||
val mainModule = loadedIr.loadedFragments[mainLibraryFile] ?: notFoundIcError("main lib loaded fragment", mainLibraryFile)
|
val mainModuleFragment = loadedIr.loadedFragments[mainLibraryFile] ?: notFoundIcError("main module fragment", mainLibraryFile)
|
||||||
val compilerForIC = compilerInterfaceFactory.createCompilerForIC(mainModule, compilerConfiguration)
|
val compilerForIC = compilerInterfaceFactory.createCompilerForIC(mainModuleFragment, compilerConfiguration)
|
||||||
|
|
||||||
// Load declarations referenced during `context` initialization
|
// Load declarations referenced during `context` initialization
|
||||||
loadedIr.linker.loadUnboundSymbols(true)
|
loadedIr.linker.loadUnboundSymbols(true)
|
||||||
@@ -639,7 +617,7 @@ class CacheUpdater(
|
|||||||
val dirtyFiles = dirtyFileExports.entries.associateTo(HashMap(dirtyFileExports.size)) { it.key to HashSet(it.value.keys) }
|
val dirtyFiles = dirtyFileExports.entries.associateTo(HashMap(dirtyFileExports.size)) { it.key to HashSet(it.value.keys) }
|
||||||
|
|
||||||
stopwatch.startNext("Processing IR - updating intrinsics and builtins dependencies")
|
stopwatch.startNext("Processing IR - updating intrinsics and builtins dependencies")
|
||||||
updater.updateStdlibIntrinsicDependencies(loadedIr.linker, mainModule, loadedIr.loadedFragments, dirtyFiles)
|
updater.updateStdlibIntrinsicDependencies(loadedIr.linker, mainModuleFragment, loadedIr.loadedFragments, dirtyFiles)
|
||||||
|
|
||||||
stopwatch.startNext("Incremental cache - building artifacts")
|
stopwatch.startNext("Incremental cache - building artifacts")
|
||||||
val incrementalCachesArtifacts = updater.buildCacheArtifacts(loadedIr.linker, loadedIr.loadedFragments)
|
val incrementalCachesArtifacts = updater.buildCacheArtifacts(loadedIr.linker, loadedIr.loadedFragments)
|
||||||
@@ -666,18 +644,19 @@ class CacheUpdater(
|
|||||||
|
|
||||||
private fun generateIrFragments(
|
private fun generateIrFragments(
|
||||||
generators: MutableList<Triple<KotlinLibraryFile, KotlinSourceFile, () -> JsIrProgramFragment>>
|
generators: MutableList<Triple<KotlinLibraryFile, KotlinSourceFile, () -> JsIrProgramFragment>>
|
||||||
): KotlinSourceFileMap<JsIrProgramFragment> {
|
): KotlinSourceFileMap<JsIrProgramFragment> = stopwatch.measure("Processing IR - generating program fragments") {
|
||||||
stopwatch.startNext("Processing IR - generating program fragments")
|
|
||||||
val rebuiltFragments = KotlinSourceFileMutableMap<JsIrProgramFragment>()
|
val rebuiltFragments = KotlinSourceFileMutableMap<JsIrProgramFragment>()
|
||||||
while (generators.isNotEmpty()) {
|
while (generators.isNotEmpty()) {
|
||||||
val (libFile, srcFile, fragmentGenerator) = generators.removeFirst()
|
val (libFile, srcFile, fragmentGenerator) = generators.removeFirst()
|
||||||
rebuiltFragments[libFile, srcFile] = fragmentGenerator()
|
rebuiltFragments[libFile, srcFile] = fragmentGenerator()
|
||||||
}
|
}
|
||||||
stopwatch.stop()
|
rebuiltFragments
|
||||||
return rebuiltFragments
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun actualizeCaches(): List<ModuleArtifact> {
|
fun actualizeCaches(): List<ModuleArtifact> {
|
||||||
|
stopwatch.clear()
|
||||||
|
dirtyFileStats.clear()
|
||||||
|
|
||||||
val (incrementalCachesArtifacts, moduleNames, generators) = loadIrAndMakeIrFragmentGenerators()
|
val (incrementalCachesArtifacts, moduleNames, generators) = loadIrAndMakeIrFragmentGenerators()
|
||||||
|
|
||||||
val rebuiltFragments = generateIrFragments(generators)
|
val rebuiltFragments = generateIrFragments(generators)
|
||||||
@@ -704,7 +683,7 @@ fun rebuildCacheForDirtyFiles(
|
|||||||
val dirtySrcFiles = dirtyFiles?.map { KotlinSourceFile(it) } ?: KotlinLibraryHeader(library).sourceFiles
|
val dirtySrcFiles = dirtyFiles?.map { KotlinSourceFile(it) } ?: KotlinLibraryHeader(library).sourceFiles
|
||||||
val modifiedFiles = mapOf(libFile to dirtySrcFiles.associateWith { emptyMetadata })
|
val modifiedFiles = mapOf(libFile to dirtySrcFiles.associateWith { emptyMetadata })
|
||||||
|
|
||||||
val jsIrLoader = JsIrLinkerLoader(configuration, library, dependencyGraph, irFactory)
|
val jsIrLoader = JsIrLinkerLoader(configuration, dependencyGraph, irFactory)
|
||||||
val (jsIrLinker, irModules) = jsIrLoader.loadIr(KotlinSourceFileMap<KotlinSourceFileExports>(modifiedFiles), true)
|
val (jsIrLinker, irModules) = jsIrLoader.loadIr(KotlinSourceFileMap<KotlinSourceFileExports>(modifiedFiles), true)
|
||||||
|
|
||||||
val currentIrModule = irModules[libFile] ?: notFoundIcError("loaded fragment", libFile)
|
val currentIrModule = irModules[libFile] ?: notFoundIcError("loaded fragment", libFile)
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ internal class StopwatchIC {
|
|||||||
val laps: List<Pair<String, Long>>
|
val laps: List<Pair<String, Long>>
|
||||||
get() = lapsImpl
|
get() = lapsImpl
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
lapStart = 0
|
||||||
|
lapDescription = null
|
||||||
|
lapsImpl.clear()
|
||||||
|
}
|
||||||
|
|
||||||
fun startNext(description: String) {
|
fun startNext(description: String) {
|
||||||
val now = System.nanoTime()
|
val now = System.nanoTime()
|
||||||
stop(now)
|
stop(now)
|
||||||
@@ -82,4 +88,11 @@ internal class StopwatchIC {
|
|||||||
}
|
}
|
||||||
lapDescription = null
|
lapDescription = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <T> measure(description: String, f: () -> T): T {
|
||||||
|
startNext(description)
|
||||||
|
val result = f()
|
||||||
|
stop()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
package org.jetbrains.kotlin.ir.backend.js.ic
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.IdSignatureDeserializer
|
import org.jetbrains.kotlin.backend.common.serialization.IdSignatureDeserializer
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.jsOutputName
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
import org.jetbrains.kotlin.library.impl.javaFile
|
import org.jetbrains.kotlin.library.impl.javaFile
|
||||||
@@ -85,7 +86,7 @@ internal class IncrementalCache(private val library: KotlinLibrary, private val
|
|||||||
val fileArtifacts = kotlinLibraryHeader.sourceFiles.map { srcFile ->
|
val fileArtifacts = kotlinLibraryHeader.sourceFiles.map { srcFile ->
|
||||||
commitSourceFileMetadata(srcFile.getCacheFile(BINARY_AST_SUFFIX), srcFile, signatureToIndexMapping[srcFile] ?: emptyMap())
|
commitSourceFileMetadata(srcFile.getCacheFile(BINARY_AST_SUFFIX), srcFile, signatureToIndexMapping[srcFile] ?: emptyMap())
|
||||||
}
|
}
|
||||||
return IncrementalCacheArtifact(cacheDir, forceRebuildJs, fileArtifacts)
|
return IncrementalCacheArtifact(cacheDir, forceRebuildJs, fileArtifacts, library.jsOutputName)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ModifiedFiles(
|
data class ModifiedFiles(
|
||||||
|
|||||||
+2
-2
@@ -54,11 +54,11 @@ internal sealed class SourceFileCacheArtifact(val srcFile: KotlinSourceFile, val
|
|||||||
internal class IncrementalCacheArtifact(
|
internal class IncrementalCacheArtifact(
|
||||||
private val artifactsDir: File,
|
private val artifactsDir: File,
|
||||||
private val forceRebuildJs: Boolean,
|
private val forceRebuildJs: Boolean,
|
||||||
private val srcCacheActions: List<SourceFileCacheArtifact>
|
private val srcCacheActions: List<SourceFileCacheArtifact>,
|
||||||
|
private val externalModuleName: String?
|
||||||
) {
|
) {
|
||||||
fun buildModuleArtifactAndCommitCache(
|
fun buildModuleArtifactAndCommitCache(
|
||||||
moduleName: String,
|
moduleName: String,
|
||||||
externalModuleName: String?,
|
|
||||||
rebuiltFileFragments: Map<KotlinSourceFile, JsIrProgramFragment>,
|
rebuiltFileFragments: Map<KotlinSourceFile, JsIrProgramFragment>,
|
||||||
): ModuleArtifact {
|
): ModuleArtifact {
|
||||||
val serializer = JsIrAstSerializer()
|
val serializer = JsIrAstSerializer()
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,6 @@ internal fun JsIrLinker.loadUnboundSymbols(checkNoUnbound: Boolean) {
|
|||||||
|
|
||||||
internal class JsIrLinkerLoader(
|
internal class JsIrLinkerLoader(
|
||||||
private val compilerConfiguration: CompilerConfiguration,
|
private val compilerConfiguration: CompilerConfiguration,
|
||||||
private val library: KotlinLibrary,
|
|
||||||
private val dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
private val dependencyGraph: Map<KotlinLibrary, List<KotlinLibrary>>,
|
||||||
private val irFactory: IrFactory
|
private val irFactory: IrFactory
|
||||||
) {
|
) {
|
||||||
@@ -87,11 +86,12 @@ internal class JsIrLinkerLoader(
|
|||||||
val loadedModules = loadModules()
|
val loadedModules = loadModules()
|
||||||
val jsIrLinker = createLinker(loadedModules)
|
val jsIrLinker = createLinker(loadedModules)
|
||||||
|
|
||||||
|
val mainLibrary = dependencyGraph.keys.lastOrNull() ?: notFoundIcError("main library")
|
||||||
val irModules = loadedModules.entries.associate { (descriptor, module) ->
|
val irModules = loadedModules.entries.associate { (descriptor, module) ->
|
||||||
val libraryFile = KotlinLibraryFile(module)
|
val libraryFile = KotlinLibraryFile(module)
|
||||||
val modifiedStrategy = when {
|
val modifiedStrategy = when {
|
||||||
loadAllIr -> DeserializationStrategy.ALL
|
loadAllIr -> DeserializationStrategy.ALL
|
||||||
module == library -> DeserializationStrategy.ALL
|
module == mainLibrary -> DeserializationStrategy.ALL
|
||||||
else -> DeserializationStrategy.EXPLICITLY_EXPORTED
|
else -> DeserializationStrategy.EXPLICITLY_EXPORTED
|
||||||
}
|
}
|
||||||
val modified = modifiedFiles[libraryFile] ?: emptyMap()
|
val modified = modifiedFiles[libraryFile] ?: emptyMap()
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
companion object {
|
companion object {
|
||||||
private val TEST_DATA_DIR_PATH = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
|
private val TEST_DATA_DIR_PATH = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
|
||||||
private const val BOX_FUNCTION_NAME = "box"
|
private const val BOX_FUNCTION_NAME = "box"
|
||||||
private const val STDLIB_ALIAS = "stdlib"
|
|
||||||
|
|
||||||
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
private const val STDLIB_MODULE_NAME = "kotlin-kotlin-stdlib-js-ir"
|
||||||
private val STDLIB_KLIB = File(System.getProperty("kotlin.js.stdlib.klib.path") ?: error("Please set stdlib path")).canonicalPath
|
private val STDLIB_KLIB = File(System.getProperty("kotlin.js.stdlib.klib.path") ?: error("Please set stdlib path")).canonicalPath
|
||||||
@@ -240,7 +239,7 @@ abstract class AbstractInvalidationTest : KotlinTestWithEnvironment() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val icCaches = cacheUpdater.actualizeCaches()
|
val icCaches = cacheUpdater.actualizeCaches()
|
||||||
verifyCacheUpdateStats(projStep.id, cacheUpdater.getDirtyFileStats(), testInfo)
|
verifyCacheUpdateStats(projStep.id, cacheUpdater.getDirtyFileLastStats(), testInfo)
|
||||||
|
|
||||||
val mainModuleName = icCaches.last().moduleExternalName
|
val mainModuleName = icCaches.last().moduleExternalName
|
||||||
val jsExecutableProducer = JsExecutableProducer(
|
val jsExecutableProducer = JsExecutableProducer(
|
||||||
|
|||||||
+1
-1
@@ -5,4 +5,4 @@ STEP 0:
|
|||||||
dirty js: lib1, lib2, main
|
dirty js: lib1, lib2, main
|
||||||
STEP 1:
|
STEP 1:
|
||||||
libs: lib1, lib2, main
|
libs: lib1, lib2, main
|
||||||
dirty js: lib2
|
dirty js: lib1, lib2
|
||||||
|
|||||||
Reference in New Issue
Block a user