JVM_IR: reconstruct fake overrides after IR deserialization.

We need to keep track of local signatures for deserialized symbols.
This commit is contained in:
Georgy Bronnikov
2021-06-01 16:27:00 +03:00
committed by TeamCityServer
parent a63cc95a2a
commit 7bbc04b6a2
5 changed files with 90 additions and 37 deletions
@@ -125,10 +125,7 @@ open class JvmGeneratorExtensionsImpl(
allowErrorNodes: Boolean allowErrorNodes: Boolean
): Boolean { ): Boolean {
val serializedIr = (irClass.source as? KotlinJvmBinarySourceElement)?.binaryClass?.classHeader?.serializedIr ?: return false val serializedIr = (irClass.source as? KotlinJvmBinarySourceElement)?.binaryClass?.classHeader?.serializedIr ?: return false
deserializeClassFromByteArray( deserializeClassFromByteArray(serializedIr, stubGenerator, irClass, allowErrorNodes)
serializedIr, stubGenerator.moduleDescriptor, stubGenerator.irBuiltIns, stubGenerator.symbolTable, parent, allowErrorNodes
)
ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies()
val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings) val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings)
irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null) irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null)
return true return true
@@ -141,10 +138,7 @@ open class JvmGeneratorExtensionsImpl(
allowErrorNodes: Boolean allowErrorNodes: Boolean
): Boolean { ): Boolean {
val serializedIr = (irClass.source as? JvmPackagePartSource)?.knownJvmBinaryClass?.classHeader?.serializedIr ?: return false val serializedIr = (irClass.source as? JvmPackagePartSource)?.knownJvmBinaryClass?.classHeader?.serializedIr ?: return false
deserializeIrFileFromByteArray( deserializeIrFileFromByteArray(serializedIr, stubGenerator, irClass, allowErrorNodes)
serializedIr, stubGenerator.moduleDescriptor, stubGenerator.irBuiltIns, stubGenerator.symbolTable, irClass, allowErrorNodes
)
ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies()
val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings) val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings)
irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null) irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null)
return true return true
@@ -42,7 +42,7 @@ class FakeOverrideGlobalDeclarationTable(
fun clear() = table.clear() fun clear() = table.clear()
} }
class FakeOverrideDeclarationTable( open class FakeOverrideDeclarationTable(
mangler: KotlinMangler.IrMangler, mangler: KotlinMangler.IrMangler,
globalTable: FakeOverrideGlobalDeclarationTable = FakeOverrideGlobalDeclarationTable(mangler) globalTable: FakeOverrideGlobalDeclarationTable = FakeOverrideGlobalDeclarationTable(mangler)
) : DeclarationTable(globalTable) { ) : DeclarationTable(globalTable) {
@@ -71,15 +71,14 @@ class FakeOverrideBuilder(
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
mangler: KotlinMangler.IrMangler, mangler: KotlinMangler.IrMangler,
typeSystem: IrTypeSystemContext, typeSystem: IrTypeSystemContext,
val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter val platformSpecificClassFilter: FakeOverrideClassFilter = DefaultFakeOverrideClassFilter,
// TODO: The declaration table is needed for the signaturer.
private val fakeOverrideDeclarationTable: DeclarationTable = FakeOverrideDeclarationTable(mangler),
) : FakeOverrideBuilderStrategy() { ) : FakeOverrideBuilderStrategy() {
private val haveFakeOverrides = mutableSetOf<IrClass>() private val haveFakeOverrides = mutableSetOf<IrClass>()
private val irOverridingUtil = IrOverridingUtil(typeSystem, this) private val irOverridingUtil = IrOverridingUtil(typeSystem, this)
// TODO: The declaration table is needed for the signaturer.
private val fakeOverrideDeclarationTable = FakeOverrideDeclarationTable(mangler)
// private class CompatibilityMode(val oldSignatures: Boolean) // private class CompatibilityMode(val oldSignatures: Boolean)
private val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>() private val fakeOverrideCandidates = mutableMapOf<IrClass, CompatibilityMode>()
@@ -169,7 +168,7 @@ class FakeOverrideBuilder(
} }
} }
private fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) { fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) {
buildFakeOverrideChainsForClass(klass, compatibleMode) buildFakeOverrideChainsForClass(klass, compatibleMode)
irOverridingUtil.clear() irOverridingUtil.clear()
haveFakeOverrides.add(klass) haveFakeOverrides.add(klass)
@@ -26,9 +26,6 @@ class JvmIrSerializerSession(
// Usage protocol: construct an instance, call only one of `serializeIrFile()` and `serializeTopLevelClass()` only once. // Usage protocol: construct an instance, call only one of `serializeIrFile()` and `serializeTopLevelClass()` only once.
// We do not reconstruct fake overrides upon deserialization (yet).
override fun backendSpecificSerializeAllMembers(irClass: IrClass): Boolean = true
fun serializeJvmIrFile(irFile: IrFile): JvmIr.JvmIrFile { fun serializeJvmIrFile(irFile: IrFile): JvmIr.JvmIrFile {
val proto = JvmIr.JvmIrFile.newBuilder() val proto = JvmIr.JvmIrFile.newBuilder()
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.serialization
import org.jetbrains.kotlin.backend.common.overrides.DefaultFakeOverrideClassFilter import org.jetbrains.kotlin.backend.common.overrides.DefaultFakeOverrideClassFilter
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideDeclarationTable
import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinder import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinder
import org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer import org.jetbrains.kotlin.backend.common.serialization.IrDeclarationDeserializer
@@ -16,24 +17,29 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolD
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.jvm.serialization.proto.JvmIr import org.jetbrains.kotlin.backend.jvm.serialization.proto.JvmIr
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.LazyIrFactory import org.jetbrains.kotlin.ir.declarations.lazy.LazyIrFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.protobuf.ByteString import org.jetbrains.kotlin.protobuf.ByteString
fun deserializeClassFromByteArray( fun deserializeClassFromByteArray(
byteArray: ByteArray, byteArray: ByteArray,
moduleDescriptor: ModuleDescriptor, stubGenerator: DeclarationStubGenerator,
irBuiltIns: IrBuiltIns, irClass: IrClass,
symbolTable: SymbolTable,
parent: IrDeclarationParent,
allowErrorNodes: Boolean, allowErrorNodes: Boolean,
) { ) {
val irBuiltIns = stubGenerator.irBuiltIns
val symbolTable = stubGenerator.symbolTable
val irProto = JvmIr.JvmIrClass.parseFrom(byteArray) val irProto = JvmIr.JvmIrClass.parseFrom(byteArray)
val irLibraryFile = IrLibraryFileFromAnnotation( val irLibraryFile = IrLibraryFileFromAnnotation(
irProto.auxTables.typeList, irProto.auxTables.typeList,
@@ -42,7 +48,11 @@ fun deserializeClassFromByteArray(
irProto.auxTables.bodyList irProto.auxTables.bodyList
) )
val descriptorFinder = val descriptorFinder =
DescriptorByIdSignatureFinder(moduleDescriptor, JvmDescriptorMangler(null), DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES) DescriptorByIdSignatureFinder(
stubGenerator.moduleDescriptor,
JvmDescriptorMangler(null),
DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES
)
val symbolDeserializer = IrSymbolDeserializer( val symbolDeserializer = IrSymbolDeserializer(
symbolTable, symbolTable,
irLibraryFile, irLibraryFile,
@@ -57,26 +67,29 @@ fun deserializeClassFromByteArray(
val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory) val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory)
val deserializer = IrDeclarationDeserializer( val deserializer = IrDeclarationDeserializer(
irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, parent, irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, irClass.parent,
allowErrorNodes = allowErrorNodes, allowErrorNodes = allowErrorNodes,
deserializeInlineFunctions = true, deserializeInlineFunctions = true,
deserializeBodies = true, deserializeBodies = true,
symbolDeserializer, symbolDeserializer,
DefaultFakeOverrideClassFilter, DefaultFakeOverrideClassFilter,
makeEmptyFakeOverrideBuilder(symbolTable, irBuiltIns) makeSimpleFakeOverrideBuilder(symbolTable, irBuiltIns, symbolDeserializer)
) )
deserializer.deserializeIrClass(irProto.irClass) deserializer.deserializeIrClass(irProto.irClass)
ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies()
buildFakeOverridesForLocalClasses(stubGenerator.symbolTable, stubGenerator.irBuiltIns, symbolDeserializer, irClass)
} }
fun deserializeIrFileFromByteArray( fun deserializeIrFileFromByteArray(
byteArray: ByteArray, byteArray: ByteArray,
moduleDescriptor: ModuleDescriptor, stubGenerator: DeclarationStubGenerator,
irBuiltIns: IrBuiltIns,
symbolTable: SymbolTable,
facadeClass: IrClass, facadeClass: IrClass,
allowErrorNodes: Boolean, allowErrorNodes: Boolean,
) { ) {
val irBuiltIns = stubGenerator.irBuiltIns
val symbolTable = stubGenerator.symbolTable
val irProto = JvmIr.JvmIrFile.parseFrom(byteArray) val irProto = JvmIr.JvmIrFile.parseFrom(byteArray)
val irLibraryFile = IrLibraryFileFromAnnotation( val irLibraryFile = IrLibraryFileFromAnnotation(
irProto.auxTables.typeList, irProto.auxTables.typeList,
@@ -85,7 +98,11 @@ fun deserializeIrFileFromByteArray(
irProto.auxTables.bodyList irProto.auxTables.bodyList
) )
val descriptorFinder = val descriptorFinder =
DescriptorByIdSignatureFinder(moduleDescriptor, JvmDescriptorMangler(null), DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES) DescriptorByIdSignatureFinder(
stubGenerator.moduleDescriptor,
JvmDescriptorMangler(null),
DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES
)
val symbolDeserializer = IrSymbolDeserializer( val symbolDeserializer = IrSymbolDeserializer(
symbolTable, symbolTable,
irLibraryFile, irLibraryFile,
@@ -99,6 +116,8 @@ fun deserializeIrFileFromByteArray(
val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory) val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory)
val fakeOverrideBuilder = makeSimpleFakeOverrideBuilder(symbolTable, irBuiltIns, symbolDeserializer)
val deserializer = IrDeclarationDeserializer( val deserializer = IrDeclarationDeserializer(
irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, facadeClass, irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, facadeClass,
allowErrorNodes = allowErrorNodes, allowErrorNodes = allowErrorNodes,
@@ -106,11 +125,14 @@ fun deserializeIrFileFromByteArray(
deserializeBodies = true, deserializeBodies = true,
symbolDeserializer, symbolDeserializer,
DefaultFakeOverrideClassFilter, DefaultFakeOverrideClassFilter,
makeEmptyFakeOverrideBuilder(symbolTable, irBuiltIns) fakeOverrideBuilder
) )
for (declarationProto in irProto.declarationList) { for (declarationProto in irProto.declarationList) {
deserializer.deserializeDeclaration(declarationProto) deserializer.deserializeDeclaration(declarationProto)
} }
ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies()
buildFakeOverridesForLocalClasses(stubGenerator.symbolTable, stubGenerator.irBuiltIns, symbolDeserializer, facadeClass)
} }
private class IrLibraryFileFromAnnotation( private class IrLibraryFileFromAnnotation(
@@ -164,17 +186,58 @@ private fun referencePublicSymbol(
} }
// TODO: implement properly // TODO: implement properly
private fun makeEmptyFakeOverrideBuilder(symbolTable: SymbolTable, irBuiltIns: IrBuiltIns): FakeOverrideBuilder { fun makeSimpleFakeOverrideBuilder(
symbolTable: SymbolTable,
irBuiltIns: IrBuiltIns,
symbolDeserializer: IrSymbolDeserializer
): FakeOverrideBuilder {
val signatureSerializer = IdSignatureSerializer(JvmIrMangler)
return FakeOverrideBuilder( return FakeOverrideBuilder(
object : FileLocalAwareLinker { object : FileLocalAwareLinker {
override fun tryReferencingPropertyByLocalSignature(parent: IrDeclaration, idSignature: IdSignature): IrPropertySymbol? = null override fun tryReferencingPropertyByLocalSignature(parent: IrDeclaration, idSignature: IdSignature): IrPropertySymbol =
symbolDeserializer.referencePropertyByLocalSignature(idSignature)
override fun tryReferencingSimpleFunctionByLocalSignature( override fun tryReferencingSimpleFunctionByLocalSignature(
parent: IrDeclaration, idSignature: IdSignature parent: IrDeclaration, idSignature: IdSignature
): IrSimpleFunctionSymbol? = null ): IrSimpleFunctionSymbol =
symbolDeserializer.referenceSimpleFunctionByLocalSignature(idSignature)
}, },
symbolTable, symbolTable,
IdSignatureSerializer(JvmIrMangler), signatureSerializer,
irBuiltIns irBuiltIns,
fakeOverrideDeclarationTable = PrePopulatedDeclarationTable(symbolDeserializer.deserializedSymbols, signatureSerializer)
) )
} }
private fun buildFakeOverridesForLocalClasses(
symbolTable: SymbolTable,
irBuiltIns: IrBuiltIns,
symbolDeserializer: IrSymbolDeserializer,
toplevel: IrClass
) {
val builder = makeSimpleFakeOverrideBuilder(symbolTable, irBuiltIns, symbolDeserializer)
toplevel.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitClass(declaration: IrClass) {
if (declaration.visibility == DescriptorVisibilities.LOCAL) {
builder.provideFakeOverrides(declaration)
}
super.visitClass(declaration)
}
})
}
class PrePopulatedDeclarationTable(
sig2symbol: Map<IdSignature, IrSymbol>,
signatureSerializer: IdSignatureSerializer
) : FakeOverrideDeclarationTable(signatureSerializer) {
private val symbol2Sig = sig2symbol.entries.associate { (x, y) -> y to x }
override fun tryComputeBackendSpecificSignature(declaration: IrDeclaration): IdSignature? {
symbol2Sig[declaration.symbol]?.let { return it }
return super.tryComputeBackendSpecificSignature(declaration)
}
}
@@ -1,12 +1,12 @@
// FILE: 1.kt // FILE: 1.kt
open class C { open class C {
fun f() = "OK" fun o() = "O"
val k = "K"
} }
inline fun inlineFun(): String { inline fun inlineFun(): String {
val cc = object : C() {} val cc = object : C() {}
return cc.f() return cc.o() + cc.k
} }
// FILE: 2.kt // FILE: 2.kt