From 3324527984006ad507644637f86100fae9af2f8b Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Tue, 4 Oct 2016 13:55:03 +0300 Subject: [PATCH] backend.native, runtime: add vtable to TypeInfo --- .../kotlin/backend/native/llvm/LlvmUtils.kt | 1 + .../backend/native/llvm/RTTIGenerator.kt | 40 +++++++++++++++++-- runtime/src/main/cpp/TypeInfo.h | 1 + 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/LlvmUtils.kt index f3ab701e56b..f79a90b5681 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/LlvmUtils.kt @@ -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) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/RTTIGenerator.kt index 2d56e0346cb..a7ff4e1ee29 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/RTTIGenerator.kt @@ -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 { + val superVtableEntries = if (KotlinBuiltIns.isAny(classDesc)) { + emptyList() + } else { + getVtableEntries(classDesc.getSuperClassOrAny()) + } + + val inheritedVtableSlots = Array(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 { 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) diff --git a/runtime/src/main/cpp/TypeInfo.h b/runtime/src/main/cpp/TypeInfo.h index 8df39fa4705..feea599a316 100644 --- a/runtime/src/main/cpp/TypeInfo.h +++ b/runtime/src/main/cpp/TypeInfo.h @@ -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;