backend.native, runtime: add vtable to TypeInfo

This commit is contained in:
Svyatoslav Scherbina
2016-10-04 13:55:03 +03:00
parent 473816ea81
commit 3324527984
3 changed files with 39 additions and 3 deletions
@@ -55,6 +55,7 @@ internal fun compileTimeValue(value: LLVMOpaqueValue?) = object : CompileTimeVal
override fun getLlvmValue() = value
}
internal val int8Type = LLVMInt8Type()
internal val int32Type = LLVMInt32Type()
internal fun pointerType(pointeeType: LLVMOpaqueType?) = LLVMPointerType(pointeeType, 0)
@@ -6,10 +6,9 @@ import llvm.*
import org.jetbrains.kotlin.backend.native.implementation
import org.jetbrains.kotlin.backend.native.implementedInterfaces
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
@@ -32,6 +31,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val objOffsetsCount: Int,
val interfaces: CompileTimeValue,
val interfacesCount: Int,
val vtable: CompileTimeValue,
val methods: CompileTimeValue,
val methodsCount: Int,
val fields: CompileTimeValue,
@@ -50,6 +50,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
interfaces,
Int32(interfacesCount),
vtable,
methods,
Int32(methodsCount),
@@ -71,6 +73,33 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
return classType
}
// TODO: optimize
private fun getVtableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> {
val superVtableEntries = if (KotlinBuiltIns.isAny(classDesc)) {
emptyList()
} else {
getVtableEntries(classDesc.getSuperClassOrAny())
}
val inheritedVtableSlots = Array<FunctionDescriptor?>(superVtableEntries.size, { null })
val methods = getMethodTableEntries(classDesc) // TODO: ensure order is well-defined
val entriesForNewVtableSlots = methods.toMutableSet()
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)
}
}
}
return inheritedVtableSlots.map { it!! } + methods.filter { it in entriesForNewVtableSlots }
}
private fun getMethodTableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> {
val contributedDescriptors = classDesc.unsubstitutedMemberScope.getContributedDescriptors()
// (includes declarations from supers)
@@ -120,6 +149,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val fieldsPtr = addGlobalConstArray("kfields:$className", runtime.fieldTableRecordType, fields)
// TODO: compile-time resolution limits binary compatibility
val vtable = getVtableEntries(classDesc).map { it.implementation.entryPointAddress }
val vtablePtr = addGlobalConstArray("kvtable:$className", pointerType(int8Type), vtable)
val methods = getMethodTableEntries(classDesc).map {
val nameSignature = it.name.nameHash // FIXME: add signature
// TODO: compile-time resolution limits binary compatibility
@@ -133,6 +166,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
superType,
objOffsetsPtr, objOffsets.size,
interfacesPtr, interfaces.size,
vtablePtr,
methodsPtr, methods.size,
fieldsPtr, fields.size)
+1
View File
@@ -29,6 +29,7 @@ struct TypeInfo {
int objOffsetsCount;
TypeInfo* const* implementedInterfaces;
int implementedInterfacesCount;
void* const* vtable; // TODO: place vtable at the end of TypeInfo to eliminate the indirection
const MethodTableRecord* methods;
int methodsCount;
const FieldTableRecord* fields;