Get rid of uneeded parts of RTTI. (#2435)
This commit is contained in:
+12
-36
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
if (classDescriptor.isInterface)
|
||||
result = result or TF_INTERFACE
|
||||
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?) :
|
||||
Struct(runtime.methodTableRecordType, nameSignature, methodEntryPoint)
|
||||
|
||||
private inner class TypeInfo(
|
||||
selfPtr: ConstPointer,
|
||||
name: ConstValue,
|
||||
extendedInfo: ConstPointer,
|
||||
size: Int,
|
||||
superType: ConstValue,
|
||||
objOffsets: ConstValue,
|
||||
@@ -79,12 +79,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
interfacesCount: Int,
|
||||
methods: ConstValue,
|
||||
methodsCount: Int,
|
||||
fields: ConstValue,
|
||||
fieldsCount: Int,
|
||||
packageName: String?,
|
||||
relativeName: String?,
|
||||
flags: Int,
|
||||
extendedInfo: ConstPointer,
|
||||
writableTypeInfo: ConstPointer?) :
|
||||
|
||||
Struct(
|
||||
@@ -92,7 +89,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
selfPtr,
|
||||
|
||||
name,
|
||||
extendedInfo,
|
||||
|
||||
Int32(KonanAbiVersion.CURRENT.version),
|
||||
|
||||
Int32(size),
|
||||
|
||||
superType,
|
||||
@@ -106,16 +106,11 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
methods,
|
||||
Int32(methodsCount),
|
||||
|
||||
fields,
|
||||
Int32(fieldsCount),
|
||||
|
||||
kotlinStringLiteral(packageName),
|
||||
kotlinStringLiteral(relativeName),
|
||||
|
||||
Int32(flags),
|
||||
|
||||
extendedInfo,
|
||||
|
||||
*listOfNotNull(writableTypeInfo).toTypedArray()
|
||||
)
|
||||
|
||||
@@ -180,8 +175,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
|
||||
val name = className.globalHash
|
||||
|
||||
val size = getInstanceSize(bodyType, className)
|
||||
|
||||
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",
|
||||
pointerType(runtime.typeInfoType), interfaces)
|
||||
|
||||
// TODO: reuse offsets obtained for 'fields' below
|
||||
val objOffsets = getStructElements(bodyType).mapIndexedNotNull { index, type ->
|
||||
if (isObjectType(type)) {
|
||||
LLVMOffsetOfElement(llvmTargetData, bodyType, index)
|
||||
@@ -210,16 +202,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
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()) {
|
||||
emptyList()
|
||||
} else {
|
||||
@@ -233,17 +215,15 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
||||
val typeInfo = TypeInfo(
|
||||
classDesc.typeInfoPtr,
|
||||
name,
|
||||
makeExtendedInfo(classDesc),
|
||||
size,
|
||||
superType,
|
||||
objOffsetsPtr, objOffsetsCount,
|
||||
interfacesPtr, interfaces.size,
|
||||
methodsPtr, methods.size,
|
||||
fieldsPtr, if (classDesc.isInterface) -1 else fields.size,
|
||||
reflectionInfo.packageName,
|
||||
reflectionInfo.relativeName,
|
||||
flagsFromClass(classDesc),
|
||||
makeExtendedInfo(classDesc),
|
||||
llvmDeclarations.writableTypeInfoGlobal?.pointer
|
||||
)
|
||||
|
||||
@@ -335,8 +315,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
): ConstPointer {
|
||||
assert(descriptor.isInterface)
|
||||
|
||||
val name = "".globalHash
|
||||
|
||||
val size = 0
|
||||
|
||||
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 })
|
||||
val objOffsetsPtr = NullPointer(int32Type)
|
||||
val objOffsetsCount = 0
|
||||
val fieldsPtr = NullPointer(runtime.fieldTableRecordType)
|
||||
val fieldsCount = 0
|
||||
|
||||
val methods = (methodTableRecords(superClass) + methodImpls.map { (method, impl) ->
|
||||
assert(method.containingDeclaration == descriptor)
|
||||
@@ -377,17 +353,15 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0)
|
||||
val typeInfoWithVtable = Struct(TypeInfo(
|
||||
selfPtr = result,
|
||||
name = name,
|
||||
extendedInfo = NullPointer(runtime.extendedTypeInfoType),
|
||||
size = size,
|
||||
superType = superClass.typeInfoPtr,
|
||||
objOffsets = objOffsetsPtr, objOffsetsCount = objOffsetsCount,
|
||||
interfaces = interfacesPtr, interfacesCount = interfaces.size,
|
||||
methods = methodsPtr, methodsCount = methods.size,
|
||||
fields = fieldsPtr, fieldsCount = fieldsCount,
|
||||
packageName = reflectionInfo.packageName,
|
||||
relativeName = reflectionInfo.relativeName,
|
||||
flags = flagsFromClass(descriptor) or (if (immutable) TF_IMMUTABLE else 0),
|
||||
extendedInfo = NullPointer(runtime.extendedTypeInfoType),
|
||||
writableTypeInfo = writableTypeInfo
|
||||
), 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_ACYCLIC = 2
|
||||
private const val TF_INTERFACE = 4
|
||||
|
||||
-1
@@ -22,7 +22,6 @@ class Runtime(bitcodeFile: String) {
|
||||
val typeInfoType = getStructType("TypeInfo")
|
||||
val extendedTypeInfoType = getStructType("ExtendedTypeInfo")
|
||||
val writableTypeInfoType = getStructTypeOrNull("WritableTypeInfo")
|
||||
val fieldTableRecordType = getStructType("FieldTableRecord")
|
||||
val methodTableRecordType = getStructType("MethodTableRecord")
|
||||
val globalHashType = getStructType("GlobalHash")
|
||||
|
||||
|
||||
@@ -671,7 +671,6 @@ static const TypeInfo* createTypeInfo(
|
||||
|
||||
result->flags_ = 0;
|
||||
|
||||
MakeGlobalHash(nullptr, 0, &result->name_);
|
||||
result->instanceSize_ = superType->instanceSize_;
|
||||
result->superType_ = superType;
|
||||
result->objOffsets_ = superType->objOffsets_;
|
||||
@@ -705,9 +704,6 @@ static const TypeInfo* createTypeInfo(
|
||||
result->openMethods_ = openMethods_;
|
||||
result->openMethodsCount_ = methodTable.size();
|
||||
|
||||
result->fields_ = nullptr;
|
||||
result->fieldsCount_ = 0;
|
||||
|
||||
result->packageName_ = nullptr;
|
||||
result->relativeName_ = nullptr; // TODO: add some info.
|
||||
result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo));
|
||||
|
||||
@@ -24,24 +24,6 @@
|
||||
extern "C" {
|
||||
#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) {
|
||||
int bottom = 0;
|
||||
int top = info->openMethodsCount_ - 1;
|
||||
@@ -62,16 +44,6 @@ void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
|
||||
|
||||
#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) {
|
||||
for (int i = 0; i < info->openMethodsCount_; ++i) {
|
||||
if (info->openMethods_[i].nameSignature_ == nameSignature) {
|
||||
|
||||
@@ -36,12 +36,6 @@ struct MethodTableRecord {
|
||||
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.
|
||||
// Keep in sync with runtimeTypeMap in RTTIGenerator.
|
||||
enum Konan_RuntimeType {
|
||||
@@ -59,7 +53,8 @@ enum Konan_RuntimeType {
|
||||
|
||||
enum Konan_TypeFlags {
|
||||
TF_IMMUTABLE = 1 << 0,
|
||||
TF_ACYCLIC = 1 << 1
|
||||
TF_ACYCLIC = 1 << 1,
|
||||
TF_INTERFACE = 1 << 2
|
||||
};
|
||||
|
||||
enum Konan_MetaFlags {
|
||||
@@ -84,8 +79,10 @@ struct ExtendedTypeInfo {
|
||||
struct TypeInfo {
|
||||
// Reference to self, to allow simple obtaining TypeInfo via meta-object.
|
||||
const TypeInfo* typeInfo_;
|
||||
// Hash of class name.
|
||||
ClassNameHash name_;
|
||||
// Extended RTTI, to retain cross-version debuggability, since ABI version 5 shall always be at the second position.
|
||||
const ExtendedTypeInfo* extendedInfo_;
|
||||
// ABI version.
|
||||
uint32_t abiVersion_;
|
||||
// Negative value marks array class/string, and it is negated element size.
|
||||
int32_t instanceSize_;
|
||||
// Must be pointer to Any for array classes, and null for Any.
|
||||
@@ -100,9 +97,6 @@ struct TypeInfo {
|
||||
// Null for abstract classes and interfaces.
|
||||
const MethodTableRecord* openMethods_;
|
||||
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,
|
||||
// or `null` if the class is local or anonymous.
|
||||
@@ -116,9 +110,6 @@ struct TypeInfo {
|
||||
// Various flags.
|
||||
int32_t flags_;
|
||||
|
||||
// Extended RTTI.
|
||||
const ExtendedTypeInfo* extendedInfo_;
|
||||
|
||||
#if KONAN_TYPE_INFO_HAS_WRITABLE_PART
|
||||
WritableTypeInfo* writableInfo_;
|
||||
#endif
|
||||
@@ -139,16 +130,12 @@ struct TypeInfo {
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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
|
||||
// dereference global memory, while this function does. However, it seems
|
||||
// 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
|
||||
// (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;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -24,7 +24,7 @@ KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) {
|
||||
RuntimeAssert(obj != nullptr, "must not be null");
|
||||
const TypeInfo* obj_type_info = obj->type_info();
|
||||
// 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) {
|
||||
if (obj_type_info->implementedInterfaces_[i] == type_info) {
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user