[JS IR] Cleanup pir IC code
This commit is contained in:
-3
@@ -132,9 +132,6 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
|||||||
)
|
)
|
||||||
var irDceRuntimeDiagnostic: String? by NullableStringFreezableVar(null)
|
var irDceRuntimeDiagnostic: String? by NullableStringFreezableVar(null)
|
||||||
|
|
||||||
@Argument(value = "-Xir-dce-driven", description = "Perform a more experimental faster dead code elimination")
|
|
||||||
var irDceDriven: Boolean by FreezableVar(false)
|
|
||||||
|
|
||||||
@Argument(value = "-Xir-dce-print-reachability-info", description = "Print declarations' reachability info to stdout during performing DCE")
|
@Argument(value = "-Xir-dce-print-reachability-info", description = "Print declarations' reachability info to stdout during performing DCE")
|
||||||
var irDcePrintReachabilityInfo: Boolean by FreezableVar(false)
|
var irDcePrintReachabilityInfo: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,15 @@ import org.jetbrains.kotlin.incremental.js.IncrementalNextRoundChecker
|
|||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.*
|
import org.jetbrains.kotlin.ir.backend.js.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.*
|
import org.jetbrains.kotlin.ir.backend.js.ic.actualizeCacheForModule
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ic.buildCacheForModuleFiles
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ic.loadModuleCaches
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.SourceMapsInfo
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.SourceMapsInfo
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
||||||
import org.jetbrains.kotlin.js.config.*
|
import org.jetbrains.kotlin.js.config.*
|
||||||
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
||||||
@@ -78,13 +79,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
return K2JSCompilerArguments()
|
return K2JSCompilerArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
private fun usePerFileInvalidator(configuration: CompilerConfiguration): Boolean = true
|
|
||||||
|
|
||||||
private fun IcCacheInfo.toICCacheMap(): Map<String, ICCache> {
|
|
||||||
return data.map { it.key to ICCache(PersistentCacheProvider.EMPTY, PersistentCacheConsumer.EMPTY, it.value) }.toMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doExecute(
|
override fun doExecute(
|
||||||
arguments: K2JSCompilerArguments,
|
arguments: K2JSCompilerArguments,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
@@ -184,10 +178,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
val outputFile = File(outputFilePath)
|
val outputFile = File(outputFilePath)
|
||||||
|
|
||||||
val moduleName = arguments.irModuleName ?: FileUtil.getNameWithoutExtension(outputFile)
|
val moduleName = arguments.irModuleName ?: FileUtil.getNameWithoutExtension(outputFile)
|
||||||
configurationJs.put(
|
configurationJs.put(CommonConfigurationKeys.MODULE_NAME, moduleName)
|
||||||
CommonConfigurationKeys.MODULE_NAME,
|
|
||||||
moduleName
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: in this method at least 3 different compiler configurations are used (original, env.configuration, jsConfig.configuration)
|
// TODO: in this method at least 3 different compiler configurations are used (original, env.configuration, jsConfig.configuration)
|
||||||
// Such situation seems a bit buggy...
|
// Such situation seems a bit buggy...
|
||||||
@@ -246,10 +237,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
configurationJs,
|
configurationJs,
|
||||||
libraries,
|
libraries,
|
||||||
friendLibraries,
|
friendLibraries,
|
||||||
AnalyzerWithCompilerReport(config.configuration),
|
AnalyzerWithCompilerReport(config.configuration)
|
||||||
icUseGlobalSignatures = icCaches.isNotEmpty(),
|
|
||||||
icUseStdlibCache = icCaches.isNotEmpty(),
|
|
||||||
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).toICCacheMap() else emptyMap()
|
|
||||||
)
|
)
|
||||||
val result = sourceModule.jsFrontEndResult.jsAnalysisResult
|
val result = sourceModule.jsFrontEndResult.jsAnalysisResult
|
||||||
if (result is JsAnalysisResult.RetryWithAdditionalRoots) {
|
if (result is JsAnalysisResult.RetryWithAdditionalRoots) {
|
||||||
@@ -323,10 +311,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
kLib,
|
kLib,
|
||||||
configurationJs,
|
configurationJs,
|
||||||
libraries,
|
libraries,
|
||||||
friendLibraries,
|
friendLibraries
|
||||||
icUseGlobalSignatures = icCaches.isNotEmpty(),
|
|
||||||
icUseStdlibCache = icCaches.isNotEmpty(),
|
|
||||||
icCache = if (icCaches.isNotEmpty()) checkCaches(libraries, icCaches, skipLib = includes).toICCacheMap() else emptyMap()
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
sourceModule
|
sourceModule
|
||||||
@@ -389,7 +374,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
val irFactory = when {
|
val irFactory = when {
|
||||||
arguments.irDceDriven -> PersistentIrFactory()
|
|
||||||
arguments.irNewIr2Js -> IrFactoryImplForJsIC(WholeWorldStageController())
|
arguments.irNewIr2Js -> IrFactoryImplForJsIC(WholeWorldStageController())
|
||||||
else -> IrFactoryImpl
|
else -> IrFactoryImpl
|
||||||
}
|
}
|
||||||
@@ -402,7 +386,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
arguments.irDceRuntimeDiagnostic,
|
arguments.irDceRuntimeDiagnostic,
|
||||||
messageCollector
|
messageCollector
|
||||||
),
|
),
|
||||||
dceDriven = arguments.irDceDriven,
|
|
||||||
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
|
propertyLazyInitialization = arguments.irPropertyLazyInitialization,
|
||||||
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
|
baseClassIntoMetadata = arguments.irBaseClassInMetadata,
|
||||||
safeExternalBoolean = arguments.irSafeExternalBoolean,
|
safeExternalBoolean = arguments.irSafeExternalBoolean,
|
||||||
@@ -410,7 +393,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
arguments.irSafeExternalBooleanDiagnostic,
|
arguments.irSafeExternalBooleanDiagnostic,
|
||||||
messageCollector
|
messageCollector
|
||||||
),
|
),
|
||||||
lowerPerModule = false,//icCaches.isNotEmpty(),
|
|
||||||
granularity = granularity,
|
granularity = granularity,
|
||||||
icCompatibleIr2Js = arguments.irNewIr2Js,
|
icCompatibleIr2Js = arguments.irNewIr2Js,
|
||||||
)
|
)
|
||||||
@@ -597,11 +579,6 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER to SourceMapSourceEmbedding.NEVER,
|
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER to SourceMapSourceEmbedding.NEVER,
|
||||||
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING to SourceMapSourceEmbedding.INLINING
|
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING to SourceMapSourceEmbedding.INLINING
|
||||||
)
|
)
|
||||||
private val produceMap = mapOf(
|
|
||||||
null to ProduceKind.DEFAULT,
|
|
||||||
"js" to ProduceKind.JS,
|
|
||||||
"klib" to ProduceKind.KLIB
|
|
||||||
)
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
|
|||||||
@@ -5,13 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js
|
package org.jetbrains.kotlin.ir.backend.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower
|
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.icCompile
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
|
import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||||
@@ -20,8 +18,6 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.StageController
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.noUnboundLeft
|
import org.jetbrains.kotlin.ir.util.noUnboundLeft
|
||||||
@@ -53,13 +49,11 @@ fun compile(
|
|||||||
phaseConfig: PhaseConfig,
|
phaseConfig: PhaseConfig,
|
||||||
irFactory: IrFactory,
|
irFactory: IrFactory,
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
exportedDeclarations: Set<FqName> = emptySet(),
|
||||||
dceDriven: Boolean = false,
|
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
||||||
es6mode: Boolean = false,
|
es6mode: Boolean = false,
|
||||||
propertyLazyInitialization: Boolean,
|
propertyLazyInitialization: Boolean,
|
||||||
verifySignatures: Boolean = true,
|
verifySignatures: Boolean = true,
|
||||||
baseClassIntoMetadata: Boolean = false,
|
baseClassIntoMetadata: Boolean = false,
|
||||||
lowerPerModule: Boolean = false,
|
|
||||||
safeExternalBoolean: Boolean = false,
|
safeExternalBoolean: Boolean = false,
|
||||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
||||||
filesToLower: Set<String>? = null,
|
filesToLower: Set<String>? = null,
|
||||||
@@ -67,20 +61,7 @@ fun compile(
|
|||||||
icCompatibleIr2Js: Boolean = false,
|
icCompatibleIr2Js: Boolean = false,
|
||||||
): LoweredIr {
|
): LoweredIr {
|
||||||
|
|
||||||
if (lowerPerModule) {
|
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) =
|
||||||
return icCompile(
|
|
||||||
depsDescriptors,
|
|
||||||
exportedDeclarations,
|
|
||||||
dceRuntimeDiagnostic,
|
|
||||||
es6mode,
|
|
||||||
propertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata,
|
|
||||||
safeExternalBoolean,
|
|
||||||
safeExternalBooleanDiagnostic,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, _) =
|
|
||||||
loadIr(depsDescriptors, irFactory, verifySignatures, filesToLower, loadFunctionInterfacesIntoStdlib = true)
|
loadIr(depsDescriptors, irFactory, verifySignatures, filesToLower, loadFunctionInterfacesIntoStdlib = true)
|
||||||
|
|
||||||
return compileIr(
|
return compileIr(
|
||||||
@@ -93,12 +74,10 @@ fun compile(
|
|||||||
deserializer,
|
deserializer,
|
||||||
phaseConfig,
|
phaseConfig,
|
||||||
exportedDeclarations,
|
exportedDeclarations,
|
||||||
dceDriven,
|
|
||||||
dceRuntimeDiagnostic,
|
dceRuntimeDiagnostic,
|
||||||
es6mode,
|
es6mode,
|
||||||
propertyLazyInitialization,
|
propertyLazyInitialization,
|
||||||
baseClassIntoMetadata,
|
baseClassIntoMetadata,
|
||||||
lowerPerModule,
|
|
||||||
safeExternalBoolean,
|
safeExternalBoolean,
|
||||||
safeExternalBooleanDiagnostic,
|
safeExternalBooleanDiagnostic,
|
||||||
granularity,
|
granularity,
|
||||||
@@ -116,12 +95,10 @@ fun compileIr(
|
|||||||
deserializer: JsIrLinker,
|
deserializer: JsIrLinker,
|
||||||
phaseConfig: PhaseConfig,
|
phaseConfig: PhaseConfig,
|
||||||
exportedDeclarations: Set<FqName>,
|
exportedDeclarations: Set<FqName>,
|
||||||
dceDriven: Boolean,
|
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic?,
|
dceRuntimeDiagnostic: RuntimeDiagnostic?,
|
||||||
es6mode: Boolean,
|
es6mode: Boolean,
|
||||||
propertyLazyInitialization: Boolean,
|
propertyLazyInitialization: Boolean,
|
||||||
baseClassIntoMetadata: Boolean,
|
baseClassIntoMetadata: Boolean,
|
||||||
lowerPerModule: Boolean,
|
|
||||||
safeExternalBoolean: Boolean,
|
safeExternalBoolean: Boolean,
|
||||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
safeExternalBooleanDiagnostic: RuntimeDiagnostic?,
|
||||||
granularity: JsGenerationGranularity,
|
granularity: JsGenerationGranularity,
|
||||||
@@ -170,55 +147,13 @@ fun compileIr(
|
|||||||
// TODO should be done incrementally
|
// TODO should be done incrementally
|
||||||
generateJsTests(context, allModules.last())
|
generateJsTests(context, allModules.last())
|
||||||
|
|
||||||
if (dceDriven) {
|
(irFactory.stageController as? WholeWorldStageController)?.let {
|
||||||
val controller = MutableController(context, pirLowerings)
|
lowerPreservingTags(allModules, context, phaseConfig, it)
|
||||||
|
} ?: jsPhases.invokeToplevel(phaseConfig, context, allModules)
|
||||||
check(irFactory is PersistentIrFactory)
|
|
||||||
irFactory.stageController = controller
|
|
||||||
|
|
||||||
controller.currentStage = controller.lowerings.size + 1
|
|
||||||
|
|
||||||
eliminateDeadDeclarations(allModules, context)
|
|
||||||
|
|
||||||
irFactory.stageController = StageController(controller.currentStage)
|
|
||||||
} else {
|
|
||||||
// TODO is this reachable when lowerPerModule == true?
|
|
||||||
if (lowerPerModule) {
|
|
||||||
val controller = WholeWorldStageController()
|
|
||||||
check(irFactory is PersistentIrFactory)
|
|
||||||
irFactory.stageController = controller
|
|
||||||
allModules.forEach {
|
|
||||||
lowerPreservingIcData(it, context, controller)
|
|
||||||
}
|
|
||||||
irFactory.stageController = object : StageController(irFactory.stageController.currentStage) {}
|
|
||||||
} else {
|
|
||||||
(irFactory.stageController as? WholeWorldStageController)?.let {
|
|
||||||
lowerPreservingTags(allModules, context, phaseConfig, it)
|
|
||||||
} ?: jsPhases.invokeToplevel(phaseConfig, context, allModules)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return LoweredIr(context, moduleFragment, allModules)
|
return LoweredIr(context, moduleFragment, allModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext, controller: WholeWorldStageController) {
|
|
||||||
// Lower all the things
|
|
||||||
controller.currentStage = 0
|
|
||||||
|
|
||||||
pirLowerings.forEachIndexed { i, lowering ->
|
|
||||||
controller.currentStage = i + 1
|
|
||||||
when (lowering) {
|
|
||||||
is DeclarationLowering ->
|
|
||||||
lowering.declarationTransformer(context).lower(module)
|
|
||||||
is BodyLowering ->
|
|
||||||
lowering.bodyLowering(context).lower(module)
|
|
||||||
is ModuleLowering -> { /*TODO what about other lowerings? */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.currentStage = pirLowerings.size + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun generateJsCode(
|
fun generateJsCode(
|
||||||
context: JsIrBackendContext,
|
context: JsIrBackendContext,
|
||||||
moduleFragment: IrModuleFragment,
|
moduleFragment: IrModuleFragment,
|
||||||
|
|||||||
@@ -5,123 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
package org.jetbrains.kotlin.ir.backend.js.ic
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.MainModule
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.toByteArray
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.security.MessageDigest
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.random.nextULong
|
|
||||||
|
|
||||||
// TODO: Proper version of the compiler (should take changes to lowerings into account)
|
|
||||||
private val compilerVersion = Random.nextULong()
|
|
||||||
|
|
||||||
private fun IcCacheInfo.toICCacheMap(): Map<String, ICCache> {
|
|
||||||
return data.map { it.key to ICCache(PersistentCacheProvider.EMPTY, PersistentCacheConsumer.EMPTY, it.value) }.toMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO more parameters for lowerings
|
|
||||||
// Returns true if caches were built. False if caches were up-to-date.
|
|
||||||
fun buildCache(
|
|
||||||
cachePath: String,
|
|
||||||
project: Project,
|
|
||||||
mainModule: MainModule.Klib,
|
|
||||||
configuration: CompilerConfiguration,
|
|
||||||
dependencies: Collection<String>,
|
|
||||||
friendDependencies: Collection<String>,
|
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
|
||||||
forceClean: Boolean = false,
|
|
||||||
icCache: IcCacheInfo = IcCacheInfo.EMPTY,
|
|
||||||
): Boolean {
|
|
||||||
val dependencyHashes = dependencies.mapNotNull {
|
|
||||||
val path = File(it).canonicalPath
|
|
||||||
icCache.md5[path]
|
|
||||||
} + compilerVersion
|
|
||||||
|
|
||||||
val md5 = File(mainModule.libPath).md5(dependencyHashes)
|
|
||||||
|
|
||||||
if (!forceClean) {
|
|
||||||
val oldCacheInfo = CacheInfo.load(cachePath)
|
|
||||||
if (oldCacheInfo != null && md5 == oldCacheInfo.flatHash) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val icDir = File(cachePath)
|
|
||||||
icDir.listFiles { file: File -> file.name.startsWith("ic-") }!!.forEach { it.deleteRecursively() }
|
|
||||||
File(icDir, "info").delete()
|
|
||||||
icDir.mkdirs()
|
|
||||||
|
|
||||||
val icData = prepareSingleLibraryIcCache(project, configuration, mainModule.libPath, dependencies, friendDependencies, exportedDeclarations, icCache.toICCacheMap())
|
|
||||||
|
|
||||||
icData.serializedIcData.writeTo(File(cachePath))
|
|
||||||
|
|
||||||
CacheInfo(cachePath, mainModule.libPath, md5, 0UL).save()
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun File.md5(additional: Iterable<ULong> = emptyList()): ULong {
|
|
||||||
val md5 = MessageDigest.getInstance("MD5")
|
|
||||||
|
|
||||||
for (ul in additional) {
|
|
||||||
md5.update(ul.toLong().toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
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)
|
|
||||||
or ((d[3].toULong() and 0xFFUL) shl 24)
|
|
||||||
or ((d[4].toULong() and 0xFFUL) shl 32)
|
|
||||||
or ((d[5].toULong() and 0xFFUL) shl 40)
|
|
||||||
or ((d[6].toULong() and 0xFFUL) shl 48)
|
|
||||||
or ((d[7].toULong() and 0xFFUL) shl 56)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkCaches(
|
|
||||||
dependencies: Collection<String>,
|
|
||||||
cachePaths: List<String>,
|
|
||||||
skipLib: String? = null,
|
|
||||||
): IcCacheInfo {
|
|
||||||
val skipLibPath = File(skipLib).canonicalPath
|
|
||||||
val allLibs = dependencies.map { File(it).canonicalPath }.toSet() - skipLibPath
|
|
||||||
|
|
||||||
val caches = cachePaths.map { CacheInfo.load(it) ?: error("Cannot load IC cache from ${it}") }
|
|
||||||
|
|
||||||
val missedLibs = allLibs - caches.map { it.libPath }
|
|
||||||
if (!missedLibs.isEmpty()) {
|
|
||||||
error("Missing caches for libraries: ${missedLibs}")
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = mutableMapOf<String, SerializedIcData>()
|
|
||||||
val md5 = mutableMapOf<String, ULong>()
|
|
||||||
|
|
||||||
for (c in caches) {
|
|
||||||
if (c.libPath !in allLibs) error("Missing library: ${c.libPath}")
|
|
||||||
|
|
||||||
result[c.libPath] = File(c.path).readIcData()
|
|
||||||
md5[c.libPath] = c.flatHash
|
|
||||||
}
|
|
||||||
|
|
||||||
return IcCacheInfo(result, md5)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO md5 hash
|
// 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) {
|
||||||
@@ -145,13 +30,3 @@ data class CacheInfo(val path: String, val libPath: String, var flatHash: ULong,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class IcCacheInfo(
|
|
||||||
val data: Map<String, SerializedIcData>,
|
|
||||||
val md5: Map<String, ULong>,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
val EMPTY = IcCacheInfo(emptyMap(), emptyMap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower
|
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.*
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.generateJsTests
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.path
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
|
||||||
import org.jetbrains.kotlin.ir.util.KotlinLikeDumpOptions
|
|
||||||
import org.jetbrains.kotlin.ir.util.dumpKotlinLike
|
|
||||||
import org.jetbrains.kotlin.ir.util.noUnboundLeft
|
|
||||||
import org.jetbrains.kotlin.js.config.RuntimeDiagnostic
|
|
||||||
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import java.io.PrintWriter
|
|
||||||
|
|
||||||
fun prepareSingleLibraryIcCache(
|
|
||||||
project: Project,
|
|
||||||
configuration: CompilerConfiguration,
|
|
||||||
libPath: String,
|
|
||||||
dependencies: Collection<String>,
|
|
||||||
friendDependencies: Collection<String> = emptyList(),
|
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
|
||||||
icCache: Map<String, ICCache> = emptyMap(),
|
|
||||||
): ICCache {
|
|
||||||
val irFactory = PersistentIrFactory()
|
|
||||||
val controller = WholeWorldStageController()
|
|
||||||
irFactory.stageController = controller
|
|
||||||
|
|
||||||
val depsDescriptor = ModulesStructure(
|
|
||||||
project,
|
|
||||||
MainModule.Klib(libPath),
|
|
||||||
configuration,
|
|
||||||
dependencies,
|
|
||||||
friendDependencies,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
icCache
|
|
||||||
)
|
|
||||||
val (context, deserializer, allModules) = prepareIr(
|
|
||||||
depsDescriptor,
|
|
||||||
exportedDeclarations,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
irFactory,
|
|
||||||
)
|
|
||||||
|
|
||||||
val moduleFragment = allModules.last()
|
|
||||||
|
|
||||||
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
|
|
||||||
|
|
||||||
// generateTests(context, moduleFragment)
|
|
||||||
|
|
||||||
lowerPreservingIcData(moduleFragment, context, controller)
|
|
||||||
|
|
||||||
return ICCache(
|
|
||||||
PersistentCacheProvider.EMPTY,
|
|
||||||
PersistentCacheConsumer.EMPTY,
|
|
||||||
IcSerializer(
|
|
||||||
context.irBuiltIns,
|
|
||||||
context.mapping,
|
|
||||||
irFactory,
|
|
||||||
deserializer,
|
|
||||||
moduleFragment
|
|
||||||
).serializeDeclarations(irFactory.allDeclarations)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinResolvedLibrary.allDependencies(): List<KotlinResolvedLibrary> {
|
|
||||||
val visited = mutableSetOf<KotlinResolvedLibrary>()
|
|
||||||
|
|
||||||
val result = mutableListOf<KotlinResolvedLibrary>()
|
|
||||||
|
|
||||||
fun KotlinResolvedLibrary.dfs() {
|
|
||||||
visited += this
|
|
||||||
|
|
||||||
resolvedDependencies.forEach {
|
|
||||||
if (it !in visited) {
|
|
||||||
it.dfs()
|
|
||||||
result += it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dfs()
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dumpIr(module: IrModuleFragment, fileName: String) {
|
|
||||||
val dumpOptions = KotlinLikeDumpOptions(printElseAsTrue = true)
|
|
||||||
|
|
||||||
var actual = ""
|
|
||||||
|
|
||||||
for (file in module.files) {
|
|
||||||
actual += file.path + "\n"
|
|
||||||
actual += run {
|
|
||||||
var r = ""
|
|
||||||
|
|
||||||
file.declarations.map { it.dumpKotlinLike(dumpOptions) }.sorted().forEach { r += it }
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
actual += "\n"
|
|
||||||
}
|
|
||||||
PrintWriter("/home/ab/vcs/kotlin/$fileName.txt").use {
|
|
||||||
it.print(actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun icCompile(
|
|
||||||
depsDescriptor: ModulesStructure,
|
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
|
||||||
es6mode: Boolean = false,
|
|
||||||
propertyLazyInitialization: Boolean,
|
|
||||||
baseClassIntoMetadata: Boolean = false,
|
|
||||||
safeExternalBoolean: Boolean = false,
|
|
||||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
|
||||||
): LoweredIr {
|
|
||||||
|
|
||||||
val irFactory = PersistentIrFactory()
|
|
||||||
val controller = WholeWorldStageController()
|
|
||||||
irFactory.stageController = controller
|
|
||||||
|
|
||||||
val (context, _, allModules, _, loweredIrLoaded) = prepareIr(
|
|
||||||
depsDescriptor,
|
|
||||||
exportedDeclarations,
|
|
||||||
dceRuntimeDiagnostic,
|
|
||||||
es6mode,
|
|
||||||
propertyLazyInitialization,
|
|
||||||
irFactory,
|
|
||||||
baseClassIntoMetadata,
|
|
||||||
safeExternalBoolean,
|
|
||||||
safeExternalBooleanDiagnostic
|
|
||||||
)
|
|
||||||
|
|
||||||
val modulesToLower = allModules.filter { it !in loweredIrLoaded }
|
|
||||||
|
|
||||||
if (!modulesToLower.isEmpty()) {
|
|
||||||
// This won't work incrementally
|
|
||||||
modulesToLower.forEach { module ->
|
|
||||||
moveBodilessDeclarationsToSeparatePlace(context, module)
|
|
||||||
}
|
|
||||||
|
|
||||||
generateJsTests(context, modulesToLower.last())
|
|
||||||
|
|
||||||
modulesToLower.forEach {
|
|
||||||
lowerPreservingIcData(it, context, controller)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dumpIr(allModules.first(), "simple-dump${if (useStdlibCache) "-actual" else ""}")
|
|
||||||
|
|
||||||
return LoweredIr(context, allModules.last(), allModules)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext, controller: WholeWorldStageController) {
|
|
||||||
// Lower all the things
|
|
||||||
controller.currentStage = 0
|
|
||||||
|
|
||||||
pirLowerings.forEachIndexed { i, lowering ->
|
|
||||||
controller.currentStage = i + 1
|
|
||||||
when (lowering) {
|
|
||||||
is DeclarationLowering ->
|
|
||||||
lowering.declarationTransformer(context).lower(module)
|
|
||||||
is BodyLowering ->
|
|
||||||
lowering.bodyLowering(context).lower(module)
|
|
||||||
else -> TODO("what about other lowerings?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.currentStage = pirLowerings.size + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareIr(
|
|
||||||
depsDescriptor: ModulesStructure,
|
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
|
||||||
dceRuntimeDiagnostic: RuntimeDiagnostic? = null,
|
|
||||||
es6mode: Boolean = false,
|
|
||||||
propertyLazyInitialization: Boolean,
|
|
||||||
irFactory: PersistentIrFactory,
|
|
||||||
baseClassIntoMetadata: Boolean = false,
|
|
||||||
safeExternalBoolean: Boolean = false,
|
|
||||||
safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null,
|
|
||||||
): PreparedIr {
|
|
||||||
val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName, loweredIrLoaded) =
|
|
||||||
loadIr(depsDescriptor, irFactory, false)
|
|
||||||
|
|
||||||
val moduleDescriptor = moduleFragment.descriptor
|
|
||||||
|
|
||||||
val allModules = when (depsDescriptor.mainModule) {
|
|
||||||
is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment)
|
|
||||||
is MainModule.Klib -> dependencyModules
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = JsIrBackendContext(
|
|
||||||
moduleDescriptor,
|
|
||||||
irBuiltIns,
|
|
||||||
symbolTable,
|
|
||||||
allModules.first(),
|
|
||||||
exportedDeclarations,
|
|
||||||
depsDescriptor.compilerConfiguration,
|
|
||||||
es6mode = es6mode,
|
|
||||||
dceRuntimeDiagnostic = dceRuntimeDiagnostic,
|
|
||||||
propertyLazyInitialization = propertyLazyInitialization,
|
|
||||||
baseClassIntoMetadata = baseClassIntoMetadata,
|
|
||||||
safeExternalBoolean = safeExternalBoolean,
|
|
||||||
safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic,
|
|
||||||
mapping = deserializer.mapping,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Load declarations referenced during `context` initialization
|
|
||||||
val irProviders = listOf(deserializer)
|
|
||||||
ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies()
|
|
||||||
|
|
||||||
deserializer.postProcess()
|
|
||||||
symbolTable.noUnboundLeft("Unbound symbols at the end of linker")
|
|
||||||
|
|
||||||
deserializer.loadIcIr { moveBodilessDeclarationsToSeparatePlace(context, it) }
|
|
||||||
|
|
||||||
return PreparedIr(context, deserializer, allModules, moduleToName, loweredIrLoaded)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class PreparedIr(
|
|
||||||
val context: JsIrBackendContext,
|
|
||||||
val linker: JsIrLinker,
|
|
||||||
val allModules: List<IrModuleFragment>,
|
|
||||||
val moduleToName: Map<IrModuleFragment, String>,
|
|
||||||
val loweredIrLoaded: Set<IrModuleFragment>,
|
|
||||||
)
|
|
||||||
@@ -252,7 +252,7 @@ private fun createLinker(
|
|||||||
val moduleDescriptor = loadedModules.keys.last()
|
val moduleDescriptor = loadedModules.keys.last()
|
||||||
val typeTranslator = TypeTranslatorImpl(symbolTable, configuration.languageVersionSettings, moduleDescriptor)
|
val typeTranslator = TypeTranslatorImpl(symbolTable, configuration.languageVersionSettings, moduleDescriptor)
|
||||||
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
|
||||||
return JsIrLinker(null, logger, irBuiltIns, symbolTable, null, null)
|
return JsIrLinker(null, logger, irBuiltIns, symbolTable, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-22
@@ -28,7 +28,7 @@ private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte
|
|||||||
|
|
||||||
private fun createFileCacheId(fileName: String): String = md5.digest(fileName.encodeToByteArray()).toHex()
|
private fun createFileCacheId(fileName: String): String = md5.digest(fileName.encodeToByteArray()).toHex()
|
||||||
|
|
||||||
class ICCache(val dataProvider: PersistentCacheProvider, val dataConsumer: PersistentCacheConsumer, val serializedIcData: SerializedIcData)
|
class ICCache()
|
||||||
|
|
||||||
class FileCache(val name: String, var ast: ByteArray?, var dts: ByteArray?, var sourceMap: ByteArray?)
|
class FileCache(val name: String, var ast: ByteArray?, var dts: ByteArray?, var sourceMap: ByteArray?)
|
||||||
class ModuleCache(val name: String, val asts: Map<String, FileCache>)
|
class ModuleCache(val name: String, val asts: Map<String, FileCache>)
|
||||||
@@ -36,8 +36,6 @@ class ModuleCache(val name: String, val asts: Map<String, FileCache>)
|
|||||||
interface PersistentCacheProvider {
|
interface PersistentCacheProvider {
|
||||||
fun fileFingerPrint(path: String): Hash
|
fun fileFingerPrint(path: String): Hash
|
||||||
|
|
||||||
fun serializedParts(path: String): SerializedIcDataForFile
|
|
||||||
|
|
||||||
fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>>
|
fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>>
|
||||||
|
|
||||||
fun inlineHashes(path: String, sigResolver: (Int) -> IdSignature): Map<IdSignature, TransHash>
|
fun inlineHashes(path: String, sigResolver: (Int) -> IdSignature): Map<IdSignature, TransHash>
|
||||||
@@ -60,10 +58,6 @@ interface PersistentCacheProvider {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serializedParts(path: String): SerializedIcDataForFile {
|
|
||||||
TODO("..")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
@@ -116,11 +110,6 @@ class PersistentCacheProviderImpl(private val cachePath: String) : PersistentCac
|
|||||||
} else 0
|
} else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serializedParts(path: String): SerializedIcDataForFile {
|
|
||||||
val fileDir = path.fileDir
|
|
||||||
return fileDir.readIcDataBinary()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseHashList(
|
private fun parseHashList(
|
||||||
fileDir: File,
|
fileDir: File,
|
||||||
fileName: String,
|
fileName: String,
|
||||||
@@ -209,7 +198,6 @@ interface PersistentCacheConsumer {
|
|||||||
fun commitInlineFunctions(path: String, hashes: Collection<Pair<IdSignature, TransHash>>, sigResolver: (IdSignature) -> Int)
|
fun commitInlineFunctions(path: String, hashes: Collection<Pair<IdSignature, TransHash>>, sigResolver: (IdSignature) -> Int)
|
||||||
fun commitFileFingerPrint(path: String, fingerprint: Hash)
|
fun commitFileFingerPrint(path: String, fingerprint: Hash)
|
||||||
fun commitInlineGraph(path: String, hashes: Collection<Pair<IdSignature, TransHash>>, sigResolver: (IdSignature) -> Int)
|
fun commitInlineGraph(path: String, hashes: Collection<Pair<IdSignature, TransHash>>, sigResolver: (IdSignature) -> Int)
|
||||||
fun commitICCacheData(path: String, icData: SerializedIcDataForFile)
|
|
||||||
fun commitBinaryAst(path: String, astData: ByteArray)
|
fun commitBinaryAst(path: String, astData: ByteArray)
|
||||||
fun commitBinaryDts(path: String, dstData: ByteArray)
|
fun commitBinaryDts(path: String, dstData: ByteArray)
|
||||||
fun commitSourceMap(path: String, mapData: ByteArray)
|
fun commitSourceMap(path: String, mapData: ByteArray)
|
||||||
@@ -236,9 +224,6 @@ interface PersistentCacheConsumer {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitICCacheData(path: String, icData: SerializedIcDataForFile) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun invalidateForFile(path: String) {
|
override fun invalidateForFile(path: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,12 +291,6 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
|
|||||||
commitFileHashMapping(path, inlineGraphFile, hashes, sigResolver)
|
commitFileHashMapping(path, inlineGraphFile, hashes, sigResolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitICCacheData(path: String, icData: SerializedIcDataForFile) {
|
|
||||||
val fileId = createFileCacheId(path)
|
|
||||||
val fileDir = File(File(cachePath), fileId)
|
|
||||||
icData.writeData(fileDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun invalidateForFile(path: String) {
|
override fun invalidateForFile(path: String) {
|
||||||
val fileId = createFileCacheId(path)
|
val fileId = createFileCacheId(path)
|
||||||
val cacheDir = File(cachePath)
|
val cacheDir = File(cachePath)
|
||||||
|
|||||||
-268
@@ -1,268 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.overrides.DefaultFakeOverrideClassFilter
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.*
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsMappingState
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
|
||||||
import org.jetbrains.kotlin.ir.serialization.CarrierDeserializer
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
|
||||||
import org.jetbrains.kotlin.library.SerializedIrFile
|
|
||||||
import org.jetbrains.kotlin.library.impl.DeclarationId
|
|
||||||
import org.jetbrains.kotlin.library.impl.DeclarationIrTableMemoryReader
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrArrayMemoryReader
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrLongArrayMemoryReader
|
|
||||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoIrFile
|
|
||||||
|
|
||||||
class IcFileDeserializer(
|
|
||||||
val linker: JsIrLinker,
|
|
||||||
private val file: IrFile,
|
|
||||||
originalFileReader: IrLibraryFileFromBytes,
|
|
||||||
fileProto: ProtoIrFile,
|
|
||||||
deserializeBodies: Boolean,
|
|
||||||
allowErrorNodes: Boolean,
|
|
||||||
deserializeInlineFunctions: Boolean,
|
|
||||||
val moduleDeserializer: IrModuleDeserializer,
|
|
||||||
val originalEnqueue: IdSignature.(IcFileDeserializer) -> Unit,
|
|
||||||
val icFileData: SerializedIcDataForFile,
|
|
||||||
val mappingState: JsMappingState,
|
|
||||||
val enqueue: IdSignature.(IcFileDeserializer) -> Unit,
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val deserializedSymbols = mutableMapOf<IdSignature, IrSymbol>()
|
|
||||||
val originalSymbolDeserializer =
|
|
||||||
IrSymbolDeserializer(
|
|
||||||
linker.symbolTable,
|
|
||||||
originalFileReader,
|
|
||||||
file.symbol,
|
|
||||||
fileProto.actualList,
|
|
||||||
{ idSig ->
|
|
||||||
idSig.enqueue(this)
|
|
||||||
if (idSig.hasTopLevel) {
|
|
||||||
idSig.topLevelSignature().originalEnqueue(this)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
linker::handleExpectActualMapping,
|
|
||||||
enqueueAllDeclarations = true,
|
|
||||||
deserializedSymbols = deserializedSymbols,
|
|
||||||
deserializePublicSymbol = ::deserializePublicSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
private val originalDeclarationDeserializer = IrDeclarationDeserializer(
|
|
||||||
linker.builtIns,
|
|
||||||
linker.symbolTable,
|
|
||||||
linker.symbolTable.irFactory,
|
|
||||||
originalFileReader,
|
|
||||||
file,
|
|
||||||
allowErrorNodes,
|
|
||||||
deserializeInlineFunctions,
|
|
||||||
deserializeBodies,
|
|
||||||
originalSymbolDeserializer,
|
|
||||||
linker.fakeOverrideBuilder.platformSpecificClassFilter,
|
|
||||||
linker.fakeOverrideBuilder,
|
|
||||||
allowRedeclaration = true,
|
|
||||||
compatibilityMode = CompatibilityMode.CURRENT
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun deserializePublicSymbol(idSig: IdSignature, kind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
// TODO: reference lowered declarations cross-module
|
|
||||||
if (kind == BinarySymbolData.SymbolKind.FILE_SYMBOL) return file.symbol
|
|
||||||
|
|
||||||
val actualModuleDeserializer = moduleDeserializer.findModuleDeserializerForTopLevelId(idSig)
|
|
||||||
?: linker.handleSignatureIdNotFoundInModuleWithDependencies(idSig, moduleDeserializer)
|
|
||||||
|
|
||||||
return actualModuleDeserializer.deserializeIrSymbol(idSig, kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalFileDeserializer =
|
|
||||||
IrFileDeserializer(file, originalFileReader, fileProto, originalSymbolDeserializer, originalDeclarationDeserializer)
|
|
||||||
|
|
||||||
private val originalSignatureQueue = ArrayDeque<IdSignature>() // Top-level signatures to be deserialized from original KLIB
|
|
||||||
|
|
||||||
// Returns whether this file should be queued for deserialization
|
|
||||||
fun enqueueForDeserialization(idSig: IdSignature): Boolean {
|
|
||||||
originalSignatureQueue.addLast(idSig)
|
|
||||||
return originalSignatureQueue.size == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializePendingSignatures() {
|
|
||||||
while (!originalSignatureQueue.isEmpty()) {
|
|
||||||
val signature = originalSignatureQueue.removeFirst()
|
|
||||||
deserializeAnyDeclaration(signature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explicitly exported declarations (e.g. top-level initializers) must be deserialized before all other declarations.
|
|
||||||
// Thus we schedule their deserialization in deserializer's constructor.
|
|
||||||
val explicitlyExportedToCompiler: Collection<IdSignature> = fileProto.explicitlyExportedToCompilerList.map {
|
|
||||||
val symbolData = originalSymbolDeserializer.parseSymbolData(it)
|
|
||||||
originalSymbolDeserializer.deserializeIdSignature(symbolData.signatureId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allOriginalDeclarationSignatures(): Collection<IdSignature> = originalFileDeserializer.reversedSignatureIndex.keys
|
|
||||||
|
|
||||||
// IC data processing starts here
|
|
||||||
|
|
||||||
private val icFileReader = IrLibraryFileFromBytes(FileReaderFromSerializedIrFile(icFileData.file))
|
|
||||||
|
|
||||||
val symbolDeserializer = IrSymbolDeserializer(
|
|
||||||
linker.symbolTable,
|
|
||||||
icFileReader,
|
|
||||||
file.symbol,
|
|
||||||
emptyList(),
|
|
||||||
{ idSig -> idSig.enqueue(this) },
|
|
||||||
{ _, s -> s },
|
|
||||||
enqueueAllDeclarations = true,
|
|
||||||
deserializedSymbols = deserializedSymbols,
|
|
||||||
deserializePublicSymbol = ::deserializePublicSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
private val declarationDeserializer = IrDeclarationDeserializer(
|
|
||||||
linker.builtIns,
|
|
||||||
linker.symbolTable,
|
|
||||||
linker.symbolTable.irFactory,
|
|
||||||
icFileReader,
|
|
||||||
file,
|
|
||||||
allowErrorNodes = true,
|
|
||||||
deserializeInlineFunctions = true,
|
|
||||||
deserializeBodies = true,
|
|
||||||
symbolDeserializer,
|
|
||||||
DefaultFakeOverrideClassFilter,
|
|
||||||
linker.fakeOverrideBuilder,
|
|
||||||
skipMutableState = true,
|
|
||||||
additionalStatementOriginIndex = additionalStatementOriginIndex,
|
|
||||||
allowErrorStatementOrigins = true,
|
|
||||||
allowRedeclaration = true,
|
|
||||||
compatibilityMode = CompatibilityMode.CURRENT,
|
|
||||||
allowErrorLoopIndices = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
private val protoFile: ProtoIrFile by lazy {
|
|
||||||
ProtoIrFile.parseFrom(icFileData.file.fileData.codedInputStream, ExtensionRegistryLite.newInstance())
|
|
||||||
}
|
|
||||||
|
|
||||||
private val carrierDeserializer by lazy {
|
|
||||||
CarrierDeserializer(declarationDeserializer, icFileData.carriers)
|
|
||||||
}
|
|
||||||
|
|
||||||
val reversedSignatureIndex: Map<IdSignature, Int> =
|
|
||||||
protoFile.declarationIdList.associateBy { symbolDeserializer.deserializeIdSignature(it) }
|
|
||||||
|
|
||||||
val visited = HashSet<IdSignature>()
|
|
||||||
|
|
||||||
val mappingsDeserializer by lazy {
|
|
||||||
mappingState.mappingsDeserializer(icFileData.mappings, { code ->
|
|
||||||
val symbolData = symbolDeserializer.parseSymbolData(code)
|
|
||||||
symbolDeserializer.deserializeIdSignature(symbolData.signatureId)
|
|
||||||
}) {
|
|
||||||
deserializeIrSymbol(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val containerSigToOrder by lazy {
|
|
||||||
mutableMapOf<IdSignature, ByteArray>().also { map ->
|
|
||||||
val containerIds = IrLongArrayMemoryReader(icFileData.order.containerSignatures).array
|
|
||||||
val declarationIds = IrArrayMemoryReader(icFileData.order.declarationSignatures)
|
|
||||||
|
|
||||||
containerIds.forEachIndexed { index, id ->
|
|
||||||
val symbolData = symbolDeserializer.parseSymbolData(id)
|
|
||||||
val containerSig = symbolDeserializer.deserializeIdSignature(symbolData.signatureId)
|
|
||||||
|
|
||||||
map[containerSig] = declarationIds.tableItemBytes(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadClassOrder(classSignature: IdSignature): List<IrSymbol>? {
|
|
||||||
val bytes = containerSigToOrder[classSignature] ?: return null
|
|
||||||
|
|
||||||
return IrLongArrayMemoryReader(bytes).array.map { deserializeIrSymbol(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeDeclaration(idSig: IdSignature): IrDeclaration? {
|
|
||||||
cachedDeclaration(idSig)?.let { return it }
|
|
||||||
|
|
||||||
val idSigIndex = reversedSignatureIndex[idSig] ?: return null
|
|
||||||
val declarationProto = icFileReader.declaration(idSigIndex)
|
|
||||||
return declarationDeserializer.deserializeDeclaration(declarationProto)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return declaration iff it was already deserialized
|
|
||||||
private fun cachedDeclaration(idSig: IdSignature): IrDeclaration? {
|
|
||||||
val symbol = deserializedSymbols[idSig] // Same map is used for both symbol deserializers
|
|
||||||
|
|
||||||
if (symbol != null && symbol.isBound) return symbol.owner as? IrDeclaration
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeAnyDeclaration(idSig: IdSignature): IrDeclaration? {
|
|
||||||
cachedDeclaration(idSig)?.let { return it }
|
|
||||||
|
|
||||||
// TODO fast path?
|
|
||||||
val maybeTopLevel = if (idSig.hasTopLevel) idSig.topLevelSignature() else idSig
|
|
||||||
|
|
||||||
if (maybeTopLevel in originalFileDeserializer.reversedSignatureIndex.keys) {
|
|
||||||
originalFileDeserializer.deserializeFileImplicitDataIfFirstUse()
|
|
||||||
return originalFileDeserializer.deserializeDeclaration(maybeTopLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
reversedSignatureIndex[maybeTopLevel]?.let { idSigIndex ->
|
|
||||||
val declarationProto = icFileReader.declaration(idSigIndex)
|
|
||||||
return declarationDeserializer.deserializeDeclaration(declarationProto)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: error?
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deserializeIrSymbol(code: Long): IrSymbol {
|
|
||||||
return symbolDeserializer.deserializeIrSymbol(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
idSig.enqueue(this)
|
|
||||||
return symbolDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun injectCarriers(declaration: IrDeclaration, signature: IdSignature) {
|
|
||||||
carrierDeserializer.injectCarriers(declaration, signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val additionalStatementOrigins = JsStatementOrigins::class.nestedClasses.toList()
|
|
||||||
private val additionalStatementOriginIndex =
|
|
||||||
additionalStatementOrigins.mapNotNull { it.objectInstance as? IrStatementOriginImpl }.associateBy { it.debugName }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FileReaderFromSerializedIrFile(val irFile: SerializedIrFile) : IrLibraryBytesSource() {
|
|
||||||
private val declarationReader = DeclarationIrTableMemoryReader(irFile.declarations)
|
|
||||||
private val typeReader = IrArrayMemoryReader(irFile.types)
|
|
||||||
private val signatureReader = IrArrayMemoryReader(irFile.signatures)
|
|
||||||
private val stringReader = IrArrayMemoryReader(irFile.strings)
|
|
||||||
private val bodyReader = IrArrayMemoryReader(irFile.bodies)
|
|
||||||
|
|
||||||
override fun irDeclaration(index: Int): ByteArray = declarationReader.tableItemBytes(DeclarationId(index))
|
|
||||||
|
|
||||||
override fun type(index: Int): ByteArray = typeReader.tableItemBytes(index)
|
|
||||||
|
|
||||||
override fun signature(index: Int): ByteArray = signatureReader.tableItemBytes(index)
|
|
||||||
|
|
||||||
override fun string(index: Int): ByteArray = stringReader.tableItemBytes(index)
|
|
||||||
|
|
||||||
override fun body(index: Int): ByteArray = bodyReader.tableItemBytes(index)
|
|
||||||
|
|
||||||
override fun debugInfo(index: Int): ByteArray? = null
|
|
||||||
}
|
|
||||||
-269
@@ -1,269 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.*
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsMapping
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
|
||||||
import org.jetbrains.kotlin.library.IrLibrary
|
|
||||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrLongArrayMemoryReader
|
|
||||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile
|
|
||||||
|
|
||||||
class IcModuleDeserializer(
|
|
||||||
val irFactory: PersistentIrFactory,
|
|
||||||
val mapping: JsMapping,
|
|
||||||
val linker: JsIrLinker,
|
|
||||||
val icData: SerializedIcData,
|
|
||||||
moduleDescriptor: ModuleDescriptor,
|
|
||||||
override val klib: IrLibrary,
|
|
||||||
override val strategyResolver: (String) -> DeserializationStrategy,
|
|
||||||
private val containsErrorCode: Boolean = false,
|
|
||||||
) : IrModuleDeserializer(moduleDescriptor, (klib as KotlinLibrary).versions.abiVersion ?: KotlinAbiVersion.CURRENT) {
|
|
||||||
|
|
||||||
private val fileToDeserializerMap = mutableMapOf<IrFile, IrFileDeserializer>()
|
|
||||||
|
|
||||||
internal val moduleReversedFileIndex = mutableMapOf<IdSignature, IcFileDeserializer>()
|
|
||||||
internal val icModuleReversedFileIndex = mutableMapOf<IdSignature, IcFileDeserializer>()
|
|
||||||
|
|
||||||
override val moduleDependencies by lazy {
|
|
||||||
moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { linker.resolveModuleDeserializer(it, null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fileDeserializers(): Collection<IrFileDeserializer> {
|
|
||||||
return fileToDeserializerMap.values
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun init(delegate: IrModuleDeserializer) {
|
|
||||||
val fileCount = klib.fileCount()
|
|
||||||
|
|
||||||
val files = ArrayList<IrFile>(fileCount)
|
|
||||||
|
|
||||||
for (i in 0 until fileCount) {
|
|
||||||
val fileStream = klib.file(i).codedInputStream
|
|
||||||
val fileProto = ProtoFile.parseFrom(fileStream, ExtensionRegistryLite.newInstance())
|
|
||||||
files.add(deserializeIrFile(fileProto, i, delegate, containsErrorCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleFragment.files.addAll(files)
|
|
||||||
|
|
||||||
fileToDeserializerMap.values.forEach { it.symbolDeserializer.deserializeExpectActualMapping() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrSymbolDeserializer.deserializeExpectActualMapping() {
|
|
||||||
actuals.forEach {
|
|
||||||
val expectSymbol = parseSymbolData(it.expectSymbol)
|
|
||||||
val actualSymbol = parseSymbolData(it.actualSymbol)
|
|
||||||
|
|
||||||
val expect = deserializeIdSignature(expectSymbol.signatureId)
|
|
||||||
val actual = deserializeIdSignature(actualSymbol.signatureId)
|
|
||||||
|
|
||||||
assert(linker.expectUniqIdToActualUniqId[expect] == null) {
|
|
||||||
"Expect signature $expect is already actualized by ${linker.expectUniqIdToActualUniqId[expect]}, while we try to record $actual"
|
|
||||||
}
|
|
||||||
linker.expectUniqIdToActualUniqId[expect] = actual
|
|
||||||
// Non-null only for topLevel declarations.
|
|
||||||
findModuleDeserializerForTopLevelId(actual)?.let { md -> linker.topLevelActualUniqItToDeserializer[actual] = md }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun referenceSimpleFunctionByLocalSignature(file: IrFile, idSignature: IdSignature): IrSimpleFunctionSymbol =
|
|
||||||
fileToDeserializerMap[file]?.symbolDeserializer?.referenceSimpleFunctionByLocalSignature(idSignature)
|
|
||||||
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
|
||||||
|
|
||||||
override fun referencePropertyByLocalSignature(file: IrFile, idSignature: IdSignature): IrPropertySymbol =
|
|
||||||
fileToDeserializerMap[file]?.symbolDeserializer?.referencePropertyByLocalSignature(idSignature)
|
|
||||||
?: error("No deserializer for file $file in module ${moduleDescriptor.name}")
|
|
||||||
|
|
||||||
// TODO: fix to topLevel checker
|
|
||||||
override fun contains(idSig: IdSignature): Boolean = idSig.topLevelSignature() in moduleReversedFileIndex || idSig in icModuleReversedFileIndex
|
|
||||||
|
|
||||||
override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol {
|
|
||||||
assert(idSig.isPubliclyVisible)
|
|
||||||
|
|
||||||
icModuleReversedFileIndex[idSig]?.let { icDeserializer ->
|
|
||||||
return icDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
|
||||||
}
|
|
||||||
|
|
||||||
val topLevelSignature = idSig.topLevelSignature()
|
|
||||||
val icDeserializer = moduleReversedFileIndex[topLevelSignature]
|
|
||||||
?: error("No file for $topLevelSignature (@ $idSig) in module $moduleDescriptor")
|
|
||||||
|
|
||||||
val symbol = icDeserializer.originalFileDeserializer.symbolDeserializer.deserializeIrSymbol(idSig, symbolKind)
|
|
||||||
|
|
||||||
if (!symbol.isBound) {
|
|
||||||
topLevelSignature.originalEnqueue(icDeserializer)
|
|
||||||
idSig.enqueue(icDeserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, linker.builtIns, emptyList())
|
|
||||||
|
|
||||||
private val pathToIcFileData = icData.files.associateBy {
|
|
||||||
it.file.path
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deserializeIrFile(
|
|
||||||
fileProto: ProtoFile,
|
|
||||||
fileIndex: Int,
|
|
||||||
moduleDeserializer: IrModuleDeserializer,
|
|
||||||
allowErrorNodes: Boolean
|
|
||||||
): IrFile {
|
|
||||||
|
|
||||||
val fileReader = IrLibraryFileFromBytes(IrKlibBytesSource(moduleDeserializer.klib, fileIndex))
|
|
||||||
val file = fileReader.createFile(moduleFragment, fileProto)
|
|
||||||
val fileStrategy = strategyResolver(file.fileEntry.name)
|
|
||||||
|
|
||||||
val icFileData = pathToIcFileData[file.path] ?: error("No IC cache found for file ${file.path}")
|
|
||||||
|
|
||||||
val icDeserializer = IcFileDeserializer(
|
|
||||||
linker,
|
|
||||||
file,
|
|
||||||
fileReader,
|
|
||||||
fileProto,
|
|
||||||
fileStrategy.needBodies,
|
|
||||||
allowErrorNodes,
|
|
||||||
fileStrategy.inlineBodies,
|
|
||||||
moduleDeserializer,
|
|
||||||
{ fileDeserializer -> originalEnqueue(fileDeserializer) },
|
|
||||||
icFileData,
|
|
||||||
mapping.state,
|
|
||||||
{ fileDeserializer -> enqueue(fileDeserializer) },
|
|
||||||
)
|
|
||||||
|
|
||||||
icDeserializers += icDeserializer
|
|
||||||
|
|
||||||
icDeserializer.explicitlyExportedToCompiler.forEach { it.topLevelSignature().originalEnqueue(icDeserializer) }
|
|
||||||
|
|
||||||
fileToDeserializerMap[file] = icDeserializer.originalFileDeserializer
|
|
||||||
|
|
||||||
val topLevelDeclarations = icDeserializer.originalFileDeserializer.reversedSignatureIndex.keys
|
|
||||||
topLevelDeclarations.forEach {
|
|
||||||
moduleReversedFileIndex.putIfAbsent(it, icDeserializer) // TODO Why not simple put?
|
|
||||||
}
|
|
||||||
|
|
||||||
icDeserializer.reversedSignatureIndex.keys.forEach {
|
|
||||||
if (it.isPubliclyVisible) {
|
|
||||||
if (it in icModuleReversedFileIndex) {
|
|
||||||
val existed = icModuleReversedFileIndex[it]!!
|
|
||||||
error("Duplicate signature $it in both ${existed.originalFileDeserializer.file.path} and in ${file.path}")
|
|
||||||
}
|
|
||||||
|
|
||||||
icModuleReversedFileIndex[it] = icDeserializer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileStrategy.theWholeWorld) {
|
|
||||||
icDeserializer.allOriginalDeclarationSignatures().forEach { it.originalEnqueue(icDeserializer) }
|
|
||||||
}
|
|
||||||
if (fileStrategy.theWholeWorld || fileStrategy.explicitlyExported) {
|
|
||||||
linker.modulesWithReachableTopLevels.add(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addModuleReachableTopLevel(idSig: IdSignature) {
|
|
||||||
val fileLocalDeserializationState = moduleReversedFileIndex[idSig] ?: error("No file found for key $idSig")
|
|
||||||
idSig.originalEnqueue(fileLocalDeserializationState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserializeReachableDeclarations() {
|
|
||||||
while (!originalFileQueue.isEmpty()) {
|
|
||||||
originalFileQueue.removeFirst().deserializePendingSignatures()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalFileQueue = ArrayDeque<IcFileDeserializer>()
|
|
||||||
|
|
||||||
fun IdSignature.originalEnqueue(fileDeserializer: IcFileDeserializer) {
|
|
||||||
if (fileDeserializer.enqueueForDeserialization(this)) {
|
|
||||||
linker.modulesWithReachableTopLevels.add(this@IcModuleDeserializer)
|
|
||||||
originalFileQueue.addLast(fileDeserializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val fileQueue = ArrayDeque<IcFileDeserializer>()
|
|
||||||
val signatureQueue = ArrayDeque<IdSignature>()
|
|
||||||
|
|
||||||
val icDeserializers = mutableListOf<IcFileDeserializer>()
|
|
||||||
val classToDeclarationSymbols = mutableMapOf<IrClass, List<IrSymbol>>()
|
|
||||||
|
|
||||||
fun IdSignature.enqueue(icDeserializer: IcFileDeserializer) {
|
|
||||||
if (this !in icDeserializer.visited) {
|
|
||||||
fileQueue.addLast(icDeserializer)
|
|
||||||
signatureQueue.addLast(this)
|
|
||||||
icDeserializer.visited += this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun postProcess() {
|
|
||||||
while (signatureQueue.isNotEmpty()) {
|
|
||||||
val icFileDeserializer = fileQueue.removeFirst()
|
|
||||||
val signature = signatureQueue.removeFirst()
|
|
||||||
|
|
||||||
val declaration =
|
|
||||||
icFileDeserializer.deserializeDeclaration(signature) ?: icFileDeserializer.deserializeAnyDeclaration(signature)
|
|
||||||
|
|
||||||
if (declaration != null) {
|
|
||||||
icFileDeserializer.injectCarriers(declaration, signature)
|
|
||||||
|
|
||||||
icFileDeserializer.mappingsDeserializer(signature, declaration)
|
|
||||||
|
|
||||||
// Make sure all members are loaded
|
|
||||||
if (declaration is IrClass) {
|
|
||||||
icFileDeserializer.loadClassOrder(signature)?.let {
|
|
||||||
classToDeclarationSymbols[declaration] = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
irFactory.stageController.withStage(1000) {
|
|
||||||
|
|
||||||
for (icDeserializer in icDeserializers) {
|
|
||||||
val fd = icDeserializer.originalFileDeserializer
|
|
||||||
val order = icDeserializer.icFileData.order
|
|
||||||
|
|
||||||
fd.file.declarations.retainAll { it.isEffectivelyExternal() }
|
|
||||||
|
|
||||||
IrLongArrayMemoryReader(order.topLevelSignatures).array.forEach {
|
|
||||||
val symbolData = icDeserializer.symbolDeserializer.parseSymbolData(it)
|
|
||||||
val idSig = icDeserializer.symbolDeserializer.deserializeIdSignature(symbolData.signatureId)
|
|
||||||
|
|
||||||
// Don't create unbound symbols for top-level declarations we don't need.
|
|
||||||
if (idSig in icDeserializer.visited) {
|
|
||||||
val declaration = icDeserializer.deserializeIrSymbol(idSig, symbolData.kind).owner as IrDeclaration
|
|
||||||
fd.file.declarations += declaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((klass, declarations) in classToDeclarationSymbols.entries) {
|
|
||||||
irFactory.stageController.unrestrictDeclarationListsAccess {
|
|
||||||
klass.declarations.clear()
|
|
||||||
for (ds in declarations) {
|
|
||||||
klass.declarations += ds.owner as IrDeclaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-179
@@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
|
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsMapping
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsGlobalDeclarationTable
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrFileSerializer
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrBodyBase
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrDeclarationBase
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
|
||||||
import org.jetbrains.kotlin.ir.serialization.serializeCarriers
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
|
||||||
import org.jetbrains.kotlin.ir.util.fileOrNull
|
|
||||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrMemoryArrayWriter
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrMemoryLongArrayWriter
|
|
||||||
|
|
||||||
class IcSerializer(
|
|
||||||
irBuiltIns: IrBuiltIns,
|
|
||||||
val mappings: JsMapping,
|
|
||||||
val irFactory: PersistentIrFactory,
|
|
||||||
val linker: JsIrLinker,
|
|
||||||
val module: IrModuleFragment
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val globalDeclarationTable = JsGlobalDeclarationTable(irBuiltIns)
|
|
||||||
|
|
||||||
fun serializeDeclarations(moduleDeclarations: Iterable<IrDeclaration>): SerializedIcData {
|
|
||||||
|
|
||||||
// TODO serialize body carriers and new bodies as well
|
|
||||||
val moduleDeserializer = linker.moduleDeserializer(module.descriptor)
|
|
||||||
|
|
||||||
val fileToDeserializer = moduleDeserializer.fileDeserializers().associateBy { it.file }
|
|
||||||
|
|
||||||
val filteredDeclarations = moduleDeclarations.filter {
|
|
||||||
when {
|
|
||||||
it.fileOrNull.let { it == null || fileToDeserializer[it] == null } -> false
|
|
||||||
it is IrFakeOverrideFunction -> it.isBound
|
|
||||||
it is IrFakeOverrideProperty -> it.isBound
|
|
||||||
else -> (it.parent as? IrFakeOverrideFunction)?.isBound ?: (it.parent as? IrFakeOverrideProperty)?.isBound ?: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val filteredBodies = irFactory.allBodies.groupBy {
|
|
||||||
(it as? PersistentIrBodyBase<*>)?.let {
|
|
||||||
if (it.hasContainer) {
|
|
||||||
it.container.fileOrNull
|
|
||||||
} else null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val dataToSerialize = filteredDeclarations.groupBy {
|
|
||||||
// TODO don't move declarations or effects outside the original file
|
|
||||||
// TODO Or invent a different mechanism for that
|
|
||||||
|
|
||||||
it.file
|
|
||||||
}
|
|
||||||
|
|
||||||
val icData = mutableListOf<SerializedIcDataForFile>()
|
|
||||||
|
|
||||||
for (file in fileToDeserializer.keys) {
|
|
||||||
val fileDeclarations = dataToSerialize[file] ?: emptyList()
|
|
||||||
val bodies = filteredBodies[file] ?: emptyList()
|
|
||||||
|
|
||||||
val fileDeserializer = fileToDeserializer[file]!!
|
|
||||||
|
|
||||||
val symbolToSignature = fileDeserializer.symbolDeserializer.deserializedSymbols.entries.associate { (idSig, symbol) -> symbol to idSig }.toMutableMap()
|
|
||||||
|
|
||||||
val icDeclarationTable = IcDeclarationTable(globalDeclarationTable, irFactory, 1000000, symbolToSignature)
|
|
||||||
val fileSerializer = JsIrFileSerializer(
|
|
||||||
linker.messageLogger,
|
|
||||||
icDeclarationTable,
|
|
||||||
mutableMapOf(),
|
|
||||||
skipExpects = true,
|
|
||||||
icMode = true,
|
|
||||||
allowErrorStatementOrigins = true,
|
|
||||||
compatibilityMode = CompatibilityMode.CURRENT,
|
|
||||||
normalizeAbsolutePaths = false,
|
|
||||||
sourceBaseDirs = emptyList()
|
|
||||||
)
|
|
||||||
|
|
||||||
icDeclarationTable.inFile(file) {
|
|
||||||
bodies.forEach { body ->
|
|
||||||
if (body is IrExpressionBody) {
|
|
||||||
fileSerializer.serializeIrExpressionBody(body.expression)
|
|
||||||
} else {
|
|
||||||
fileSerializer.serializeIrStatementBody(body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only save newly created declarations
|
|
||||||
val newDeclarations = fileDeclarations.filter { d ->
|
|
||||||
d is PersistentIrDeclarationBase<*> && (d.createdOn > 0 || /*d.isFakeOverride ||*/ (d is IrValueParameter || d is IrTypeParameter) && (d.parent as IrDeclaration).isFakeOverride)
|
|
||||||
}
|
|
||||||
|
|
||||||
val serializedCarriers = fileSerializer.serializeCarriers(fileDeclarations, bodies) { declaration ->
|
|
||||||
icDeclarationTable.signatureByDeclaration(declaration, compatibleMode = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
val serializedMappings = mappings.state.serializeMappings(fileDeclarations) { symbol ->
|
|
||||||
fileSerializer.serializeIrSymbol(symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
val order = storeOrder(file, fileDeclarations) { symbol ->
|
|
||||||
fileSerializer.serializeIrSymbol(symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
val serializedIrFile = fileSerializer.serializeDeclarationsForIC(file, newDeclarations)
|
|
||||||
|
|
||||||
icData += SerializedIcDataForFile(
|
|
||||||
serializedIrFile,
|
|
||||||
serializedCarriers,
|
|
||||||
serializedMappings,
|
|
||||||
order,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SerializedIcData(icData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns precomputed signatures for the newly created declarations. Delegates to the default table otherwise.
|
|
||||||
class IcDeclarationTable(
|
|
||||||
globalDeclarationTable: JsGlobalDeclarationTable,
|
|
||||||
val irFactory: PersistentIrFactory,
|
|
||||||
startIndex: Int,
|
|
||||||
val existingMappings: MutableMap<IrSymbol, IdSignature>
|
|
||||||
) : DeclarationTable(globalDeclarationTable) {
|
|
||||||
|
|
||||||
override val signaturer: IdSignatureSerializer =
|
|
||||||
IdSignatureSerializer(globalDeclarationTable.publicIdSignatureComputer, this, startIndex)
|
|
||||||
|
|
||||||
override fun signatureByDeclaration(declaration: IrDeclaration, compatibleMode: Boolean): IdSignature {
|
|
||||||
return existingMappings.getOrPut(declaration.symbol) {
|
|
||||||
irFactory.declarationSignature(declaration) ?: super.signatureByDeclaration(declaration, compatibleMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun storeOrder(file: IrFile, fileDeclarations: Iterable<IrDeclaration>, idSigToLong: (IrSymbol) -> Long): SerializedOrder {
|
|
||||||
val topLevelSignatures = mutableListOf<Long>()
|
|
||||||
val containerSignatures = mutableListOf<Long>()
|
|
||||||
val declarationSignatures = mutableListOf<ByteArray>()
|
|
||||||
|
|
||||||
fun IrDeclaration.idSigIndex(): Long = idSigToLong(symbol)
|
|
||||||
|
|
||||||
file.declarations.forEach { d ->
|
|
||||||
topLevelSignatures += d.idSigIndex()
|
|
||||||
}
|
|
||||||
|
|
||||||
fileDeclarations.forEach { declaration ->
|
|
||||||
if (declaration is IrClass) {
|
|
||||||
// First element is the container signature
|
|
||||||
containerSignatures += declaration.idSigIndex()
|
|
||||||
val declarationIds = declaration.declarations.map { it.idSigIndex() }
|
|
||||||
|
|
||||||
declarationSignatures += IrMemoryLongArrayWriter(declarationIds).writeIntoMemory()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SerializedOrder(
|
|
||||||
IrMemoryLongArrayWriter(topLevelSignatures).writeIntoMemory(),
|
|
||||||
IrMemoryLongArrayWriter(containerSignatures).writeIntoMemory(),
|
|
||||||
IrMemoryArrayWriter(declarationSignatures).writeIntoMemory(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.ic
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.SerializedMapping
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.SerializedMappings
|
|
||||||
import org.jetbrains.kotlin.ir.serialization.SerializedCarriers
|
|
||||||
import org.jetbrains.kotlin.library.SerializedIrFile
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrArrayMemoryReader
|
|
||||||
import org.jetbrains.kotlin.library.impl.IrMemoryArrayWriter
|
|
||||||
import org.jetbrains.kotlin.library.impl.toArray
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class SerializedIcData(
|
|
||||||
val files: Collection<SerializedIcDataForFile>,
|
|
||||||
)
|
|
||||||
|
|
||||||
class SerializedIcDataForFile(
|
|
||||||
val file: SerializedIrFile,
|
|
||||||
val carriers: SerializedCarriers,
|
|
||||||
val mappings: SerializedMappings,
|
|
||||||
val order: SerializedOrder,
|
|
||||||
)
|
|
||||||
|
|
||||||
class SerializedOrder(
|
|
||||||
val topLevelSignatures: ByteArray,
|
|
||||||
val containerSignatures: ByteArray,
|
|
||||||
val declarationSignatures: ByteArray,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun newFile(fileDir: File, name: String): File {
|
|
||||||
val f = File(fileDir, name)
|
|
||||||
if (f.exists()) f.delete()
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SerializedIcDataForFile.writeData(fileDir: File) {
|
|
||||||
// .file
|
|
||||||
newFile(fileDir, "file.fileData").writeBytes(file.fileData)
|
|
||||||
newFile(fileDir, "file.path").writeBytes(file.path.toByteArray(Charsets.UTF_8))
|
|
||||||
newFile(fileDir, "file.declarations").writeBytes(file.declarations)
|
|
||||||
newFile(fileDir, "file.types").writeBytes(file.types)
|
|
||||||
newFile(fileDir, "file.signatures").writeBytes(file.signatures)
|
|
||||||
newFile(fileDir, "file.strings").writeBytes(file.strings)
|
|
||||||
newFile(fileDir, "file.bodies").writeBytes(file.bodies)
|
|
||||||
// .carriers
|
|
||||||
newFile(fileDir, "carriers.signatures").writeBytes(carriers.signatures)
|
|
||||||
newFile(fileDir, "carriers.declarationCarriers").writeBytes(carriers.declarationCarriers)
|
|
||||||
newFile(fileDir, "carriers.bodyCarriers").writeBytes(carriers.bodyCarriers)
|
|
||||||
newFile(fileDir, "carriers.removedOn").writeBytes(carriers.removedOn)
|
|
||||||
// .mappings
|
|
||||||
newFile(fileDir, "mappings.keys").writeBytes(mappings.keyBytes())
|
|
||||||
newFile(fileDir, "mappings.values").writeBytes(mappings.valueBytes())
|
|
||||||
// .order
|
|
||||||
newFile(fileDir, "order.topLevelSignatures").writeBytes(order.topLevelSignatures)
|
|
||||||
newFile(fileDir, "order.containerSignatures").writeBytes(order.containerSignatures)
|
|
||||||
newFile(fileDir, "order.declarationSignatures").writeBytes(order.declarationSignatures)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SerializedIcData.writeTo(dir: File) {
|
|
||||||
if (!dir.exists()) error("Directory doesn't exist: ${dir.absolutePath}")
|
|
||||||
if (!dir.isDirectory) error("Not a directory: ${dir.absolutePath}")
|
|
||||||
|
|
||||||
files.forEach {
|
|
||||||
val fqnPath = it.file.fqName
|
|
||||||
val fileId = it.file.path.hashCode().toString(Character.MAX_RADIX)
|
|
||||||
val irFileDirectory = "ic-$fqnPath.$fileId.file"
|
|
||||||
val fileDir = File(dir, irFileDirectory)
|
|
||||||
|
|
||||||
// TODO: just rewrite?
|
|
||||||
if (!fileDir.exists()) {
|
|
||||||
if (!fileDir.mkdirs()) error("Failed to create output dir for file ${fileDir.absolutePath}")
|
|
||||||
}
|
|
||||||
|
|
||||||
it.writeData(fileDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun SerializedMappings.keyBytes() = IrMemoryArrayWriter(mappings.map { it.keys }).writeIntoMemory()
|
|
||||||
private fun SerializedMappings.valueBytes() = IrMemoryArrayWriter(mappings.map { it.values }).writeIntoMemory()
|
|
||||||
|
|
||||||
fun File.readIcDataBinary(): SerializedIcDataForFile {
|
|
||||||
val file = SerializedIrFile(
|
|
||||||
fileData = File(this, "file.fileData").readBytes(),
|
|
||||||
fqName = name.split('.').dropLast(2).joinToString(separator = "."),
|
|
||||||
path = File(this, "file.path").readBytes().toString(Charsets.UTF_8),
|
|
||||||
types = File(this, "file.types").readBytes(),
|
|
||||||
signatures = File(this, "file.signatures").readBytes(),
|
|
||||||
strings = File(this, "file.strings").readBytes(),
|
|
||||||
bodies = File(this, "file.bodies").readBytes(),
|
|
||||||
declarations = File(this, "file.declarations").readBytes(),
|
|
||||||
debugInfo = null
|
|
||||||
)
|
|
||||||
|
|
||||||
val carriers = SerializedCarriers(
|
|
||||||
signatures = File(this, "carriers.signatures").readBytes(),
|
|
||||||
declarationCarriers = File(this, "carriers.declarationCarriers").readBytes(),
|
|
||||||
bodyCarriers = File(this, "carriers.bodyCarriers").readBytes(),
|
|
||||||
removedOn = File(this, "carriers.removedOn").readBytes(),
|
|
||||||
)
|
|
||||||
|
|
||||||
val mappingKeys = IrArrayMemoryReader(File(this, "mappings.keys").readBytes()).toArray()
|
|
||||||
val mappingValues = IrArrayMemoryReader(File(this, "mappings.values").readBytes()).toArray()
|
|
||||||
assert(mappingKeys.size == mappingValues.size)
|
|
||||||
val mappings = SerializedMappings(mappingKeys.zip(mappingValues).map { (k, v) -> SerializedMapping(k, v) })
|
|
||||||
|
|
||||||
val order = SerializedOrder(
|
|
||||||
topLevelSignatures = File(this, "order.topLevelSignatures").readBytes(),
|
|
||||||
containerSignatures = File(this, "order.containerSignatures").readBytes(),
|
|
||||||
declarationSignatures = File(this, "order.declarationSignatures").readBytes(),
|
|
||||||
)
|
|
||||||
|
|
||||||
return SerializedIcDataForFile(file, carriers, mappings, order)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun File.readIcData(): SerializedIcData {
|
|
||||||
if (!this.isDirectory) error("Directory doesn't exist: ${this.absolutePath}")
|
|
||||||
|
|
||||||
return SerializedIcData(this.listFiles()!!.filter { it.isDirectory && it.name.startsWith("ic-") }.map { fileDir ->
|
|
||||||
fileDir.readIcDataBinary()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -31,8 +31,6 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.ICCache
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.SerializedIcData
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
|
||||||
@@ -71,7 +69,6 @@ import org.jetbrains.kotlin.util.DummyLogger
|
|||||||
import org.jetbrains.kotlin.util.Logger
|
import org.jetbrains.kotlin.util.Logger
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
|
||||||
|
|
||||||
val KotlinLibrary.moduleName: String
|
val KotlinLibrary.moduleName: String
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)
|
||||||
@@ -83,11 +80,6 @@ val KotlinLibrary.isBuiltIns: Boolean
|
|||||||
.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
|
|
||||||
// TODO: The only place loadKlib() is used now is Wasm backend.
|
|
||||||
// Need to move it to SearchPathResolver too.
|
|
||||||
fun loadKlib(klibPath: String) =
|
|
||||||
resolveSingleFileKlib(KFile(KFile(klibPath).absolutePath))
|
|
||||||
|
|
||||||
private val CompilerConfiguration.metadataVersion
|
private val CompilerConfiguration.metadataVersion
|
||||||
get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE
|
get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE
|
||||||
|
|
||||||
@@ -255,9 +247,7 @@ data class IrModuleInfo(
|
|||||||
val allDependencies: List<IrModuleFragment>,
|
val allDependencies: List<IrModuleFragment>,
|
||||||
val bultins: IrBuiltIns,
|
val bultins: IrBuiltIns,
|
||||||
val symbolTable: SymbolTable,
|
val symbolTable: SymbolTable,
|
||||||
val deserializer: JsIrLinker,
|
val deserializer: JsIrLinker
|
||||||
val moduleFragmentToUniqueName: Map<IrModuleFragment, String>,
|
|
||||||
val loweredIrLoaded: Set<IrModuleFragment> = emptySet(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<KotlinLibrary> {
|
fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<KotlinLibrary> {
|
||||||
@@ -269,14 +259,6 @@ fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<
|
|||||||
}.reversed()
|
}.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoweringsCacheProvider {
|
|
||||||
fun cacheByPath(path: String): SerializedIcData?
|
|
||||||
}
|
|
||||||
|
|
||||||
object EmptyLoweringsCacheProvider : LoweringsCacheProvider {
|
|
||||||
override fun cacheByPath(path: String): SerializedIcData? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deserializeDependencies(
|
fun deserializeDependencies(
|
||||||
sortedDependencies: Collection<KotlinLibrary>,
|
sortedDependencies: Collection<KotlinLibrary>,
|
||||||
irLinker: JsIrLinker,
|
irLinker: JsIrLinker,
|
||||||
@@ -296,14 +278,6 @@ fun deserializeDependencies(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Map<IrModuleFragment, KotlinLibrary>.getUniqueNameForEachFragment(): Map<IrModuleFragment, String> {
|
|
||||||
return this.entries.mapNotNull { (moduleFragment, klib) ->
|
|
||||||
klib.manifestProperties.getProperty(KLIB_PROPERTY_JS_OUTPUT_NAME)?.let {
|
|
||||||
moduleFragment to it
|
|
||||||
}
|
|
||||||
}.toMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFunctionFactoryCallback(stdlibModule: IrModuleFragment) = { packageFragmentDescriptor: PackageFragmentDescriptor ->
|
fun getFunctionFactoryCallback(stdlibModule: IrModuleFragment) = { packageFragmentDescriptor: PackageFragmentDescriptor ->
|
||||||
IrFileImpl(
|
IrFileImpl(
|
||||||
NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"),
|
NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"),
|
||||||
@@ -345,31 +319,13 @@ fun loadIr(
|
|||||||
mainModule.files,
|
mainModule.files,
|
||||||
sortDependencies(depsDescriptors.descriptors),
|
sortDependencies(depsDescriptors.descriptors),
|
||||||
friendModules,
|
friendModules,
|
||||||
depsDescriptors.loweredIcData,
|
|
||||||
symbolTable,
|
symbolTable,
|
||||||
messageLogger,
|
messageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib,
|
loadFunctionInterfacesIntoStdlib,
|
||||||
verifySignatures,
|
verifySignatures,
|
||||||
{ depsDescriptors.modulesWithCaches(it) },
|
) { depsDescriptors.getModuleDescriptor(it) }
|
||||||
{ depsDescriptors.getModuleDescriptor(it) },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
is MainModule.Klib -> {
|
is MainModule.Klib -> {
|
||||||
val loweredIcData = if (!depsDescriptors.icUseGlobalSignatures && !depsDescriptors.icUseStdlibCache) emptyMap() else {
|
|
||||||
val result = mutableMapOf<ModuleDescriptor, SerializedIcData>()
|
|
||||||
|
|
||||||
for (lib in depsDescriptors.moduleDependencies.keys) {
|
|
||||||
val path = lib.libraryFile.absolutePath
|
|
||||||
val icData = depsDescriptors.loweringsCacheProvider.cacheByPath(path)
|
|
||||||
if (icData != null) {
|
|
||||||
val desc = depsDescriptors.getModuleDescriptor(lib)
|
|
||||||
result[desc] = icData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
val mainPath = File(mainModule.libPath).canonicalPath
|
val mainPath = File(mainModule.libPath).canonicalPath
|
||||||
val mainModuleLib = allDependencies.find { it.libraryFile.canonicalPath == mainPath }
|
val mainModuleLib = allDependencies.find { it.libraryFile.canonicalPath == mainPath }
|
||||||
?: error("No module with ${mainModule.libPath} found")
|
?: error("No module with ${mainModule.libPath} found")
|
||||||
@@ -386,10 +342,7 @@ fun loadIr(
|
|||||||
symbolTable,
|
symbolTable,
|
||||||
messageLogger,
|
messageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib,
|
loadFunctionInterfacesIntoStdlib,
|
||||||
loweredIcData,
|
) { depsDescriptors.getModuleDescriptor(it) }
|
||||||
{ depsDescriptors.modulesWithCaches(it) },
|
|
||||||
{ depsDescriptors.getModuleDescriptor(it) },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,8 +357,6 @@ fun getIrModuleInfoForKlib(
|
|||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
messageLogger: IrMessageLogger,
|
messageLogger: IrMessageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib: Boolean,
|
loadFunctionInterfacesIntoStdlib: Boolean,
|
||||||
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
|
|
||||||
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
|
|
||||||
mapping: (KotlinLibrary) -> ModuleDescriptor,
|
mapping: (KotlinLibrary) -> ModuleDescriptor,
|
||||||
): IrModuleInfo {
|
): IrModuleInfo {
|
||||||
val mainModuleLib = sortedDependencies.last()
|
val mainModuleLib = sortedDependencies.last()
|
||||||
@@ -422,7 +373,6 @@ fun getIrModuleInfoForKlib(
|
|||||||
symbolTable,
|
symbolTable,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
loweredIcData,
|
|
||||||
friendModules,
|
friendModules,
|
||||||
allowUnboundSymbols
|
allowUnboundSymbols
|
||||||
)
|
)
|
||||||
@@ -443,11 +393,7 @@ fun getIrModuleInfoForKlib(
|
|||||||
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
|
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
|
||||||
irLinker.postProcess()
|
irLinker.postProcess()
|
||||||
|
|
||||||
return IrModuleInfo(
|
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
|
||||||
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
|
|
||||||
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
|
|
||||||
filterModulesWithCache(deserializedModuleFragments)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
@@ -458,12 +404,10 @@ fun getIrModuleInfoForSourceFiles(
|
|||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
allSortedDependencies: Collection<KotlinLibrary>,
|
allSortedDependencies: Collection<KotlinLibrary>,
|
||||||
friendModules: Map<String, List<String>>,
|
friendModules: Map<String, List<String>>,
|
||||||
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
|
|
||||||
symbolTable: SymbolTable,
|
symbolTable: SymbolTable,
|
||||||
messageLogger: IrMessageLogger,
|
messageLogger: IrMessageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib: Boolean,
|
loadFunctionInterfacesIntoStdlib: Boolean,
|
||||||
verifySignatures: Boolean,
|
verifySignatures: Boolean,
|
||||||
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
|
|
||||||
mapping: (KotlinLibrary) -> ModuleDescriptor
|
mapping: (KotlinLibrary) -> ModuleDescriptor
|
||||||
): IrModuleInfo {
|
): IrModuleInfo {
|
||||||
val irBuiltIns = psi2IrContext.irBuiltIns
|
val irBuiltIns = psi2IrContext.irBuiltIns
|
||||||
@@ -481,7 +425,6 @@ fun getIrModuleInfoForSourceFiles(
|
|||||||
symbolTable,
|
symbolTable,
|
||||||
feContext,
|
feContext,
|
||||||
null,
|
null,
|
||||||
loweredIcData,
|
|
||||||
friendModules,
|
friendModules,
|
||||||
allowUnboundSymbols
|
allowUnboundSymbols
|
||||||
)
|
)
|
||||||
@@ -517,11 +460,7 @@ fun getIrModuleInfoForSourceFiles(
|
|||||||
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
|
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return IrModuleInfo(
|
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
|
||||||
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
|
|
||||||
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
|
|
||||||
filterModulesWithCache(deserializedModuleFragments)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun prepareAnalyzedSourceModule(
|
fun prepareAnalyzedSourceModule(
|
||||||
@@ -531,13 +470,10 @@ fun prepareAnalyzedSourceModule(
|
|||||||
dependencies: List<String>,
|
dependencies: List<String>,
|
||||||
friendDependencies: List<String>,
|
friendDependencies: List<String>,
|
||||||
analyzer: AbstractAnalyzerWithCompilerReport,
|
analyzer: AbstractAnalyzerWithCompilerReport,
|
||||||
icUseGlobalSignatures: Boolean = false,
|
|
||||||
icUseStdlibCache: Boolean = false,
|
|
||||||
icCache: Map<String, ICCache> = emptyMap(),
|
|
||||||
errorPolicy: ErrorTolerancePolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT,
|
errorPolicy: ErrorTolerancePolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT,
|
||||||
): ModulesStructure {
|
): ModulesStructure {
|
||||||
val mainModule = MainModule.SourceFiles(files)
|
val mainModule = MainModule.SourceFiles(files)
|
||||||
val sourceModule = ModulesStructure(project, mainModule, configuration, dependencies, friendDependencies, icUseGlobalSignatures, icUseStdlibCache, icCache)
|
val sourceModule = ModulesStructure(project, mainModule, configuration, dependencies, friendDependencies)
|
||||||
return sourceModule.apply {
|
return sourceModule.apply {
|
||||||
runAnalysis(errorPolicy, analyzer)
|
runAnalysis(errorPolicy, analyzer)
|
||||||
}
|
}
|
||||||
@@ -626,19 +562,7 @@ class ModulesStructure(
|
|||||||
val compilerConfiguration: CompilerConfiguration,
|
val compilerConfiguration: CompilerConfiguration,
|
||||||
val dependencies: Collection<String>,
|
val dependencies: Collection<String>,
|
||||||
friendDependenciesPaths: Collection<String>,
|
friendDependenciesPaths: Collection<String>,
|
||||||
val icUseGlobalSignatures: Boolean,
|
|
||||||
val icUseStdlibCache: Boolean,
|
|
||||||
val icCache: Map<String, ICCache>,
|
|
||||||
) {
|
) {
|
||||||
val loweringsCacheProvider: LoweringsCacheProvider = when {
|
|
||||||
icUseStdlibCache -> object : LoweringsCacheProvider {
|
|
||||||
override fun cacheByPath(path: String): SerializedIcData? {
|
|
||||||
return icCache[path]?.serializedIcData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
icUseGlobalSignatures -> EmptyLoweringsCacheProvider
|
|
||||||
else -> EmptyLoweringsCacheProvider
|
|
||||||
}
|
|
||||||
|
|
||||||
val allResolvedDependencies = jsResolveLibraries(
|
val allResolvedDependencies = jsResolveLibraries(
|
||||||
dependencies,
|
dependencies,
|
||||||
@@ -662,7 +586,7 @@ class ModulesStructure(
|
|||||||
}.toMap()
|
}.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
val builtInsDep = allDependencies.find { it.library.isBuiltIns }
|
private val builtInsDep = allDependencies.find { it.library.isBuiltIns }
|
||||||
|
|
||||||
class JsFrontEndResult(val jsAnalysisResult: AnalysisResult, val hasErrors: Boolean) {
|
class JsFrontEndResult(val jsAnalysisResult: AnalysisResult, val hasErrors: Boolean) {
|
||||||
val moduleDescriptor: ModuleDescriptor
|
val moduleDescriptor: ModuleDescriptor
|
||||||
@@ -719,8 +643,6 @@ class ModulesStructure(
|
|||||||
// TODO: these are roughly equivalent to KlibResolvedModuleDescriptorsFactoryImpl. Refactor me.
|
// TODO: these are roughly equivalent to KlibResolvedModuleDescriptorsFactoryImpl. Refactor me.
|
||||||
val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>()
|
val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>()
|
||||||
|
|
||||||
val loweredIcData = mutableMapOf<ModuleDescriptor, SerializedIcData>()
|
|
||||||
|
|
||||||
fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) {
|
fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) {
|
||||||
val isBuiltIns = current.unresolvedDependencies.isEmpty()
|
val isBuiltIns = current.unresolvedDependencies.isEmpty()
|
||||||
|
|
||||||
@@ -738,17 +660,9 @@ class ModulesStructure(
|
|||||||
val dependencies = moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
|
val dependencies = moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
|
||||||
md.setDependencies(listOf(md) + dependencies)
|
md.setDependencies(listOf(md) + dependencies)
|
||||||
|
|
||||||
loweringsCacheProvider.cacheByPath(current.libraryFile.absolutePath)?.let { icData ->
|
|
||||||
loweredIcData[md] = icData
|
|
||||||
}
|
|
||||||
|
|
||||||
md
|
md
|
||||||
}
|
}
|
||||||
|
|
||||||
fun modulesWithCaches(allModules: Iterable<IrModuleFragment>): Set<IrModuleFragment> {
|
|
||||||
return allModules.filter { it.descriptor in loweredIcData }.toSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
val builtInModuleDescriptor =
|
val builtInModuleDescriptor =
|
||||||
if (builtInsDep != null)
|
if (builtInsDep != null)
|
||||||
getModuleDescriptor(builtInsDep.library)
|
getModuleDescriptor(builtInsDep.library)
|
||||||
|
|||||||
-28
@@ -9,12 +9,8 @@ import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
|
|||||||
import org.jetbrains.kotlin.backend.common.serialization.*
|
import org.jetbrains.kotlin.backend.common.serialization.*
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsMapping
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.IcModuleDeserializer
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ic.SerializedIcData
|
|
||||||
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.library.IrLibrary
|
import org.jetbrains.kotlin.library.IrLibrary
|
||||||
@@ -26,7 +22,6 @@ class JsIrLinker(
|
|||||||
private val currentModule: ModuleDescriptor?, messageLogger: IrMessageLogger, builtIns: IrBuiltIns, symbolTable: SymbolTable,
|
private val currentModule: ModuleDescriptor?, messageLogger: IrMessageLogger, builtIns: IrBuiltIns, symbolTable: SymbolTable,
|
||||||
override val translationPluginContext: TranslationPluginContext?,
|
override val translationPluginContext: TranslationPluginContext?,
|
||||||
private val icData: ICData? = null,
|
private val icData: ICData? = null,
|
||||||
private val loweredIcData: Map<ModuleDescriptor, SerializedIcData> = emptyMap(),
|
|
||||||
friendModules: Map<String, Collection<String>> = emptyMap(),
|
friendModules: Map<String, Collection<String>> = emptyMap(),
|
||||||
allowUnboundSymbols: Boolean = false
|
allowUnboundSymbols: Boolean = false
|
||||||
) : KotlinIrLinker(
|
) : KotlinIrLinker(
|
||||||
@@ -53,23 +48,9 @@ class JsIrLinker(
|
|||||||
|
|
||||||
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategyResolver: (String) -> DeserializationStrategy): IrModuleDeserializer {
|
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategyResolver: (String) -> DeserializationStrategy): IrModuleDeserializer {
|
||||||
require(klib != null) { "Expecting kotlin library" }
|
require(klib != null) { "Expecting kotlin library" }
|
||||||
loweredIcData[moduleDescriptor]?.let { loweredIcData ->
|
|
||||||
return IcModuleDeserializer(
|
|
||||||
symbolTable.irFactory as PersistentIrFactory,
|
|
||||||
mapping,
|
|
||||||
this,
|
|
||||||
loweredIcData,
|
|
||||||
moduleDescriptor,
|
|
||||||
klib,
|
|
||||||
strategyResolver,
|
|
||||||
containsErrorCode = klib.libContainsErrorCode,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return JsModuleDeserializer(moduleDescriptor, klib, strategyResolver, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT, klib.libContainsErrorCode)
|
return JsModuleDeserializer(moduleDescriptor, klib, strategyResolver, klib.versions.abiVersion ?: KotlinAbiVersion.CURRENT, klib.libContainsErrorCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mapping: JsMapping by lazy { JsMapping(symbolTable.irFactory) }
|
|
||||||
|
|
||||||
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategyResolver: (String) -> DeserializationStrategy, libraryAbiVersion: KotlinAbiVersion, allowErrorCode: Boolean) :
|
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategyResolver: (String) -> DeserializationStrategy, libraryAbiVersion: KotlinAbiVersion, allowErrorCode: Boolean) :
|
||||||
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategyResolver, libraryAbiVersion, allowErrorCode)
|
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategyResolver, libraryAbiVersion, allowErrorCode)
|
||||||
|
|
||||||
@@ -102,15 +83,6 @@ class JsIrLinker(
|
|||||||
return deserializersForModules[moduleDescriptor.name.asString()] ?: error("Deserializer for $moduleDescriptor not found")
|
return deserializersForModules[moduleDescriptor.name.asString()] ?: error("Deserializer for $moduleDescriptor not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadIcIr(preprocess: (IrModuleFragment) -> Unit) {
|
|
||||||
deserializersForModules.values.reversed().forEach {
|
|
||||||
if (it.moduleDescriptor in loweredIcData) {
|
|
||||||
preprocess(it.moduleFragment)
|
|
||||||
}
|
|
||||||
it.postProcess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JsFePluginContext(
|
class JsFePluginContext(
|
||||||
override val moduleDescriptor: ModuleDescriptor,
|
override val moduleDescriptor: ModuleDescriptor,
|
||||||
override val symbolTable: ReferenceSymbolTable,
|
override val symbolTable: ReferenceSymbolTable,
|
||||||
|
|||||||
-1
@@ -13,7 +13,6 @@ where advanced options include:
|
|||||||
-Xir-base-class-in-metadata Write base class into metadata
|
-Xir-base-class-in-metadata Write base class into metadata
|
||||||
-Xir-build-cache Use compiler to build cache
|
-Xir-build-cache Use compiler to build cache
|
||||||
-Xir-dce Perform experimental dead code elimination
|
-Xir-dce Perform experimental dead code elimination
|
||||||
-Xir-dce-driven Perform a more experimental faster dead code elimination
|
|
||||||
-Xir-dce-print-reachability-info
|
-Xir-dce-print-reachability-info
|
||||||
Print declarations' reachability info to stdout during performing DCE
|
Print declarations' reachability info to stdout during performing DCE
|
||||||
-Xir-dce-runtime-diagnostic={log|exception}
|
-Xir-dce-runtime-diagnostic={log|exception}
|
||||||
|
|||||||
-5
@@ -210,11 +210,6 @@ object JsEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
|
|||||||
applicability = DirectiveApplicability.Global
|
applicability = DirectiveApplicability.Global
|
||||||
)
|
)
|
||||||
|
|
||||||
val LOWER_PER_MODULE by directive(
|
|
||||||
description = "",
|
|
||||||
applicability = DirectiveApplicability.Global
|
|
||||||
)
|
|
||||||
|
|
||||||
val KLIB_MAIN_MODULE by directive(
|
val KLIB_MAIN_MODULE by directive(
|
||||||
description = "Specify that main module is actually a klib",
|
description = "Specify that main module is actually a klib",
|
||||||
applicability = DirectiveApplicability.Global
|
applicability = DirectiveApplicability.Global
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ abstract class AbstractKlibTextTestCase : CodegenTestCase() {
|
|||||||
val typeTranslator =
|
val typeTranslator =
|
||||||
TypeTranslatorImpl(symbolTable, myEnvironment.configuration.languageVersionSettings, testDescriptor)
|
TypeTranslatorImpl(symbolTable, myEnvironment.configuration.languageVersionSettings, testDescriptor)
|
||||||
val irBuiltIns = IrBuiltInsOverDescriptors(testDescriptor.builtIns, typeTranslator, symbolTable)
|
val irBuiltIns = IrBuiltInsOverDescriptors(testDescriptor.builtIns, typeTranslator, symbolTable)
|
||||||
val irLinker = JsIrLinker(null, IrMessageLogger.None, irBuiltIns, symbolTable, null, null)
|
val irLinker = JsIrLinker(null, IrMessageLogger.None, irBuiltIns, symbolTable, null)
|
||||||
irLinker.deserializeIrModuleHeader(stdlibDescriptor, stdlib)
|
irLinker.deserializeIrModuleHeader(stdlibDescriptor, stdlib)
|
||||||
val testModule = irLinker.deserializeIrModuleHeader(testDescriptor, klib, { DeserializationStrategy.ALL })
|
val testModule = irLinker.deserializeIrModuleHeader(testDescriptor, klib, { DeserializationStrategy.ALL })
|
||||||
irLinker.init(null, emptyList())
|
irLinker.init(null, emptyList())
|
||||||
@@ -280,7 +280,7 @@ abstract class AbstractKlibTextTestCase : CodegenTestCase() {
|
|||||||
val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl, NameProvider.DEFAULT)
|
val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImpl, NameProvider.DEFAULT)
|
||||||
val context = psi2Ir.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable)
|
val context = psi2Ir.createGeneratorContext(moduleDescriptor, bindingContext, symbolTable)
|
||||||
val irBuiltIns = context.irBuiltIns
|
val irBuiltIns = context.irBuiltIns
|
||||||
val irLinker = JsIrLinker(moduleDescriptor, IrMessageLogger.None, irBuiltIns, symbolTable, null, null)
|
val irLinker = JsIrLinker(moduleDescriptor, IrMessageLogger.None, irBuiltIns, symbolTable, null)
|
||||||
irLinker.deserializeIrModuleHeader(stdlibDescriptor, stdlib)
|
irLinker.deserializeIrModuleHeader(stdlibDescriptor, stdlib)
|
||||||
|
|
||||||
return psi2Ir.generateModuleFragment(context, ktFiles, listOf(irLinker), emptyList(), expectActualSymbols) to bindingContext
|
return psi2Ir.generateModuleFragment(context, ktFiles, listOf(irLinker), emptyList(), expectActualSymbols) to bindingContext
|
||||||
|
|||||||
@@ -31,15 +31,15 @@ abstract class AbstractJsKLibABITestCase : AbstractKlibABITestCase() {
|
|||||||
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, MAIN_MODULE_NAME)
|
||||||
val kLib = MainModule.Klib(mainModulePath)
|
val kLib = MainModule.Klib(mainModulePath)
|
||||||
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries, emptyList(), false, false, emptyMap())
|
val moduleStructure = ModulesStructure(project, kLib, configuration, libraries, emptyList())
|
||||||
|
|
||||||
val ir = compile(
|
val ir = compile(
|
||||||
moduleStructure,
|
moduleStructure,
|
||||||
PhaseConfig(jsPhases),
|
PhaseConfig(jsPhases),
|
||||||
IrFactoryImplForJsIC(WholeWorldStageController()),
|
IrFactoryImplForJsIC(WholeWorldStageController()),
|
||||||
|
exportedDeclarations = setOf(FqName("box")),
|
||||||
propertyLazyInitialization = true,
|
propertyLazyInitialization = true,
|
||||||
granularity = JsGenerationGranularity.PER_MODULE,
|
granularity = JsGenerationGranularity.PER_MODULE,
|
||||||
exportedDeclarations = setOf(FqName("box")),
|
|
||||||
icCompatibleIr2Js = true
|
icCompatibleIr2Js = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class JsIrBackendFacade(
|
|||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
inputArtifact: BinaryArtifacts.KLib,
|
inputArtifact: BinaryArtifacts.KLib,
|
||||||
): BinaryArtifacts.Js? {
|
): BinaryArtifacts.Js? {
|
||||||
val (irModuleFragment, dependencyModules, _, symbolTable, deserializer, _) = moduleInfo
|
val (irModuleFragment, dependencyModules, _, symbolTable, deserializer) = moduleInfo
|
||||||
|
|
||||||
val splitPerModule = JsEnvironmentConfigurationDirectives.SPLIT_PER_MODULE in module.directives
|
val splitPerModule = JsEnvironmentConfigurationDirectives.SPLIT_PER_MODULE in module.directives
|
||||||
val splitPerFile = JsEnvironmentConfigurationDirectives.SPLIT_PER_FILE in module.directives
|
val splitPerFile = JsEnvironmentConfigurationDirectives.SPLIT_PER_FILE in module.directives
|
||||||
@@ -86,7 +86,6 @@ class JsIrBackendFacade(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val testPackage = extractTestPackage(testServices)
|
val testPackage = extractTestPackage(testServices)
|
||||||
val lowerPerModule = JsEnvironmentConfigurationDirectives.LOWER_PER_MODULE in module.directives
|
|
||||||
val skipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE in module.directives
|
val skipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE in module.directives
|
||||||
|
|
||||||
if (skipRegularMode) return null
|
if (skipRegularMode) return null
|
||||||
@@ -132,12 +131,10 @@ class JsIrBackendFacade(
|
|||||||
deserializer,
|
deserializer,
|
||||||
phaseConfig,
|
phaseConfig,
|
||||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
|
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
|
||||||
dceDriven = false,
|
|
||||||
dceRuntimeDiagnostic = null,
|
dceRuntimeDiagnostic = null,
|
||||||
es6mode = false,
|
es6mode = false,
|
||||||
propertyLazyInitialization = JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives,
|
propertyLazyInitialization = JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION in module.directives,
|
||||||
baseClassIntoMetadata = false,
|
baseClassIntoMetadata = false,
|
||||||
lowerPerModule = lowerPerModule,
|
|
||||||
safeExternalBoolean = JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN in module.directives,
|
safeExternalBoolean = JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN in module.directives,
|
||||||
safeExternalBooleanDiagnostic = module.directives[JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN_DIAGNOSTIC].singleOrNull(),
|
safeExternalBooleanDiagnostic = module.directives[JsEnvironmentConfigurationDirectives.SAFE_EXTERNAL_BOOLEAN_DIAGNOSTIC].singleOrNull(),
|
||||||
granularity = granularity,
|
granularity = granularity,
|
||||||
@@ -221,10 +218,7 @@ class JsIrBackendFacade(
|
|||||||
symbolTable,
|
symbolTable,
|
||||||
messageLogger,
|
messageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib = true,
|
loadFunctionInterfacesIntoStdlib = true,
|
||||||
emptyMap(),
|
) { if (it == mainModuleLib) moduleDescriptor else testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) }
|
||||||
{ emptySet() },
|
|
||||||
{ if (it == mainModuleLib) moduleDescriptor else testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadIrFromSources(
|
private fun loadIrFromSources(
|
||||||
@@ -254,14 +248,11 @@ class JsIrBackendFacade(
|
|||||||
inputArtifact.allKtFiles.values.toList(),
|
inputArtifact.allKtFiles.values.toList(),
|
||||||
sortDependencies(JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices)),
|
sortDependencies(JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices)),
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
emptyMap(),
|
|
||||||
symbolTable,
|
symbolTable,
|
||||||
messageLogger,
|
messageLogger,
|
||||||
loadFunctionInterfacesIntoStdlib = true,
|
loadFunctionInterfacesIntoStdlib = true,
|
||||||
verifySignatures,
|
verifySignatures,
|
||||||
{ emptySet() },
|
) { testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) }
|
||||||
{ testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jsOutputSink(perFileOutputDir: File): CompilerOutputSink {
|
private fun jsOutputSink(perFileOutputDir: File): CompilerOutputSink {
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ abstract class AbstractJsIrTest(
|
|||||||
defaultDirectives {
|
defaultDirectives {
|
||||||
val runIc = getBoolean("kotlin.js.ir.icMode")
|
val runIc = getBoolean("kotlin.js.ir.icMode")
|
||||||
if (runIc) +JsEnvironmentConfigurationDirectives.RUN_IC
|
if (runIc) +JsEnvironmentConfigurationDirectives.RUN_IC
|
||||||
if (runIc || getBoolean("kotlin.js.ir.lowerPerModule")) +JsEnvironmentConfigurationDirectives.LOWER_PER_MODULE
|
|
||||||
if (getBoolean("kotlin.js.ir.klibMainModule")) +JsEnvironmentConfigurationDirectives.KLIB_MAIN_MODULE
|
if (getBoolean("kotlin.js.ir.klibMainModule")) +JsEnvironmentConfigurationDirectives.KLIB_MAIN_MODULE
|
||||||
if (getBoolean("kotlin.js.ir.perModule", true)) +JsEnvironmentConfigurationDirectives.PER_MODULE
|
if (getBoolean("kotlin.js.ir.perModule", true)) +JsEnvironmentConfigurationDirectives.PER_MODULE
|
||||||
if (getBoolean("kotlin.js.ir.dce", true)) +JsEnvironmentConfigurationDirectives.RUN_IR_DCE
|
if (getBoolean("kotlin.js.ir.dce", true)) +JsEnvironmentConfigurationDirectives.RUN_IR_DCE
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ class TestModuleCache(val files: MutableMap<String, FileCache>) {
|
|||||||
return 0L
|
return 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serializedParts(path: String): SerializedIcDataForFile {
|
|
||||||
error("Is not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
|
||||||
error("Is not supported")
|
error("Is not supported")
|
||||||
}
|
}
|
||||||
@@ -97,10 +93,6 @@ class TestModuleCache(val files: MutableMap<String, FileCache>) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun commitICCacheData(path: String, icData: SerializedIcDataForFile) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun commitBinaryAst(path: String, astData: ByteArray) {
|
override fun commitBinaryAst(path: String, astData: ByteArray) {
|
||||||
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
val storage = files.getOrPut(path) { FileCache(path, null, null, null) }
|
||||||
storage.ast = astData
|
storage.ast = astData
|
||||||
|
|||||||
@@ -77,10 +77,7 @@ class ApiTest : KotlinTestWithEnvironment() {
|
|||||||
MainModule.Klib(File(fullRuntimeKlib).canonicalPath),
|
MainModule.Klib(File(fullRuntimeKlib).canonicalPath),
|
||||||
configuration,
|
configuration,
|
||||||
listOf(fullRuntimeKlib),
|
listOf(fullRuntimeKlib),
|
||||||
emptyList(),
|
emptyList()
|
||||||
false,
|
|
||||||
false,
|
|
||||||
emptyMap()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return loadIr(
|
return loadIr(
|
||||||
|
|||||||
Reference in New Issue
Block a user