From f147860fea0f33c95df2d231d0469f575abafe49 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 16 Nov 2016 11:13:40 +0700 Subject: [PATCH] backend: fix some bugs and improve RTTI * fix incorrect assert at RTTIGenerator.kt:109 * add `final override` methods to methods table (aka openMethods) * fix NPE when building vtable with `final override` methods * make vtable generation impl more clear --- .../backend/konan/llvm/RTTIGenerator.kt | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index d82a496284c..b5c4db8fc56 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -86,29 +86,24 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { getVtableEntries(classDesc.getSuperClassOrAny()) } - val inheritedVtableSlots = Array(superVtableEntries.size, { null }) - val methods = getMethodTableEntries(classDesc) // TODO: ensure order is well-defined - val entriesForNewVtableSlots = methods.toMutableSet() + val methods = classDesc.getContributedMethods() // TODO: ensure order is well-defined - methods.forEach { method -> - superVtableEntries.forEachIndexed { i, superMethod -> - if (OverridingUtil.overrides(method, superMethod)) { - assert (inheritedVtableSlots[i] == null) - inheritedVtableSlots[i] = method - - assert (method in entriesForNewVtableSlots) - entriesForNewVtableSlots.remove(method) - } - } + val inheritedVtableSlots = superVtableEntries.map { superMethod -> + methods.single { OverridingUtil.overrides(it, superMethod) } } - return inheritedVtableSlots.map { it!! } + methods.filter { it in entriesForNewVtableSlots } + return inheritedVtableSlots + (methods - inheritedVtableSlots).filter { it.isOverridable } } private fun getMethodTableEntries(classDesc: ClassDescriptor): List { assert (classDesc.modality != Modality.ABSTRACT) - val contributedDescriptors = classDesc.unsubstitutedMemberScope.getContributedDescriptors() + return classDesc.getContributedMethods().filter { it.isOverridableOrOverrides } + // TODO: probably method table should contain all accessible methods to improve binary compatibility + } + + private fun ClassDescriptor.getContributedMethods(): List { + val contributedDescriptors = unsubstitutedMemberScope.getContributedDescriptors() // (includes declarations from supers) val functions = contributedDescriptors.filterIsInstance() @@ -118,9 +113,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { val setters = properties.mapNotNull { it.setter } val allMethods = functions + getters + setters - - // TODO: adding or removing 'open' modifier will break the binary compatibility - return allMethods.filter { it.modality != Modality.FINAL } + return allMethods } private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMOpaqueValue?) {