Fix using cached Kotlin subclasses of Objective-C classes (#3990)

This commit is contained in:
SvyatoslavScherbina
2020-03-18 14:17:48 +03:00
committed by GitHub
parent 5b9beec860
commit fe3057a40b
4 changed files with 39 additions and 14 deletions
@@ -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.isUnit
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.ir.declarations.*
import org.jetbrains.kotlin.ir.util.findAnnotation
@@ -93,6 +94,14 @@ internal val IrClass.objectInstanceGetterSymbolName: String
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.symbolName get() = with(KonanBinaryInterface) { symbolName }
@@ -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")
}
val objCDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!!
val classPointerGlobal = objCDeclarations.classPointerGlobal.llvmGlobal
val classInfo = codegen.kotlinObjCClassInfo(irClass)
val classPointerGlobal = load(structGep(classInfo, 12 /* createdClass */))
val storedClass = this.load(classPointerGlobal)
val storedClassIsNotNull = this.icmpNe(storedClass, kNullInt8Ptr)
return this.ifThenElse(storedClassIsNotNull, storedClass) {
val newClass = call(
call(
context.llvm.createKotlinObjCClass,
listOf(objCDeclarations.classInfoGlobal.llvmGlobal),
listOf(classInfo),
exceptionHandler = exceptionHandler
)
this.store(newClass, classPointerGlobal)
newClass
}
}
}
@@ -66,12 +66,14 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
irClass.typeInfoPtr,
companionObject?.typeInfoPtr ?: NullPointer(runtime.typeInfoType),
objCLLvmDeclarations.classPointerGlobal.pointer
staticData.placeGlobal(
"kobjcclassptr:${irClass.fqNameForIrSerialization}#internal",
NullPointer(int8Type)
).pointer
)
objCLLvmDeclarations.classInfoGlobal.setInitializer(info)
objCLLvmDeclarations.classPointerGlobal.setInitializer(NullPointer(int8Type))
objCLLvmDeclarations.bodyOffsetGlobal.setInitializer(Int32(0))
}
@@ -132,4 +134,17 @@ internal class KotlinObjCClassInfoGenerator(override val context: Context) : Con
it.llvmFunction
)
}
}
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
}
}
@@ -70,7 +70,6 @@ internal class ClassLlvmDeclarations(
internal class SingletonLlvmDeclarations(val instanceStorage: AddressAccess, val instanceShadowStorage: AddressAccess?)
internal class KotlinObjCClassLlvmDeclarations(
val classPointerGlobal: StaticData.Global,
val classInfoGlobal: StaticData.Global,
val bodyOffsetGlobal: StaticData.Global
)
@@ -290,18 +289,23 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
private fun createKotlinObjCClassDeclarations(irClass: IrClass): KotlinObjCClassLlvmDeclarations {
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(
context.llvm.runtime.kotlinObjCClassInfo,
"kobjcclassinfo:$internalName"
classInfoSymbolName,
isExported = isExported
).apply {
setConstant(true)
}
val bodyOffsetGlobal = staticData.createGlobal(int32Type, "kobjcbodyoffs:$internalName")
return KotlinObjCClassLlvmDeclarations(classPointerGlobal, classInfoGlobal, bodyOffsetGlobal)
return KotlinObjCClassLlvmDeclarations(classInfoGlobal, bodyOffsetGlobal)
}
override fun visitField(declaration: IrField) {