From 7bbc04b6a259ac9137f539bc026c581cab529cb2 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Tue, 1 Jun 2021 16:27:00 +0300 Subject: [PATCH] JVM_IR: reconstruct fake overrides after IR deserialization. We need to keep track of local signatures for deserialized symbols. --- .../backend/jvm/JvmGeneratorExtensionsImpl.kt | 10 +- .../backend/common/overrides/FakeOverrides.kt | 11 +-- .../serialization/JvmIrSerializerSession.kt | 3 - .../deserializeLazyDeclarations.kt | 97 +++++++++++++++---- .../boxInline/innerClasses/fakeOverride.kt | 6 +- 5 files changed, 90 insertions(+), 37 deletions(-) diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensionsImpl.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensionsImpl.kt index 1b00f498afa..24b4c4abba7 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensionsImpl.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmGeneratorExtensionsImpl.kt @@ -125,10 +125,7 @@ open class JvmGeneratorExtensionsImpl( allowErrorNodes: Boolean ): Boolean { val serializedIr = (irClass.source as? KotlinJvmBinarySourceElement)?.binaryClass?.classHeader?.serializedIr ?: return false - deserializeClassFromByteArray( - serializedIr, stubGenerator.moduleDescriptor, stubGenerator.irBuiltIns, stubGenerator.symbolTable, parent, allowErrorNodes - ) - ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies() + deserializeClassFromByteArray(serializedIr, stubGenerator, irClass, allowErrorNodes) val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings) irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null) return true @@ -141,10 +138,7 @@ open class JvmGeneratorExtensionsImpl( allowErrorNodes: Boolean ): Boolean { val serializedIr = (irClass.source as? JvmPackagePartSource)?.knownJvmBinaryClass?.classHeader?.serializedIr ?: return false - deserializeIrFileFromByteArray( - serializedIr, stubGenerator.moduleDescriptor, stubGenerator.irBuiltIns, stubGenerator.symbolTable, irClass, allowErrorNodes - ) - ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies() + deserializeIrFileFromByteArray(serializedIr, stubGenerator, irClass, allowErrorNodes) val cachedFields = getCachedFields(stubGenerator.irBuiltIns.irFactory, stubGenerator.irBuiltIns.languageVersionSettings) irClass.transform(SingletonObjectJvmStaticTransformer(stubGenerator.irBuiltIns, cachedFields), null) return true diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt index 79d9f8f1424..eff65bd0340 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt @@ -42,7 +42,7 @@ class FakeOverrideGlobalDeclarationTable( fun clear() = table.clear() } -class FakeOverrideDeclarationTable( +open class FakeOverrideDeclarationTable( mangler: KotlinMangler.IrMangler, globalTable: FakeOverrideGlobalDeclarationTable = FakeOverrideGlobalDeclarationTable(mangler) ) : DeclarationTable(globalTable) { @@ -71,15 +71,14 @@ class FakeOverrideBuilder( val symbolTable: SymbolTable, mangler: KotlinMangler.IrMangler, 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() { private val haveFakeOverrides = mutableSetOf() 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 val fakeOverrideCandidates = mutableMapOf() @@ -169,7 +168,7 @@ class FakeOverrideBuilder( } } - private fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) { + fun provideFakeOverrides(klass: IrClass, compatibleMode: CompatibilityMode) { buildFakeOverrideChainsForClass(klass, compatibleMode) irOverridingUtil.clear() haveFakeOverrides.add(klass) diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmIrSerializerSession.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmIrSerializerSession.kt index fd96f836d80..4090e8b2c80 100644 --- a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmIrSerializerSession.kt +++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmIrSerializerSession.kt @@ -26,9 +26,6 @@ class JvmIrSerializerSession( // 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 { val proto = JvmIr.JvmIrFile.newBuilder() diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt index 8cb5f8a680b..8c382f91c87 100644 --- a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt +++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/deserializeLazyDeclarations.kt @@ -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.FakeOverrideBuilder +import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideDeclarationTable import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinder 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.jvm.serialization.proto.JvmIr 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.JvmIrMangler import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.lazy.LazyIrFactory import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns 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.SymbolTable +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.protobuf.ByteString fun deserializeClassFromByteArray( byteArray: ByteArray, - moduleDescriptor: ModuleDescriptor, - irBuiltIns: IrBuiltIns, - symbolTable: SymbolTable, - parent: IrDeclarationParent, + stubGenerator: DeclarationStubGenerator, + irClass: IrClass, allowErrorNodes: Boolean, ) { + val irBuiltIns = stubGenerator.irBuiltIns + val symbolTable = stubGenerator.symbolTable val irProto = JvmIr.JvmIrClass.parseFrom(byteArray) val irLibraryFile = IrLibraryFileFromAnnotation( irProto.auxTables.typeList, @@ -42,7 +48,11 @@ fun deserializeClassFromByteArray( irProto.auxTables.bodyList ) val descriptorFinder = - DescriptorByIdSignatureFinder(moduleDescriptor, JvmDescriptorMangler(null), DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES) + DescriptorByIdSignatureFinder( + stubGenerator.moduleDescriptor, + JvmDescriptorMangler(null), + DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES + ) val symbolDeserializer = IrSymbolDeserializer( symbolTable, irLibraryFile, @@ -57,26 +67,29 @@ fun deserializeClassFromByteArray( val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory) val deserializer = IrDeclarationDeserializer( - irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, parent, + irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, irClass.parent, allowErrorNodes = allowErrorNodes, deserializeInlineFunctions = true, deserializeBodies = true, symbolDeserializer, DefaultFakeOverrideClassFilter, - makeEmptyFakeOverrideBuilder(symbolTable, irBuiltIns) + makeSimpleFakeOverrideBuilder(symbolTable, irBuiltIns, symbolDeserializer) ) deserializer.deserializeIrClass(irProto.irClass) + + ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies() + buildFakeOverridesForLocalClasses(stubGenerator.symbolTable, stubGenerator.irBuiltIns, symbolDeserializer, irClass) } fun deserializeIrFileFromByteArray( byteArray: ByteArray, - moduleDescriptor: ModuleDescriptor, - irBuiltIns: IrBuiltIns, - symbolTable: SymbolTable, + stubGenerator: DeclarationStubGenerator, facadeClass: IrClass, allowErrorNodes: Boolean, ) { + val irBuiltIns = stubGenerator.irBuiltIns + val symbolTable = stubGenerator.symbolTable val irProto = JvmIr.JvmIrFile.parseFrom(byteArray) val irLibraryFile = IrLibraryFileFromAnnotation( irProto.auxTables.typeList, @@ -85,7 +98,11 @@ fun deserializeIrFileFromByteArray( irProto.auxTables.bodyList ) val descriptorFinder = - DescriptorByIdSignatureFinder(moduleDescriptor, JvmDescriptorMangler(null), DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES) + DescriptorByIdSignatureFinder( + stubGenerator.moduleDescriptor, + JvmDescriptorMangler(null), + DescriptorByIdSignatureFinder.LookupMode.MODULE_WITH_DEPENDENCIES + ) val symbolDeserializer = IrSymbolDeserializer( symbolTable, irLibraryFile, @@ -99,6 +116,8 @@ fun deserializeIrFileFromByteArray( val lazyIrFactory = LazyIrFactory(irBuiltIns.irFactory) + val fakeOverrideBuilder = makeSimpleFakeOverrideBuilder(symbolTable, irBuiltIns, symbolDeserializer) + val deserializer = IrDeclarationDeserializer( irBuiltIns, symbolTable, lazyIrFactory, irLibraryFile, facadeClass, allowErrorNodes = allowErrorNodes, @@ -106,11 +125,14 @@ fun deserializeIrFileFromByteArray( deserializeBodies = true, symbolDeserializer, DefaultFakeOverrideClassFilter, - makeEmptyFakeOverrideBuilder(symbolTable, irBuiltIns) + fakeOverrideBuilder ) for (declarationProto in irProto.declarationList) { deserializer.deserializeDeclaration(declarationProto) } + + ExternalDependenciesGenerator(stubGenerator.symbolTable, listOf(stubGenerator)).generateUnboundSymbolsAsDependencies() + buildFakeOverridesForLocalClasses(stubGenerator.symbolTable, stubGenerator.irBuiltIns, symbolDeserializer, facadeClass) } private class IrLibraryFileFromAnnotation( @@ -164,17 +186,58 @@ private fun referencePublicSymbol( } // 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( 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( parent: IrDeclaration, idSignature: IdSignature - ): IrSimpleFunctionSymbol? = null + ): IrSimpleFunctionSymbol = + symbolDeserializer.referenceSimpleFunctionByLocalSignature(idSignature) }, symbolTable, - IdSignatureSerializer(JvmIrMangler), - irBuiltIns + signatureSerializer, + 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, + 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) + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/innerClasses/fakeOverride.kt b/compiler/testData/codegen/boxInline/innerClasses/fakeOverride.kt index ac9772c5eaa..3ec84aafdb9 100644 --- a/compiler/testData/codegen/boxInline/innerClasses/fakeOverride.kt +++ b/compiler/testData/codegen/boxInline/innerClasses/fakeOverride.kt @@ -1,12 +1,12 @@ // FILE: 1.kt - open class C { - fun f() = "OK" + fun o() = "O" + val k = "K" } inline fun inlineFun(): String { val cc = object : C() {} - return cc.f() + return cc.o() + cc.k } // FILE: 2.kt