From 61d3ae147745f038ead8b52e6efb26d9a55269ed Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 1 Feb 2021 12:42:46 +0300 Subject: [PATCH] Refactor building of reverse adapters in ObjCExportCodeGenerator * Make it more understandable and reliable: don't predict which reverse adapters are inherited, reuse information from generating super types instead. * Drop usages of obsolete "IrDeclaration.descriptor" --- .../objcexport/ObjCExportCodeGenerator.kt | 53 ++++++++++++++++--- .../runtime/src/main/cpp/ObjCExport.mm | 4 ++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 52b92313de9..948787b315b 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.konan.target.Family import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.LinkerOutputKind import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.DFS internal fun TypeBridge.makeNothing() = when (this) { is ReferenceBridge, is BlockPointerBridge -> kNullInt8Ptr @@ -235,7 +236,7 @@ internal class ObjCExportCodeGenerator( val allReverseAdapters = createReverseAdapters(types) return types.map { - val reverseAdapters = allReverseAdapters.getValue(it) + val reverseAdapters = allReverseAdapters.getValue(it).adapters when (it) { objCClassForAny -> { createTypeAdapter(it, superClass = null, reverseAdapters) @@ -1355,14 +1356,51 @@ private fun ObjCExportCodeGenerator.createTypeAdapter( private fun ObjCExportCodeGenerator.createReverseAdapters( types: List -): Map> { - return types.associateWith { createReverseAdapters(it) } +): Map { + val irClassSymbolToType = types.associateBy { it.irClassSymbol } + + val result = mutableMapOf() + + fun getOrCreateFor(type: ObjCTypeForKotlinType): ReverseAdapters = result.getOrPut(type) { + // Each type also inherits reverse adapters from super types. + // This is handled in runtime when building TypeInfo for Swift or Obj-C type + // subclassing Kotlin classes or interfaces. See [createTypeInfo] in ObjCExport.mm. + val allSuperClasses = DFS.dfs( + type.irClassSymbol.owner.superClasses, + { it.owner.superClasses }, + object : DFS.NodeHandlerWithListResult() { + override fun afterChildren(current: IrClassSymbol) { + this.result += current + } + } + ) + + val inheritsAdaptersFrom = allSuperClasses.mapNotNull { irClassSymbolToType[it] } + + val inheritedAdapters = inheritsAdaptersFrom.map { getOrCreateFor(it) } + + createReverseAdapters(type, inheritedAdapters) + } + + types.forEach { getOrCreateFor(it) } + + return result } +private class ReverseAdapters( + val adapters: List, + val coveredMethods: Set +) + private fun ObjCExportCodeGenerator.createReverseAdapters( - type: ObjCTypeForKotlinType -): List { + type: ObjCTypeForKotlinType, + inheritedAdapters: List +): ReverseAdapters { val result = mutableListOf() + val coveredMethods = mutableSetOf() + + val methodsCoveredByInheritedAdapters = inheritedAdapters.flatMapTo(mutableSetOf()) { it.coveredMethods } + val allBaseMethodsByIr = type.kotlinMethods.map { it.baseMethod }.associateBy { it.symbol.owner } for (method in type.irClassSymbol.owner.simpleFunctions()) { @@ -1381,7 +1419,7 @@ private fun ObjCExportCodeGenerator.createReverseAdapters( val allOverriddenMethods = method.allOverriddenFunctions val (inherited, uninherited) = allOverriddenMethods.partition { - it != method && mapper.shouldBeExposed(it.descriptor) + it in methodsCoveredByInheritedAdapters } inherited.forEach { @@ -1401,6 +1439,7 @@ private fun ObjCExportCodeGenerator.createReverseAdapters( presentMethodTableBridges += functionName presentItableBridges += itablePlace result += createReverseAdapter(it, baseMethod, functionName, vtableIndex, itablePlace) + coveredMethods += it } } @@ -1412,7 +1451,7 @@ private fun ObjCExportCodeGenerator.createReverseAdapters( } } - return result + return ReverseAdapters(result, coveredMethods) } private fun ObjCExportCodeGenerator.nonOverridableAdapter( diff --git a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm index 9988eaf427a..795d1a91b94 100644 --- a/kotlin-native/runtime/src/main/cpp/ObjCExport.mm +++ b/kotlin-native/runtime/src/main/cpp/ObjCExport.mm @@ -902,6 +902,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co } }; + // Compiler relies on using reverse adapters here from all supertypes + // in [ObjCExportCodeGenerator.createReverseAdapters]. for (const TypeInfo* t : supers) { const ObjCTypeAdapter* typeAdapter = getTypeAdapter(t); if (typeAdapter == nullptr) continue; @@ -921,6 +923,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co } } + // Compiler relies on using reverse adapters here from all supertypes + // in [ObjCExportCodeGenerator.createReverseAdapters]. for (const TypeInfo* typeInfo : addedInterfaces) { const ObjCTypeAdapter* typeAdapter = getTypeAdapter(typeInfo);