Get rid of uneeded parts of RTTI. (#2435)

This commit is contained in:
Nikolay Igotti
2018-12-03 12:39:47 +03:00
committed by GitHub
parent 132e12ba3e
commit c6ac807034
6 changed files with 20 additions and 90 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isAnnotationClass import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.konan.KonanAbiVersion
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
internal class RTTIGenerator(override val context: Context) : ContextUtils { internal class RTTIGenerator(override val context: Context) : ContextUtils {
@@ -59,18 +60,17 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
result = result or TF_ACYCLIC result = result or TF_ACYCLIC
} }
} }
if (classDescriptor.isInterface)
result = result or TF_INTERFACE
return result return result
} }
private inner class FieldTableRecord(val nameSignature: LocalHash, fieldOffset: Int) :
Struct(runtime.fieldTableRecordType, nameSignature, Int32(fieldOffset))
inner class MethodTableRecord(val nameSignature: LocalHash, methodEntryPoint: ConstPointer?) : inner class MethodTableRecord(val nameSignature: LocalHash, methodEntryPoint: ConstPointer?) :
Struct(runtime.methodTableRecordType, nameSignature, methodEntryPoint) Struct(runtime.methodTableRecordType, nameSignature, methodEntryPoint)
private inner class TypeInfo( private inner class TypeInfo(
selfPtr: ConstPointer, selfPtr: ConstPointer,
name: ConstValue, extendedInfo: ConstPointer,
size: Int, size: Int,
superType: ConstValue, superType: ConstValue,
objOffsets: ConstValue, objOffsets: ConstValue,
@@ -79,12 +79,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
interfacesCount: Int, interfacesCount: Int,
methods: ConstValue, methods: ConstValue,
methodsCount: Int, methodsCount: Int,
fields: ConstValue,
fieldsCount: Int,
packageName: String?, packageName: String?,
relativeName: String?, relativeName: String?,
flags: Int, flags: Int,
extendedInfo: ConstPointer,
writableTypeInfo: ConstPointer?) : writableTypeInfo: ConstPointer?) :
Struct( Struct(
@@ -92,7 +89,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
selfPtr, selfPtr,
name, extendedInfo,
Int32(KonanAbiVersion.CURRENT.version),
Int32(size), Int32(size),
superType, superType,
@@ -106,16 +106,11 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
methods, methods,
Int32(methodsCount), Int32(methodsCount),
fields,
Int32(fieldsCount),
kotlinStringLiteral(packageName), kotlinStringLiteral(packageName),
kotlinStringLiteral(relativeName), kotlinStringLiteral(relativeName),
Int32(flags), Int32(flags),
extendedInfo,
*listOfNotNull(writableTypeInfo).toTypedArray() *listOfNotNull(writableTypeInfo).toTypedArray()
) )
@@ -180,8 +175,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val bodyType = llvmDeclarations.bodyType val bodyType = llvmDeclarations.bodyType
val name = className.globalHash
val size = getInstanceSize(bodyType, className) val size = getInstanceSize(bodyType, className)
val superTypeOrAny = classDesc.getSuperClassNotAny() ?: context.ir.symbols.any.owner val superTypeOrAny = classDesc.getSuperClassNotAny() ?: context.ir.symbols.any.owner
@@ -192,7 +185,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className", val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className",
pointerType(runtime.typeInfoType), interfaces) pointerType(runtime.typeInfoType), interfaces)
// TODO: reuse offsets obtained for 'fields' below
val objOffsets = getStructElements(bodyType).mapIndexedNotNull { index, type -> val objOffsets = getStructElements(bodyType).mapIndexedNotNull { index, type ->
if (isObjectType(type)) { if (isObjectType(type)) {
LLVMOffsetOfElement(llvmTargetData, bodyType, index) LLVMOffsetOfElement(llvmTargetData, bodyType, index)
@@ -210,16 +202,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
objOffsets.size objOffsets.size
} }
val fields = llvmDeclarations.fields.mapIndexed { index, field ->
// Note: using FQ name because a class may have multiple fields with the same name due to property overriding
val nameSignature = field.fqNameSafe.localHash // FIXME: add signature
val fieldOffset = LLVMOffsetOfElement(llvmTargetData, bodyType, index)
FieldTableRecord(nameSignature, fieldOffset.toInt())
}.sortedBy { it.nameSignature.value }
val fieldsPtr = staticData.placeGlobalConstArray("kfields:$className",
runtime.fieldTableRecordType, fields)
val methods = if (classDesc.isAbstract()) { val methods = if (classDesc.isAbstract()) {
emptyList() emptyList()
} else { } else {
@@ -233,17 +215,15 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
val typeInfo = TypeInfo( val typeInfo = TypeInfo(
classDesc.typeInfoPtr, classDesc.typeInfoPtr,
name, makeExtendedInfo(classDesc),
size, size,
superType, superType,
objOffsetsPtr, objOffsetsCount, objOffsetsPtr, objOffsetsCount,
interfacesPtr, interfaces.size, interfacesPtr, interfaces.size,
methodsPtr, methods.size, methodsPtr, methods.size,
fieldsPtr, if (classDesc.isInterface) -1 else fields.size,
reflectionInfo.packageName, reflectionInfo.packageName,
reflectionInfo.relativeName, reflectionInfo.relativeName,
flagsFromClass(classDesc), flagsFromClass(classDesc),
makeExtendedInfo(classDesc),
llvmDeclarations.writableTypeInfoGlobal?.pointer llvmDeclarations.writableTypeInfoGlobal?.pointer
) )
@@ -335,8 +315,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
): ConstPointer { ): ConstPointer {
assert(descriptor.isInterface) assert(descriptor.isInterface)
val name = "".globalHash
val size = 0 val size = 0
val superClass = context.ir.symbols.any.owner val superClass = context.ir.symbols.any.owner
@@ -349,8 +327,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
assert(superClass.declarations.all { it !is IrProperty && it !is IrField }) assert(superClass.declarations.all { it !is IrProperty && it !is IrField })
val objOffsetsPtr = NullPointer(int32Type) val objOffsetsPtr = NullPointer(int32Type)
val objOffsetsCount = 0 val objOffsetsCount = 0
val fieldsPtr = NullPointer(runtime.fieldTableRecordType)
val fieldsCount = 0
val methods = (methodTableRecords(superClass) + methodImpls.map { (method, impl) -> val methods = (methodTableRecords(superClass) + methodImpls.map { (method, impl) ->
assert(method.containingDeclaration == descriptor) assert(method.containingDeclaration == descriptor)
@@ -377,17 +353,15 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0) val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0)
val typeInfoWithVtable = Struct(TypeInfo( val typeInfoWithVtable = Struct(TypeInfo(
selfPtr = result, selfPtr = result,
name = name, extendedInfo = NullPointer(runtime.extendedTypeInfoType),
size = size, size = size,
superType = superClass.typeInfoPtr, superType = superClass.typeInfoPtr,
objOffsets = objOffsetsPtr, objOffsetsCount = objOffsetsCount, objOffsets = objOffsetsPtr, objOffsetsCount = objOffsetsCount,
interfaces = interfacesPtr, interfacesCount = interfaces.size, interfaces = interfacesPtr, interfacesCount = interfaces.size,
methods = methodsPtr, methodsCount = methods.size, methods = methodsPtr, methodsCount = methods.size,
fields = fieldsPtr, fieldsCount = fieldsCount,
packageName = reflectionInfo.packageName, packageName = reflectionInfo.packageName,
relativeName = reflectionInfo.relativeName, relativeName = reflectionInfo.relativeName,
flags = flagsFromClass(descriptor) or (if (immutable) TF_IMMUTABLE else 0), flags = flagsFromClass(descriptor) or (if (immutable) TF_IMMUTABLE else 0),
extendedInfo = NullPointer(runtime.extendedTypeInfoType),
writableTypeInfo = writableTypeInfo writableTypeInfo = writableTypeInfo
), vtable) ), vtable)
@@ -417,5 +391,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
} }
} }
// Keep in sync with Konan_TypeFlags in TypeInfo.h.
private const val TF_IMMUTABLE = 1 private const val TF_IMMUTABLE = 1
private const val TF_ACYCLIC = 2 private const val TF_ACYCLIC = 2
private const val TF_INTERFACE = 4
@@ -22,7 +22,6 @@ class Runtime(bitcodeFile: String) {
val typeInfoType = getStructType("TypeInfo") val typeInfoType = getStructType("TypeInfo")
val extendedTypeInfoType = getStructType("ExtendedTypeInfo") val extendedTypeInfoType = getStructType("ExtendedTypeInfo")
val writableTypeInfoType = getStructTypeOrNull("WritableTypeInfo") val writableTypeInfoType = getStructTypeOrNull("WritableTypeInfo")
val fieldTableRecordType = getStructType("FieldTableRecord")
val methodTableRecordType = getStructType("MethodTableRecord") val methodTableRecordType = getStructType("MethodTableRecord")
val globalHashType = getStructType("GlobalHash") val globalHashType = getStructType("GlobalHash")
-4
View File
@@ -671,7 +671,6 @@ static const TypeInfo* createTypeInfo(
result->flags_ = 0; result->flags_ = 0;
MakeGlobalHash(nullptr, 0, &result->name_);
result->instanceSize_ = superType->instanceSize_; result->instanceSize_ = superType->instanceSize_;
result->superType_ = superType; result->superType_ = superType;
result->objOffsets_ = superType->objOffsets_; result->objOffsets_ = superType->objOffsets_;
@@ -705,9 +704,6 @@ static const TypeInfo* createTypeInfo(
result->openMethods_ = openMethods_; result->openMethods_ = openMethods_;
result->openMethodsCount_ = methodTable.size(); result->openMethodsCount_ = methodTable.size();
result->fields_ = nullptr;
result->fieldsCount_ = 0;
result->packageName_ = nullptr; result->packageName_ = nullptr;
result->relativeName_ = nullptr; // TODO: add some info. result->relativeName_ = nullptr; // TODO: add some info.
result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo)); result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo));
-28
View File
@@ -24,24 +24,6 @@
extern "C" { extern "C" {
#if USE_BINARY_SEARCH #if USE_BINARY_SEARCH
int LookupFieldOffset(const TypeInfo* info, FieldNameHash nameSignature) {
int bottom = 0;
int top = info->fieldsCount_ - 1;
while (bottom <= top) {
int middle = (bottom + top) / 2;
if (info->fields_[middle].nameSignature_ < nameSignature)
bottom = middle + 1;
else if (info->fields_[middle].nameSignature_ == nameSignature)
return info->fields_[middle].fieldOffset_;
else
top = middle - 1;
}
RuntimeAssert(false, "Unknown field");
return -1;
}
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) { void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
int bottom = 0; int bottom = 0;
int top = info->openMethodsCount_ - 1; int top = info->openMethodsCount_ - 1;
@@ -62,16 +44,6 @@ void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
#else #else
int LookupFieldOffset(const TypeInfo* info, FieldNameHash nameSignature) {
for (int i = 0; i < info->fieldsCount_; ++i) {
if (info->fields_[i].nameSignature_ == nameSignature) {
return info->fields_[i].fieldOffset_;
}
}
RuntimeAssert(false, "Unknown field");
return -1;
}
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) { void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
for (int i = 0; i < info->openMethodsCount_; ++i) { for (int i = 0; i < info->openMethodsCount_; ++i) {
if (info->openMethods_[i].nameSignature_ == nameSignature) { if (info->openMethods_[i].nameSignature_ == nameSignature) {
+7 -20
View File
@@ -36,12 +36,6 @@ struct MethodTableRecord {
void* methodEntryPoint_; void* methodEntryPoint_;
}; };
// An element of sorted by hash in-place array representing field offsets.
struct FieldTableRecord {
FieldNameHash nameSignature_;
int fieldOffset_;
};
// Type for runtime representation of Konan object. // Type for runtime representation of Konan object.
// Keep in sync with runtimeTypeMap in RTTIGenerator. // Keep in sync with runtimeTypeMap in RTTIGenerator.
enum Konan_RuntimeType { enum Konan_RuntimeType {
@@ -59,7 +53,8 @@ enum Konan_RuntimeType {
enum Konan_TypeFlags { enum Konan_TypeFlags {
TF_IMMUTABLE = 1 << 0, TF_IMMUTABLE = 1 << 0,
TF_ACYCLIC = 1 << 1 TF_ACYCLIC = 1 << 1,
TF_INTERFACE = 1 << 2
}; };
enum Konan_MetaFlags { enum Konan_MetaFlags {
@@ -84,8 +79,10 @@ struct ExtendedTypeInfo {
struct TypeInfo { struct TypeInfo {
// Reference to self, to allow simple obtaining TypeInfo via meta-object. // Reference to self, to allow simple obtaining TypeInfo via meta-object.
const TypeInfo* typeInfo_; const TypeInfo* typeInfo_;
// Hash of class name. // Extended RTTI, to retain cross-version debuggability, since ABI version 5 shall always be at the second position.
ClassNameHash name_; const ExtendedTypeInfo* extendedInfo_;
// ABI version.
uint32_t abiVersion_;
// Negative value marks array class/string, and it is negated element size. // Negative value marks array class/string, and it is negated element size.
int32_t instanceSize_; int32_t instanceSize_;
// Must be pointer to Any for array classes, and null for Any. // Must be pointer to Any for array classes, and null for Any.
@@ -100,9 +97,6 @@ struct TypeInfo {
// Null for abstract classes and interfaces. // Null for abstract classes and interfaces.
const MethodTableRecord* openMethods_; const MethodTableRecord* openMethods_;
uint32_t openMethodsCount_; uint32_t openMethodsCount_;
const FieldTableRecord* fields_;
// Is negative to mark an interface.
int32_t fieldsCount_;
// String for the fully qualified dot-separated name of the package containing class, // String for the fully qualified dot-separated name of the package containing class,
// or `null` if the class is local or anonymous. // or `null` if the class is local or anonymous.
@@ -116,9 +110,6 @@ struct TypeInfo {
// Various flags. // Various flags.
int32_t flags_; int32_t flags_;
// Extended RTTI.
const ExtendedTypeInfo* extendedInfo_;
#if KONAN_TYPE_INFO_HAS_WRITABLE_PART #if KONAN_TYPE_INFO_HAS_WRITABLE_PART
WritableTypeInfo* writableInfo_; WritableTypeInfo* writableInfo_;
#endif #endif
@@ -139,16 +130,12 @@ struct TypeInfo {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// Find offset of given hash in table. // Find open method by its hash. Other methods are resolved in compile-time.
// Note, that we use attribute const, which assumes function doesn't // Note, that we use attribute const, which assumes function doesn't
// dereference global memory, while this function does. However, it seems // dereference global memory, while this function does. However, it seems
// to be safe, as actual result of this computation depends only on 'type_info' // to be safe, as actual result of this computation depends only on 'type_info'
// and 'hash' numeric values and doesn't really depends on global memory state // and 'hash' numeric values and doesn't really depends on global memory state
// (as TypeInfo is compile time constant and type info pointers are stable). // (as TypeInfo is compile time constant and type info pointers are stable).
int LookupFieldOffset(const TypeInfo* type_info, FieldNameHash hash) RUNTIME_CONST;
// Find open method by its hash. Other methods are resolved in compile-time.
// See comment in LookupFieldOffset().
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) RUNTIME_CONST; void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) RUNTIME_CONST;
#ifdef __cplusplus #ifdef __cplusplus
+1 -1
View File
@@ -24,7 +24,7 @@ KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) {
RuntimeAssert(obj != nullptr, "must not be null"); RuntimeAssert(obj != nullptr, "must not be null");
const TypeInfo* obj_type_info = obj->type_info(); const TypeInfo* obj_type_info = obj->type_info();
// If it is an interface - check in list of implemented interfaces. // If it is an interface - check in list of implemented interfaces.
if (type_info->fieldsCount_ < 0) { if ((type_info->flags_ & TF_INTERFACE) != 0) {
for (int i = 0; i < obj_type_info->implementedInterfacesCount_; ++i) { for (int i = 0; i < obj_type_info->implementedInterfacesCount_; ++i) {
if (obj_type_info->implementedInterfaces_[i] == type_info) { if (obj_type_info->implementedInterfaces_[i] == type_info) {
return 1; return 1;