[JS IR] Cleanup pir IC code

This commit is contained in:
Roman Artemev
2021-12-20 22:05:26 +03:00
committed by teamcity
parent 287c23269a
commit 353bfe9018
21 changed files with 27 additions and 1488 deletions
@@ -28,7 +28,7 @@ private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte
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 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 {
fun fileFingerPrint(path: String): Hash
fun serializedParts(path: String): SerializedIcDataForFile
fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>>
fun inlineHashes(path: String, sigResolver: (Int) -> IdSignature): Map<IdSignature, TransHash>
@@ -60,10 +58,6 @@ interface PersistentCacheProvider {
return 0
}
override fun serializedParts(path: String): SerializedIcDataForFile {
TODO("..")
}
override fun inlineGraphForFile(path: String, sigResolver: (Int) -> IdSignature): Collection<Pair<IdSignature, TransHash>> {
return emptyList()
}
@@ -116,11 +110,6 @@ class PersistentCacheProviderImpl(private val cachePath: String) : PersistentCac
} else 0
}
override fun serializedParts(path: String): SerializedIcDataForFile {
val fileDir = path.fileDir
return fileDir.readIcDataBinary()
}
private fun parseHashList(
fileDir: File,
fileName: String,
@@ -209,7 +198,6 @@ interface PersistentCacheConsumer {
fun commitInlineFunctions(path: String, hashes: Collection<Pair<IdSignature, TransHash>>, sigResolver: (IdSignature) -> Int)
fun commitFileFingerPrint(path: String, fingerprint: Hash)
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 commitBinaryDts(path: String, dstData: 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) {
}
@@ -306,12 +291,6 @@ class PersistentCacheConsumerImpl(private val cachePath: String) : PersistentCac
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) {
val fileId = createFileCacheId(path)
val cacheDir = File(cachePath)
@@ -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
}
@@ -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
}
}
}
}
}
}
@@ -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.ir.IrBuiltIns
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.JsIrModuleSerializer
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.utils.DFS
import java.io.File
import org.jetbrains.kotlin.konan.file.File as KFile
val KotlinLibrary.moduleName: String
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)
@@ -83,11 +80,6 @@ val KotlinLibrary.isBuiltIns: Boolean
.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
.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
get() = get(CommonConfigurationKeys.METADATA_VERSION) as? KlibMetadataVersion ?: KlibMetadataVersion.INSTANCE
@@ -255,9 +247,7 @@ data class IrModuleInfo(
val allDependencies: List<IrModuleFragment>,
val bultins: IrBuiltIns,
val symbolTable: SymbolTable,
val deserializer: JsIrLinker,
val moduleFragmentToUniqueName: Map<IrModuleFragment, String>,
val loweredIrLoaded: Set<IrModuleFragment> = emptySet(),
val deserializer: JsIrLinker
)
fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<KotlinLibrary> {
@@ -269,14 +259,6 @@ fun sortDependencies(mapping: Map<KotlinLibrary, ModuleDescriptor>): Collection<
}.reversed()
}
interface LoweringsCacheProvider {
fun cacheByPath(path: String): SerializedIcData?
}
object EmptyLoweringsCacheProvider : LoweringsCacheProvider {
override fun cacheByPath(path: String): SerializedIcData? = null
}
fun deserializeDependencies(
sortedDependencies: Collection<KotlinLibrary>,
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 ->
IrFileImpl(
NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"),
@@ -345,31 +319,13 @@ fun loadIr(
mainModule.files,
sortDependencies(depsDescriptors.descriptors),
friendModules,
depsDescriptors.loweredIcData,
symbolTable,
messageLogger,
loadFunctionInterfacesIntoStdlib,
verifySignatures,
{ depsDescriptors.modulesWithCaches(it) },
{ depsDescriptors.getModuleDescriptor(it) },
)
) { depsDescriptors.getModuleDescriptor(it) }
}
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 mainModuleLib = allDependencies.find { it.libraryFile.canonicalPath == mainPath }
?: error("No module with ${mainModule.libPath} found")
@@ -386,10 +342,7 @@ fun loadIr(
symbolTable,
messageLogger,
loadFunctionInterfacesIntoStdlib,
loweredIcData,
{ depsDescriptors.modulesWithCaches(it) },
{ depsDescriptors.getModuleDescriptor(it) },
)
) { depsDescriptors.getModuleDescriptor(it) }
}
}
}
@@ -404,8 +357,6 @@ fun getIrModuleInfoForKlib(
symbolTable: SymbolTable,
messageLogger: IrMessageLogger,
loadFunctionInterfacesIntoStdlib: Boolean,
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
mapping: (KotlinLibrary) -> ModuleDescriptor,
): IrModuleInfo {
val mainModuleLib = sortedDependencies.last()
@@ -422,7 +373,6 @@ fun getIrModuleInfoForKlib(
symbolTable,
null,
null,
loweredIcData,
friendModules,
allowUnboundSymbols
)
@@ -443,11 +393,7 @@ fun getIrModuleInfoForKlib(
ExternalDependenciesGenerator(symbolTable, listOf(irLinker)).generateUnboundSymbolsAsDependencies()
irLinker.postProcess()
return IrModuleInfo(
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
filterModulesWithCache(deserializedModuleFragments)
)
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -458,12 +404,10 @@ fun getIrModuleInfoForSourceFiles(
files: List<KtFile>,
allSortedDependencies: Collection<KotlinLibrary>,
friendModules: Map<String, List<String>>,
loweredIcData: Map<ModuleDescriptor, SerializedIcData>,
symbolTable: SymbolTable,
messageLogger: IrMessageLogger,
loadFunctionInterfacesIntoStdlib: Boolean,
verifySignatures: Boolean,
filterModulesWithCache: (Iterable<IrModuleFragment>) -> Set<IrModuleFragment>,
mapping: (KotlinLibrary) -> ModuleDescriptor
): IrModuleInfo {
val irBuiltIns = psi2IrContext.irBuiltIns
@@ -481,7 +425,6 @@ fun getIrModuleInfoForSourceFiles(
symbolTable,
feContext,
null,
loweredIcData,
friendModules,
allowUnboundSymbols
)
@@ -517,11 +460,7 @@ fun getIrModuleInfoForSourceFiles(
irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) }
}
return IrModuleInfo(
moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker,
deserializedModuleFragmentsToLib.getUniqueNameForEachFragment(),
filterModulesWithCache(deserializedModuleFragments)
)
return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker)
}
fun prepareAnalyzedSourceModule(
@@ -531,13 +470,10 @@ fun prepareAnalyzedSourceModule(
dependencies: List<String>,
friendDependencies: List<String>,
analyzer: AbstractAnalyzerWithCompilerReport,
icUseGlobalSignatures: Boolean = false,
icUseStdlibCache: Boolean = false,
icCache: Map<String, ICCache> = emptyMap(),
errorPolicy: ErrorTolerancePolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT,
): ModulesStructure {
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 {
runAnalysis(errorPolicy, analyzer)
}
@@ -626,19 +562,7 @@ class ModulesStructure(
val compilerConfiguration: CompilerConfiguration,
val dependencies: 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(
dependencies,
@@ -662,7 +586,7 @@ class ModulesStructure(
}.toMap()
}
val builtInsDep = allDependencies.find { it.library.isBuiltIns }
private val builtInsDep = allDependencies.find { it.library.isBuiltIns }
class JsFrontEndResult(val jsAnalysisResult: AnalysisResult, val hasErrors: Boolean) {
val moduleDescriptor: ModuleDescriptor
@@ -719,8 +643,6 @@ class ModulesStructure(
// TODO: these are roughly equivalent to KlibResolvedModuleDescriptorsFactoryImpl. Refactor me.
val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>()
val loweredIcData = mutableMapOf<ModuleDescriptor, SerializedIcData>()
fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) {
val isBuiltIns = current.unresolvedDependencies.isEmpty()
@@ -738,17 +660,9 @@ class ModulesStructure(
val dependencies = moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
md.setDependencies(listOf(md) + dependencies)
loweringsCacheProvider.cacheByPath(current.libraryFile.absolutePath)?.let { icData ->
loweredIcData[md] = icData
}
md
}
fun modulesWithCaches(allModules: Iterable<IrModuleFragment>): Set<IrModuleFragment> {
return allModules.filter { it.descriptor in loweredIcData }.toSet()
}
val builtInModuleDescriptor =
if (builtInsDep != null)
getModuleDescriptor(builtInsDep.library)
@@ -9,12 +9,8 @@ import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
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.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.IrLibrary
@@ -26,7 +22,6 @@ class JsIrLinker(
private val currentModule: ModuleDescriptor?, messageLogger: IrMessageLogger, builtIns: IrBuiltIns, symbolTable: SymbolTable,
override val translationPluginContext: TranslationPluginContext?,
private val icData: ICData? = null,
private val loweredIcData: Map<ModuleDescriptor, SerializedIcData> = emptyMap(),
friendModules: Map<String, Collection<String>> = emptyMap(),
allowUnboundSymbols: Boolean = false
) : KotlinIrLinker(
@@ -53,23 +48,9 @@ class JsIrLinker(
override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: KotlinLibrary?, strategyResolver: (String) -> DeserializationStrategy): IrModuleDeserializer {
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)
}
val mapping: JsMapping by lazy { JsMapping(symbolTable.irFactory) }
private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategyResolver: (String) -> DeserializationStrategy, libraryAbiVersion: KotlinAbiVersion, allowErrorCode: Boolean) :
BasicIrModuleDeserializer(this, moduleDescriptor, klib, strategyResolver, libraryAbiVersion, allowErrorCode)
@@ -102,15 +83,6 @@ class JsIrLinker(
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(
override val moduleDescriptor: ModuleDescriptor,
override val symbolTable: ReferenceSymbolTable,