Abstract class objc fix (#3517)
Fixed itable for objc inheritors of abstract classes
This commit is contained in:
+18
-17
@@ -84,7 +84,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
methods: ConstValue,
|
methods: ConstValue,
|
||||||
methodsCount: Int,
|
methodsCount: Int,
|
||||||
interfaceTableSize: Int,
|
interfaceTableSize: Int,
|
||||||
interfaceTable: ConstPointer?,
|
interfaceTable: ConstValue,
|
||||||
packageName: String?,
|
packageName: String?,
|
||||||
relativeName: String?,
|
relativeName: String?,
|
||||||
flags: Int,
|
flags: Int,
|
||||||
@@ -220,7 +220,15 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className",
|
val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className",
|
||||||
runtime.methodTableRecordType, methods)
|
runtime.methodTableRecordType, methods)
|
||||||
|
|
||||||
val (interfaceTable, interfaceTableSize) = interfaceTable(irClass)
|
val needInterfaceTable = context.ghaEnabled() && !irClass.isInterface
|
||||||
|
&& !irClass.isAbstract() && !irClass.isObjCClass()
|
||||||
|
val (interfaceTable, interfaceTableSize) = if (needInterfaceTable) {
|
||||||
|
interfaceTableRecords(irClass)
|
||||||
|
} else {
|
||||||
|
Pair(emptyList(), -1)
|
||||||
|
}
|
||||||
|
val interfaceTablePtr = staticData.placeGlobalConstArray("kifacetable:$className",
|
||||||
|
runtime.interfaceTableRecordType, interfaceTable)
|
||||||
|
|
||||||
val reflectionInfo = getReflectionInfo(irClass)
|
val reflectionInfo = getReflectionInfo(irClass)
|
||||||
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
||||||
@@ -236,7 +244,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
objOffsetsPtr, objOffsetsCount,
|
objOffsetsPtr, objOffsetsCount,
|
||||||
interfacesPtr, interfaces.size,
|
interfacesPtr, interfaces.size,
|
||||||
methodsPtr, methods.size,
|
methodsPtr, methods.size,
|
||||||
interfaceTableSize, interfaceTable,
|
interfaceTableSize, interfaceTablePtr,
|
||||||
reflectionInfo.packageName,
|
reflectionInfo.packageName,
|
||||||
reflectionInfo.relativeName,
|
reflectionInfo.relativeName,
|
||||||
flagsFromClass(irClass),
|
flagsFromClass(irClass),
|
||||||
@@ -301,10 +309,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
}.sortedBy { it.nameSignature.value }
|
}.sortedBy { it.nameSignature.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun interfaceTable(irClass: IrClass): Pair<ConstPointer?, Int> {
|
fun interfaceTableRecords(irClass: IrClass): Pair<List<InterfaceTableRecord>, Int> {
|
||||||
val needInterfaceTable = context.ghaEnabled() && !irClass.isInterface
|
|
||||||
&& !irClass.isAbstract() && !irClass.isObjCClass()
|
|
||||||
if (!needInterfaceTable) return Pair(null, 0)
|
|
||||||
// The details are in ClassLayoutBuilder.
|
// The details are in ClassLayoutBuilder.
|
||||||
val interfaceLayouts = irClass.implementedInterfaces.map { context.getLayoutBuilder(it) }
|
val interfaceLayouts = irClass.implementedInterfaces.map { context.getLayoutBuilder(it) }
|
||||||
val interfaceColors = interfaceLayouts.map { it.hierarchyInfo.interfaceColor }
|
val interfaceColors = interfaceLayouts.map { it.hierarchyInfo.interfaceColor }
|
||||||
@@ -366,11 +371,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return Pair(
|
return Pair(interfaceTableEntries, if (conservative) -size else (size - 1))
|
||||||
staticData.placeGlobalConstArray("kifacetable:$className",
|
|
||||||
runtime.interfaceTableRecordType, interfaceTableEntries),
|
|
||||||
if (conservative) -size else (size - 1)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapRuntimeType(type: LLVMTypeRef): Int =
|
private fun mapRuntimeType(type: LLVMTypeRef): Int =
|
||||||
@@ -489,19 +490,19 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
else
|
else
|
||||||
ClassGlobalHierarchyInfo(-1, -1, 0, 0)
|
ClassGlobalHierarchyInfo(-1, -1, 0, 0)
|
||||||
|
|
||||||
val interfaceTable = if (!context.ghaEnabled()) null else {
|
val interfaceTable = if (!context.ghaEnabled()) emptyList() else {
|
||||||
val layoutBuilder = context.getLayoutBuilder(irClass)
|
val layoutBuilder = context.getLayoutBuilder(irClass)
|
||||||
val vtableEntries = layoutBuilder.interfaceTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) }
|
val vtableEntries = layoutBuilder.interfaceTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) }
|
||||||
val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries)
|
val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries)
|
||||||
staticData.placeGlobalConstArray("",
|
listOf(
|
||||||
runtime.interfaceTableRecordType, listOf(
|
|
||||||
InterfaceTableRecord(
|
InterfaceTableRecord(
|
||||||
Int32(layoutBuilder.hierarchyInfo.interfaceId),
|
Int32(layoutBuilder.hierarchyInfo.interfaceId),
|
||||||
Int32(layoutBuilder.interfaceTableEntries.size),
|
Int32(layoutBuilder.interfaceTableEntries.size),
|
||||||
interfaceVTable.pointer.getElementPtr(0)
|
interfaceVTable.pointer.getElementPtr(0)
|
||||||
)
|
)
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
val interfaceTablePtr = staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, interfaceTable)
|
||||||
|
|
||||||
val typeInfoWithVtable = Struct(TypeInfo(
|
val typeInfoWithVtable = Struct(TypeInfo(
|
||||||
selfPtr = result,
|
selfPtr = result,
|
||||||
@@ -512,7 +513,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
interfaces = interfacesPtr, interfacesCount = interfaces.size,
|
interfaces = interfacesPtr, interfacesCount = interfaces.size,
|
||||||
methods = methodsPtr, methodsCount = methods.size,
|
methods = methodsPtr, methodsCount = methods.size,
|
||||||
// 0 is a perfectly valid itable size (since 0 is in form of (2^k - 1).
|
// 0 is a perfectly valid itable size (since 0 is in form of (2^k - 1).
|
||||||
interfaceTableSize = 0, interfaceTable = interfaceTable,
|
interfaceTableSize = 0, interfaceTable = interfaceTablePtr,
|
||||||
packageName = reflectionInfo.packageName,
|
packageName = reflectionInfo.packageName,
|
||||||
relativeName = reflectionInfo.relativeName,
|
relativeName = reflectionInfo.relativeName,
|
||||||
flags = flagsFromClass(irClass) or (if (immutable) TF_IMMUTABLE else 0),
|
flags = flagsFromClass(irClass) or (if (immutable) TF_IMMUTABLE else 0),
|
||||||
|
|||||||
+9
-3
@@ -380,6 +380,7 @@ internal class ObjCExportCodeGenerator(
|
|||||||
vtable: ConstPointer?,
|
vtable: ConstPointer?,
|
||||||
vtableSize: Int,
|
vtableSize: Int,
|
||||||
methodTable: List<RTTIGenerator.MethodTableRecord>,
|
methodTable: List<RTTIGenerator.MethodTableRecord>,
|
||||||
|
itable: List<RTTIGenerator.InterfaceTableRecord>,
|
||||||
itableSize: Int,
|
itableSize: Int,
|
||||||
val objCName: String,
|
val objCName: String,
|
||||||
directAdapters: List<ObjCToKotlinMethodAdapter>,
|
directAdapters: List<ObjCToKotlinMethodAdapter>,
|
||||||
@@ -396,6 +397,7 @@ internal class ObjCExportCodeGenerator(
|
|||||||
staticData.placeGlobalConstArray("", runtime.methodTableRecordType, methodTable),
|
staticData.placeGlobalConstArray("", runtime.methodTableRecordType, methodTable),
|
||||||
Int32(methodTable.size),
|
Int32(methodTable.size),
|
||||||
|
|
||||||
|
staticData.placeGlobalConstArray("", runtime.interfaceTableRecordType, itable),
|
||||||
Int32(itableSize),
|
Int32(itableSize),
|
||||||
|
|
||||||
staticData.cStringLiteral(objCName),
|
staticData.cStringLiteral(objCName),
|
||||||
@@ -1043,6 +1045,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapterForFileClass(
|
|||||||
vtable = null,
|
vtable = null,
|
||||||
vtableSize = -1,
|
vtableSize = -1,
|
||||||
methodTable = emptyList(),
|
methodTable = emptyList(),
|
||||||
|
itable = emptyList(),
|
||||||
itableSize = -1,
|
itableSize = -1,
|
||||||
objCName = name,
|
objCName = name,
|
||||||
directAdapters = emptyList(),
|
directAdapters = emptyList(),
|
||||||
@@ -1117,9 +1120,11 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val itableSize = if (irClass.isInterface)
|
val (itable, itableSize) = when {
|
||||||
context.getLayoutBuilder(irClass).interfaceTableEntries.size
|
irClass.isInterface -> Pair(emptyList(), context.getLayoutBuilder(irClass).interfaceTableEntries.size)
|
||||||
else -1
|
irClass.isAbstract() && context.ghaEnabled() -> rttiGenerator.interfaceTableRecords(irClass)
|
||||||
|
else -> Pair(emptyList(), -1)
|
||||||
|
}
|
||||||
|
|
||||||
when (irClass.kind) {
|
when (irClass.kind) {
|
||||||
ClassKind.OBJECT -> {
|
ClassKind.OBJECT -> {
|
||||||
@@ -1140,6 +1145,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
vtable,
|
vtable,
|
||||||
vtableSize,
|
vtableSize,
|
||||||
methodTable,
|
methodTable,
|
||||||
|
itable,
|
||||||
itableSize,
|
itableSize,
|
||||||
objCName,
|
objCName,
|
||||||
adapters,
|
adapters,
|
||||||
|
|||||||
@@ -981,6 +981,39 @@ __attribute__((swift_name("InterfaceForTypeCheck")))
|
|||||||
@required
|
@required
|
||||||
@end;
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("IAbstractInterface")))
|
||||||
|
@protocol ValuesIAbstractInterface
|
||||||
|
@required
|
||||||
|
- (int32_t)foo __attribute__((swift_name("foo()")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("IAbstractInterface2")))
|
||||||
|
@protocol ValuesIAbstractInterface2
|
||||||
|
@required
|
||||||
|
- (int32_t)foo __attribute__((swift_name("foo()")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("AbstractInterfaceBase")))
|
||||||
|
@interface ValuesAbstractInterfaceBase : ValuesBase <ValuesIAbstractInterface>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
- (int32_t)foo __attribute__((swift_name("foo()")));
|
||||||
|
- (int32_t)bar __attribute__((swift_name("bar()")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("AbstractInterfaceBase2")))
|
||||||
|
@interface ValuesAbstractInterfaceBase2 : ValuesBase <ValuesIAbstractInterface2>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
@end;
|
||||||
|
|
||||||
|
__attribute__((swift_name("AbstractInterfaceBase3")))
|
||||||
|
@interface ValuesAbstractInterfaceBase3 : ValuesBase <ValuesIAbstractInterface>
|
||||||
|
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||||
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||||
|
- (int32_t)foo __attribute__((swift_name("foo()")));
|
||||||
|
@end;
|
||||||
|
|
||||||
@interface ValuesEnumeration (ValuesKt)
|
@interface ValuesEnumeration (ValuesKt)
|
||||||
- (ValuesEnumeration *)getAnswer __attribute__((swift_name("getAnswer()")));
|
- (ValuesEnumeration *)getAnswer __attribute__((swift_name("getAnswer()")));
|
||||||
@end;
|
@end;
|
||||||
@@ -1064,6 +1097,8 @@ __attribute__((swift_name("ValuesKt")))
|
|||||||
+ (void)gc __attribute__((swift_name("gc()")));
|
+ (void)gc __attribute__((swift_name("gc()")));
|
||||||
+ (BOOL)testClassTypeCheckX:(id)x __attribute__((swift_name("testClassTypeCheck(x:)")));
|
+ (BOOL)testClassTypeCheckX:(id)x __attribute__((swift_name("testClassTypeCheck(x:)")));
|
||||||
+ (BOOL)testInterfaceTypeCheckX:(id)x __attribute__((swift_name("testInterfaceTypeCheck(x:)")));
|
+ (BOOL)testInterfaceTypeCheckX:(id)x __attribute__((swift_name("testInterfaceTypeCheck(x:)")));
|
||||||
|
+ (int32_t)testAbstractInterfaceCallX:(id<ValuesIAbstractInterface>)x __attribute__((swift_name("testAbstractInterfaceCall(x:)")));
|
||||||
|
+ (int32_t)testAbstractInterfaceCall2X:(id<ValuesIAbstractInterface2>)x __attribute__((swift_name("testAbstractInterfaceCall2(x:)")));
|
||||||
@property (class, readonly) double dbl __attribute__((swift_name("dbl")));
|
@property (class, readonly) double dbl __attribute__((swift_name("dbl")));
|
||||||
@property (class, readonly) float flt __attribute__((swift_name("flt")));
|
@property (class, readonly) float flt __attribute__((swift_name("flt")));
|
||||||
@property (class, readonly) int32_t integer __attribute__((swift_name("integer")));
|
@property (class, readonly) int32_t integer __attribute__((swift_name("integer")));
|
||||||
|
|||||||
@@ -788,3 +788,26 @@ fun testClassTypeCheck(x: Any) = x is ClassForTypeCheck
|
|||||||
interface InterfaceForTypeCheck
|
interface InterfaceForTypeCheck
|
||||||
|
|
||||||
fun testInterfaceTypeCheck(x: Any) = x is InterfaceForTypeCheck
|
fun testInterfaceTypeCheck(x: Any) = x is InterfaceForTypeCheck
|
||||||
|
|
||||||
|
interface IAbstractInterface {
|
||||||
|
fun foo(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAbstractInterface2 {
|
||||||
|
fun foo() = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testAbstractInterfaceCall(x: IAbstractInterface) = x.foo()
|
||||||
|
fun testAbstractInterfaceCall2(x: IAbstractInterface2) = x.foo()
|
||||||
|
|
||||||
|
abstract class AbstractInterfaceBase : IAbstractInterface {
|
||||||
|
override fun foo() = bar()
|
||||||
|
|
||||||
|
abstract fun bar(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractInterfaceBase2 : IAbstractInterface2
|
||||||
|
|
||||||
|
abstract class AbstractInterfaceBase3 : IAbstractInterface {
|
||||||
|
abstract override fun foo(): Int
|
||||||
|
}
|
||||||
@@ -1029,6 +1029,35 @@ func testInterfaceTypeCheck() throws {
|
|||||||
try assertFalse(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheck_Fail()))
|
try assertFalse(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheck_Fail()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AbstractInterface : AbstractInterfaceBase {
|
||||||
|
override func bar() -> Int32 {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://github.com/JetBrains/kotlin-native/issues/3503
|
||||||
|
func testGH3503_1() throws {
|
||||||
|
try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface()), expected: 42)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AbstractInterface2 : AbstractInterfaceBase2 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGH3503_2() throws {
|
||||||
|
try assertEquals(actual: ValuesKt.testAbstractInterfaceCall2(x: AbstractInterface2()), expected: 42)
|
||||||
|
}
|
||||||
|
|
||||||
|
class AbstractInterface3 : AbstractInterfaceBase3 {
|
||||||
|
override func foo() -> Int32 {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGH3503_3() throws {
|
||||||
|
try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface3()), expected: 42)
|
||||||
|
}
|
||||||
|
|
||||||
// -------- Execution of the test --------
|
// -------- Execution of the test --------
|
||||||
|
|
||||||
class ValuesTests : TestProvider {
|
class ValuesTests : TestProvider {
|
||||||
@@ -1080,6 +1109,9 @@ class ValuesTests : TestProvider {
|
|||||||
TestCase(name: "TestSharedRefs", method: withAutorelease(TestSharedRefs().test)),
|
TestCase(name: "TestSharedRefs", method: withAutorelease(TestSharedRefs().test)),
|
||||||
TestCase(name: "TestClassTypeCheck", method: withAutorelease(testClassTypeCheck)),
|
TestCase(name: "TestClassTypeCheck", method: withAutorelease(testClassTypeCheck)),
|
||||||
TestCase(name: "TestInterfaceTypeCheck", method: withAutorelease(testInterfaceTypeCheck)),
|
TestCase(name: "TestInterfaceTypeCheck", method: withAutorelease(testInterfaceTypeCheck)),
|
||||||
|
TestCase(name: "TestGH3503_1", method: withAutorelease(testGH3503_1)),
|
||||||
|
TestCase(name: "TestGH3503_2", method: withAutorelease(testGH3503_2)),
|
||||||
|
TestCase(name: "TestGH3503_3", method: withAutorelease(testGH3503_3)),
|
||||||
TestCase(name: "TestGH2931", method: withAutorelease(testGH2931)),
|
TestCase(name: "TestGH2931", method: withAutorelease(testGH2931)),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ struct ObjCTypeAdapter {
|
|||||||
const MethodTableRecord* kotlinMethodTable;
|
const MethodTableRecord* kotlinMethodTable;
|
||||||
int kotlinMethodTableSize;
|
int kotlinMethodTableSize;
|
||||||
|
|
||||||
|
const InterfaceTableRecord* kotlinItable;
|
||||||
int kotlinItableSize;
|
int kotlinItableSize;
|
||||||
|
|
||||||
const char* objCName;
|
const char* objCName;
|
||||||
@@ -634,6 +635,8 @@ static const TypeInfo* createTypeInfo(
|
|||||||
const KStdVector<VTableElement>& vtable,
|
const KStdVector<VTableElement>& vtable,
|
||||||
const KStdVector<MethodTableRecord>& methodTable,
|
const KStdVector<MethodTableRecord>& methodTable,
|
||||||
const KStdOrderedMap<ClassId, KStdVector<VTableElement>>& interfaceVTables,
|
const KStdOrderedMap<ClassId, KStdVector<VTableElement>>& interfaceVTables,
|
||||||
|
const InterfaceTableRecord* superItable,
|
||||||
|
int superItableSize,
|
||||||
bool itableEqualsSuper
|
bool itableEqualsSuper
|
||||||
) {
|
) {
|
||||||
TypeInfo* result = (TypeInfo*)konanAllocMemory(sizeof(TypeInfo) + vtable.size() * sizeof(void*));
|
TypeInfo* result = (TypeInfo*)konanAllocMemory(sizeof(TypeInfo) + vtable.size() * sizeof(void*));
|
||||||
@@ -669,11 +672,10 @@ static const TypeInfo* createTypeInfo(
|
|||||||
|
|
||||||
result->implementedInterfaces_ = implementedInterfaces_;
|
result->implementedInterfaces_ = implementedInterfaces_;
|
||||||
result->implementedInterfacesCount_ = implementedInterfaces.size();
|
result->implementedInterfacesCount_ = implementedInterfaces.size();
|
||||||
const InterfaceTableRecord* superItable = superType->interfaceTable_;
|
|
||||||
if (superItable != nullptr) {
|
if (superItable != nullptr) {
|
||||||
if (itableEqualsSuper) {
|
if (itableEqualsSuper) {
|
||||||
result->interfaceTableSize_ = superType->interfaceTableSize_;
|
result->interfaceTableSize_ = superItableSize;
|
||||||
result->interfaceTable_ = superType->interfaceTable_;
|
result->interfaceTable_ = superItable;
|
||||||
} else {
|
} else {
|
||||||
buildITable(result, interfaceVTables);
|
buildITable(result, interfaceVTables);
|
||||||
}
|
}
|
||||||
@@ -803,6 +805,9 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType) {
|
|||||||
const MethodTableRecord* superMethodTable = nullptr;
|
const MethodTableRecord* superMethodTable = nullptr;
|
||||||
int superMethodTableSize = 0;
|
int superMethodTableSize = 0;
|
||||||
|
|
||||||
|
InterfaceTableRecord const* superITable = nullptr;
|
||||||
|
int superITableSize = 0;
|
||||||
|
|
||||||
if (superTypeAdapter != nullptr) {
|
if (superTypeAdapter != nullptr) {
|
||||||
// Then super class is Kotlin class.
|
// Then super class is Kotlin class.
|
||||||
|
|
||||||
@@ -811,6 +816,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType) {
|
|||||||
superVtable = superTypeAdapter->kotlinVtable;
|
superVtable = superTypeAdapter->kotlinVtable;
|
||||||
superMethodTable = superTypeAdapter->kotlinMethodTable;
|
superMethodTable = superTypeAdapter->kotlinMethodTable;
|
||||||
superMethodTableSize = superTypeAdapter->kotlinMethodTableSize;
|
superMethodTableSize = superTypeAdapter->kotlinMethodTableSize;
|
||||||
|
superITable = superTypeAdapter->kotlinItable;
|
||||||
|
superITableSize = superTypeAdapter->kotlinItableSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superVtable == nullptr) superVtable = superType->vtable();
|
if (superVtable == nullptr) superVtable = superType->vtable();
|
||||||
@@ -828,12 +835,14 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType) {
|
|||||||
superMethodTable, superMethodTable + superMethodTableSize
|
superMethodTable, superMethodTable + superMethodTableSize
|
||||||
);
|
);
|
||||||
|
|
||||||
InterfaceTableRecord const* superITable = superType->interfaceTable_;
|
if (superITable == nullptr) {
|
||||||
|
superITable = superType->interfaceTable_;
|
||||||
|
superITableSize = superType->interfaceTableSize_;
|
||||||
|
}
|
||||||
KStdOrderedMap<ClassId, KStdVector<VTableElement>> interfaceVTables;
|
KStdOrderedMap<ClassId, KStdVector<VTableElement>> interfaceVTables;
|
||||||
if (superITable != nullptr) {
|
if (superITable != nullptr) {
|
||||||
int superITableSize = superType->interfaceTableSize_;
|
int actualItableSize = superITableSize >= 0 ? superITableSize + 1 : -superITableSize;
|
||||||
superITableSize = superITableSize >= 0 ? superITableSize + 1 : -superITableSize;
|
for (int i = 0; i < actualItableSize; ++i) {
|
||||||
for (int i = 0; i < superITableSize; ++i) {
|
|
||||||
auto& record = superITable[i];
|
auto& record = superITable[i];
|
||||||
auto interfaceId = record.id;
|
auto interfaceId = record.id;
|
||||||
if (interfaceId == kInvalidInterfaceId) continue;
|
if (interfaceId == kInvalidInterfaceId) continue;
|
||||||
@@ -919,7 +928,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType) {
|
|||||||
|
|
||||||
// TODO: consider forbidding the class being abstract.
|
// TODO: consider forbidding the class being abstract.
|
||||||
|
|
||||||
const TypeInfo* result = createTypeInfo(superType, addedInterfaces, vtable, methodTable, interfaceVTables, itableEqualsSuper);
|
const TypeInfo* result = createTypeInfo(superType, addedInterfaces, vtable, methodTable,
|
||||||
|
interfaceVTables, superITable, superITableSize, itableEqualsSuper);
|
||||||
|
|
||||||
// TODO: it will probably never be requested, since such a class can't be instantiated in Kotlin.
|
// TODO: it will probably never be requested, since such a class can't be instantiated in Kotlin.
|
||||||
result->writableInfo_->objCExport.objCClass = clazz;
|
result->writableInfo_->objCExport.objCClass = clazz;
|
||||||
|
|||||||
Reference in New Issue
Block a user