backend, runtime: improve support for abstract methods (#62)

backend, runtime: improve support for abstract methods

Do not generate vtable and openMethods for abstract classes and interfaces
This commit is contained in:
SvyatoslavScherbina
2016-11-15 17:30:49 +07:00
committed by GitHub
parent c5cfa0ac4f
commit 755194486b
3 changed files with 24 additions and 22 deletions
@@ -15,20 +15,14 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
var currentFunction:FunctionDescriptor? = null
fun function(declaration: IrFunction) {
if (declaration.descriptor.isExternal) {
if (declaration.body == null) {
// Abstract and external methods.
return
}
if (currentFunction == declaration.descriptor) return
val fn = prolog(declaration)
// TODO: functions without Kotlin body must not have a bitcode body,
// which is required to workaround link errors
if (declaration.body == null) {
trap()
return
}
var indexOffset = 0
if (declaration.descriptor is ClassConstructorDescriptor || declaration.descriptor.dispatchReceiverParameter != null) {
val name = "this"
@@ -78,9 +78,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
// TODO: optimize
private fun getVtableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> {
if (classDesc.isInterface) {
return emptyList()
}
assert (!classDesc.isInterface)
val superVtableEntries = if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDesc)) {
emptyList()
@@ -108,9 +106,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
}
private fun getMethodTableEntries(classDesc: ClassDescriptor): List<FunctionDescriptor> {
if (classDesc.isInterface) {
return emptyList()
}
assert (classDesc.modality != Modality.ABSTRACT)
val contributedDescriptors = classDesc.unsubstitutedMemberScope.getContributedDescriptors()
// (includes declarations from supers)
@@ -197,16 +193,26 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val fieldsPtr = staticData.placeGlobalConstArray("kfields:$className",
runtime.fieldTableRecordType, fields)
// TODO: compile-time resolution limits binary compatibility
val vtable = getVtableEntries(classDesc).map { it.implementation.entryPointAddress }
val vtablePtr = staticData.placeGlobalConstArray("kvtable:$className", pointerType(int8Type), vtable)
val vtable: List<ConstValue>
val methods: List<ConstValue>
val methods = getMethodTableEntries(classDesc).map {
val nameSignature = it.functionName.localHash
if (classDesc.modality != Modality.ABSTRACT) {
// TODO: compile-time resolution limits binary compatibility
val methodEntryPoint = it.implementation.entryPointAddress
MethodTableRecord(nameSignature, methodEntryPoint)
}.sortedBy { it.nameSignature.value }
vtable = getVtableEntries(classDesc).map { it.implementation.entryPointAddress }
methods = getMethodTableEntries(classDesc).map {
val nameSignature = it.functionName.localHash
// TODO: compile-time resolution limits binary compatibility
val methodEntryPoint = it.implementation.entryPointAddress
MethodTableRecord(nameSignature, methodEntryPoint)
}.sortedBy { it.nameSignature.value }
} else {
vtable = emptyList()
methods = emptyList()
}
val vtablePtr = staticData.placeGlobalConstArray("kvtable:$className", pointerType(int8Type), vtable)
val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className",
runtime.methodTableRecordType, methods)
+2
View File
@@ -32,8 +32,10 @@ struct TypeInfo {
int32_t objOffsetsCount_;
const TypeInfo* const* implementedInterfaces_;
int32_t implementedInterfacesCount_;
// Null for abstract classes and interfaces.
// TODO: place vtable at the end of TypeInfo to eliminate the indirection.
void* const* vtable_;
// Null for abstract classes and interfaces.
const MethodTableRecord* openMethods_;
uint32_t openMethodsCount_;
const FieldTableRecord* fields_;