Fix using cached Kotlin subclasses of Objective-C classes (#3990)
This commit is contained in:
committed by
GitHub
parent
5b9beec860
commit
fe3057a40b
+9
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
|||||||
import org.jetbrains.kotlin.backend.konan.ir.allParameters
|
import org.jetbrains.kotlin.backend.konan.ir.allParameters
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.isUnit
|
import org.jetbrains.kotlin.backend.konan.ir.isUnit
|
||||||
import org.jetbrains.kotlin.backend.konan.isExternalObjCClass
|
import org.jetbrains.kotlin.backend.konan.isExternalObjCClass
|
||||||
|
import org.jetbrains.kotlin.backend.konan.isKotlinObjCClass
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.AbstractKonanIrMangler
|
import org.jetbrains.kotlin.backend.konan.serialization.AbstractKonanIrMangler
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.util.findAnnotation
|
import org.jetbrains.kotlin.ir.util.findAnnotation
|
||||||
@@ -93,6 +94,14 @@ internal val IrClass.objectInstanceGetterSymbolName: String
|
|||||||
return "kobjget:$fqNameForIrSerialization"
|
return "kobjget:$fqNameForIrSerialization"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val IrClass.kotlinObjCClassInfoSymbolName: String
|
||||||
|
get() {
|
||||||
|
assert (this.isExported())
|
||||||
|
assert (this.isKotlinObjCClass())
|
||||||
|
|
||||||
|
return "kobjcclassinfo:$fqNameForIrSerialization"
|
||||||
|
}
|
||||||
|
|
||||||
val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName }
|
val IrFunction.functionName get() = with(KonanBinaryInterface) { functionName }
|
||||||
|
|
||||||
val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName }
|
val IrFunction.symbolName get() = with(KonanBinaryInterface) { symbolName }
|
||||||
|
|||||||
+4
-7
@@ -1005,22 +1005,19 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
error("type-checking against Kotlin classes inheriting Objective-C meta-classes isn't supported yet")
|
error("type-checking against Kotlin classes inheriting Objective-C meta-classes isn't supported yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
val objCDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
val classInfo = codegen.kotlinObjCClassInfo(irClass)
|
||||||
val classPointerGlobal = objCDeclarations.classPointerGlobal.llvmGlobal
|
val classPointerGlobal = load(structGep(classInfo, 12 /* createdClass */))
|
||||||
|
|
||||||
val storedClass = this.load(classPointerGlobal)
|
val storedClass = this.load(classPointerGlobal)
|
||||||
|
|
||||||
val storedClassIsNotNull = this.icmpNe(storedClass, kNullInt8Ptr)
|
val storedClassIsNotNull = this.icmpNe(storedClass, kNullInt8Ptr)
|
||||||
|
|
||||||
return this.ifThenElse(storedClassIsNotNull, storedClass) {
|
return this.ifThenElse(storedClassIsNotNull, storedClass) {
|
||||||
val newClass = call(
|
call(
|
||||||
context.llvm.createKotlinObjCClass,
|
context.llvm.createKotlinObjCClass,
|
||||||
listOf(objCDeclarations.classInfoGlobal.llvmGlobal),
|
listOf(classInfo),
|
||||||
exceptionHandler = exceptionHandler
|
exceptionHandler = exceptionHandler
|
||||||
)
|
)
|
||||||
|
|
||||||
this.store(newClass, classPointerGlobal)
|
|
||||||
newClass
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-2
@@ -66,12 +66,14 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
irClass.typeInfoPtr,
|
irClass.typeInfoPtr,
|
||||||
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
|
||||||
|
|
||||||
objCLLvmDeclarations.classPointerGlobal.pointer
|
staticData.placeGlobal(
|
||||||
|
"kobjcclassptr:${irClass.fqNameForIrSerialization}#internal",
|
||||||
|
NullPointer(int8Type)
|
||||||
|
).pointer
|
||||||
)
|
)
|
||||||
|
|
||||||
objCLLvmDeclarations.classInfoGlobal.setInitializer(info)
|
objCLLvmDeclarations.classInfoGlobal.setInitializer(info)
|
||||||
|
|
||||||
objCLLvmDeclarations.classPointerGlobal.setInitializer(NullPointer(int8Type))
|
|
||||||
objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(Int32(0))
|
objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(Int32(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,3 +135,16 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun CodeGenerator.kotlinObjCClassInfo(irClass: IrClass): LLVMValueRef {
|
||||||
|
require(irClass.isKotlinObjCClass())
|
||||||
|
return if (isExternal(irClass)) {
|
||||||
|
importGlobal(
|
||||||
|
irClass.kotlinObjCClassInfoSymbolName,
|
||||||
|
runtime.kotlinObjCClassInfo,
|
||||||
|
origin = irClass.llvmSymbolOrigin
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
context.llvmDeclarations.forClass(irClass).objCDeclarations!!.classInfoGlobal.llvmGlobal
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-5
@@ -70,7 +70,6 @@ internal class ClassLlvmDeclarations(
|
|||||||
internal class SingletonLlvmDeclarations(val instanceStorage: AddressAccess, val instanceShadowStorage: AddressAccess?)
|
internal class SingletonLlvmDeclarations(val instanceStorage: AddressAccess, val instanceShadowStorage: AddressAccess?)
|
||||||
|
|
||||||
internal class KotlinObjCClassLlvmDeclarations(
|
internal class KotlinObjCClassLlvmDeclarations(
|
||||||
val classPointerGlobal: StaticData.Global,
|
|
||||||
val classInfoGlobal: StaticData.Global,
|
val classInfoGlobal: StaticData.Global,
|
||||||
val bodyOffsetGlobal: StaticData.Global
|
val bodyOffsetGlobal: StaticData.Global
|
||||||
)
|
)
|
||||||
@@ -290,18 +289,23 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
private fun createKotlinObjCClassDeclarations(irClass: IrClass): KotlinObjCClassLlvmDeclarations {
|
private fun createKotlinObjCClassDeclarations(irClass: IrClass): KotlinObjCClassLlvmDeclarations {
|
||||||
val internalName = qualifyInternalName(irClass)
|
val internalName = qualifyInternalName(irClass)
|
||||||
|
|
||||||
val classPointerGlobal = staticData.createGlobal(int8TypePtr, "kobjcclassptr:$internalName")
|
val isExported = irClass.isExported()
|
||||||
|
val classInfoSymbolName = if (isExported) {
|
||||||
|
irClass.kotlinObjCClassInfoSymbolName
|
||||||
|
} else {
|
||||||
|
"kobjcclassinfo:$internalName"
|
||||||
|
}
|
||||||
val classInfoGlobal = staticData.createGlobal(
|
val classInfoGlobal = staticData.createGlobal(
|
||||||
context.llvm.runtime.kotlinObjCClassInfo,
|
context.llvm.runtime.kotlinObjCClassInfo,
|
||||||
"kobjcclassinfo:$internalName"
|
classInfoSymbolName,
|
||||||
|
isExported = isExported
|
||||||
).apply {
|
).apply {
|
||||||
setConstant(true)
|
setConstant(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bodyOffsetGlobal = staticData.createGlobal(int32Type, "kobjcbodyoffs:$internalName")
|
val bodyOffsetGlobal = staticData.createGlobal(int32Type, "kobjcbodyoffs:$internalName")
|
||||||
|
|
||||||
return KotlinObjCClassLlvmDeclarations(classPointerGlobal, classInfoGlobal, bodyOffsetGlobal)
|
return KotlinObjCClassLlvmDeclarations(classInfoGlobal, bodyOffsetGlobal)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(declaration: IrField) {
|
override fun visitField(declaration: IrField) {
|
||||||
|
|||||||
Reference in New Issue
Block a user