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
This commit is contained in:
Svyatoslav Scherbina
2016-11-16 11:13:40 +07:00
committed by SvyatoslavScherbina
parent db15540a74
commit f147860fea
@@ -86,29 +86,24 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
getVtableEntries(classDesc.getSuperClassOrAny()) getVtableEntries(classDesc.getSuperClassOrAny())
} }
val inheritedVtableSlots = Array<FunctionDescriptor?>(superVtableEntries.size, { null }) val methods = classDesc.getContributedMethods() // TODO: ensure order is well-defined
val methods = getMethodTableEntries(classDesc) // TODO: ensure order is well-defined
val entriesForNewVtableSlots = methods.toMutableSet()
methods.forEach { method -> val inheritedVtableSlots = superVtableEntries.map { superMethod ->
superVtableEntries.forEachIndexed { i, superMethod -> methods.single { OverridingUtil.overrides(it, superMethod) }
if (OverridingUtil.overrides(method, superMethod)) {
assert (inheritedVtableSlots[i] == null)
inheritedVtableSlots[i] = method
assert (method in entriesForNewVtableSlots)
entriesForNewVtableSlots.remove(method)
}
}
} }
return inheritedVtableSlots.map { it!! } + methods.filter { it in entriesForNewVtableSlots } return inheritedVtableSlots + (methods - inheritedVtableSlots).filter { it.isOverridable }
} }
private fun getMethodTableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> { private fun getMethodTableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> {
assert (classDesc.modality != Modality.ABSTRACT) 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<FunctionDescriptor> {
val contributedDescriptors = unsubstitutedMemberScope.getContributedDescriptors()
// (includes declarations from supers) // (includes declarations from supers)
val functions = contributedDescriptors.filterIsInstance<FunctionDescriptor>() val functions = contributedDescriptors.filterIsInstance<FunctionDescriptor>()
@@ -118,9 +113,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val setters = properties.mapNotNull { it.setter } val setters = properties.mapNotNull { it.setter }
val allMethods = functions + getters + setters val allMethods = functions + getters + setters
return allMethods
// TODO: adding or removing 'open' modifier will break the binary compatibility
return allMethods.filter { it.modality != Modality.FINAL }
} }
private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMOpaqueValue?) { private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMOpaqueValue?) {