未验证 提交 c6ac8070 编写于 作者: N Nikolay Igotti 提交者: GitHub

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

上级 132e12ba
......@@ -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
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册