[K/N][codegen] Refactored interface calls

Removed old impl for debug builds
Fixes https://youtrack.jetbrains.com/issue/KT-44547 as a side effect
This commit is contained in:
Igor Chevdar
2021-05-02 11:28:34 +05:00
parent 3df45f9651
commit 3b3318ab06
15 changed files with 139 additions and 272 deletions
@@ -52,7 +52,6 @@ struct ObjCToKotlinMethodAdapter {
struct KotlinToObjCMethodAdapter {
const char* selector;
MethodNameHash nameSignature;
ClassId interfaceId;
int itableSize;
int itableIndex;
@@ -66,9 +65,6 @@ struct ObjCTypeAdapter {
const void * const * kotlinVtable;
int kotlinVtableSize;
const MethodTableRecord* kotlinMethodTable;
int kotlinMethodTableSize;
const InterfaceTableRecord* kotlinItable;
int kotlinItableSize;
@@ -652,7 +648,6 @@ static const TypeInfo* createTypeInfo(
const TypeInfo* superType,
const KStdVector<const TypeInfo*>& superInterfaces,
const KStdVector<VTableElement>& vtable,
const KStdVector<MethodTableRecord>& methodTable,
const KStdOrderedMap<ClassId, KStdVector<VTableElement>>& interfaceVTables,
const InterfaceTableRecord* superItable,
int superItableSize,
@@ -707,12 +702,6 @@ static const TypeInfo* createTypeInfo(
}
}
MethodTableRecord* openMethods_ = konanAllocArray<MethodTableRecord>(methodTable.size());
for (size_t i = 0; i < methodTable.size(); ++i) openMethods_[i] = methodTable[i];
result->openMethods_ = openMethods_;
result->openMethodsCount_ = methodTable.size();
result->packageName_ = nullptr;
result->relativeName_ = nullptr; // TODO: add some info.
result->writableInfo_ = (WritableTypeInfo*)konanAllocMemory(sizeof(WritableTypeInfo));
@@ -777,22 +766,6 @@ static int getVtableSize(const TypeInfo* typeInfo) {
return -1;
}
static void insertOrReplace(KStdVector<MethodTableRecord>& methodTable, MethodNameHash nameSignature, void* entryPoint) {
MethodTableRecord record = {nameSignature, entryPoint};
for (int i = methodTable.size() - 1; i >= 0; --i) {
if (methodTable[i].nameSignature_ == nameSignature) {
methodTable[i].methodEntryPoint_ = entryPoint;
return;
} else if (methodTable[i].nameSignature_ < nameSignature) {
methodTable.insert(methodTable.begin() + (i + 1), record);
return;
}
}
methodTable.insert(methodTable.begin(), record);
}
static void throwIfCantBeOverridden(Class clazz, const KotlinToObjCMethodAdapter* adapter) {
if (adapter->kotlinImpl == nullptr) {
NSString* reason;
@@ -816,9 +789,6 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
const void * const * superVtable = nullptr;
int superVtableSize = getVtableSize(superType);
const MethodTableRecord* superMethodTable = nullptr;
int superMethodTableSize = 0;
InterfaceTableRecord const* superITable = nullptr;
int superITableSize = 0;
@@ -828,27 +798,17 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
// And if it is abstract, then vtable and method table are not available from TypeInfo,
// but present in type adapter instead:
superVtable = superTypeAdapter->kotlinVtable;
superMethodTable = superTypeAdapter->kotlinMethodTable;
superMethodTableSize = superTypeAdapter->kotlinMethodTableSize;
superITable = superTypeAdapter->kotlinItable;
superITableSize = superTypeAdapter->kotlinItableSize;
}
if (superVtable == nullptr) superVtable = superType->vtable();
if (superMethodTable == nullptr) {
superMethodTable = superType->openMethods_;
superMethodTableSize = superType->openMethodsCount_;
}
KStdVector<const void*> vtable(
superVtable,
superVtable + superVtableSize
);
KStdVector<MethodTableRecord> methodTable(
superMethodTable, superMethodTable + superMethodTableSize
);
if (superITable == nullptr) {
superITable = superType->interfaceTable_;
superITableSize = superType->interfaceTableSize_;
@@ -915,7 +875,6 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
throwIfCantBeOverridden(clazz, adapter);
itableEqualsSuper = false;
insertOrReplace(methodTable, adapter->nameSignature, const_cast<void*>(adapter->kotlinImpl));
if (adapter->vtableIndex != -1) vtable[adapter->vtableIndex] = adapter->kotlinImpl;
if (adapter->itableIndex != -1 && superITable != nullptr)
@@ -940,7 +899,6 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
const KotlinToObjCMethodAdapter* adapter = &typeAdapter->reverseAdapters[i];
throwIfCantBeOverridden(clazz, adapter);
insertOrReplace(methodTable, adapter->nameSignature, const_cast<void*>(adapter->kotlinImpl));
RuntimeAssert(adapter->vtableIndex == -1, "");
if (adapter->itableIndex != -1 && superITable != nullptr) {
@@ -954,9 +912,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
// TODO: consider forbidding the class being abstract.
const TypeInfo* result = createTypeInfo(superType, addedInterfaces, vtable, methodTable,
interfaceVTables, superITable, superITableSize, itableEqualsSuper,
fieldsInfo);
const TypeInfo* result = createTypeInfo(superType, addedInterfaces, vtable, interfaceVTables,
superITable, superITableSize, itableEqualsSuper, fieldsInfo);
// TODO: it will probably never be requested, since such a class can't be instantiated in Kotlin.
result->writableInfo_->objCExport.objCClass = clazz;
@@ -17,44 +17,7 @@
#include "KAssert.h"
#include "TypeInfo.h"
// If one shall use binary search when looking up methods and fields.
// TODO: maybe select strategy basing on number of elements.
#define USE_BINARY_SEARCH 1
extern "C" {
#if USE_BINARY_SEARCH
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
int bottom = 0;
int top = info->openMethodsCount_ - 1;
while (bottom <= top) {
int middle = (bottom + top) / 2;
if (info->openMethods_[middle].nameSignature_ < nameSignature)
bottom = middle + 1;
else if (info->openMethods_[middle].nameSignature_ == nameSignature)
return info->openMethods_[middle].methodEntryPoint_;
else
top = middle - 1;
}
RuntimeAssert(false, "Unknown open method");
return nullptr;
}
#else
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) {
for (int i = 0; i < info->openMethodsCount_; ++i) {
if (info->openMethods_[i].nameSignature_ == nameSignature) {
return info->openMethods_[i].methodEntryPoint_;
}
}
RuntimeAssert(false, "Unknown open method");
return nullptr;
}
#endif
// Seeks for the specified id. In case of failure returns a valid pointer to some record, never returns nullptr.
// It is the caller's responsibility to check if the search has succeeded or not.
@@ -29,17 +29,6 @@ struct WritableTypeInfo;
struct ObjHeader;
struct AssociatedObjectTableRecord;
// Hash of open method name. Must be unique per class/scope (CityHash64 is being used).
typedef int64_t MethodNameHash;
// An element of sorted by hash in-place array representing methods.
// For systems where introspection is not needed - only open methods are in
// this table.
struct MethodTableRecord {
MethodNameHash nameSignature_;
void* methodEntryPoint_;
};
// Type for runtime representation of Konan object.
// Keep in sync with runtimeTypeMap in RTTIGenerator.
enum Konan_RuntimeType {
@@ -123,9 +112,6 @@ struct TypeInfo {
int32_t objOffsetsCount_;
const TypeInfo* const* implementedInterfaces_;
int32_t implementedInterfacesCount_;
// Null for abstract classes and interfaces.
const MethodTableRecord* openMethods_;
uint32_t openMethodsCount_;
int32_t interfaceTableSize_;
InterfaceTableRecord const* interfaceTable_;
@@ -181,14 +167,6 @@ struct TypeInfo {
#ifdef __cplusplus
extern "C" {
#endif
// 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).
void* LookupOpenMethod(const TypeInfo* info, MethodNameHash nameSignature) RUNTIME_CONST;
InterfaceTableRecord const* LookupInterfaceTableRecord(InterfaceTableRecord const* interfaceTable,
int interfaceTableSize, ClassId interfaceId) RUNTIME_CONST;