Merged different RTTI-related structure builders
This includes vTable, fields and associated objects
This commit is contained in:
+3
-3
@@ -257,10 +257,10 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName)
|
KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val vtableBuilders = mutableMapOf<IrClass, ClassVtablesBuilder>()
|
val layoutBuilders = mutableMapOf<IrClass, ClassLayoutBuilder>()
|
||||||
|
|
||||||
fun getVtableBuilder(classDescriptor: IrClass) = vtableBuilders.getOrPut(classDescriptor) {
|
fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) {
|
||||||
ClassVtablesBuilder(classDescriptor, this)
|
ClassLayoutBuilder(irClass, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We serialize untouched descriptor tree and inline IR bodies
|
// We serialize untouched descriptor tree and inline IR bodies
|
||||||
|
|||||||
+71
-7
@@ -12,11 +12,10 @@ import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
|||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
|
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.isInterface
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.ir.util.overrides
|
|
||||||
|
|
||||||
internal class OverriddenFunctionInfo(
|
internal class OverriddenFunctionInfo(
|
||||||
val function: IrSimpleFunction,
|
val function: IrSimpleFunction,
|
||||||
@@ -78,7 +77,7 @@ internal class OverriddenFunctionInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ClassVtablesBuilder(val irClass: IrClass, val context: Context) {
|
internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
|
||||||
private val DEBUG = 0
|
private val DEBUG = 0
|
||||||
|
|
||||||
private inline fun DEBUG_OUTPUT(severity: Int, block: () -> Unit) {
|
private inline fun DEBUG_OUTPUT(severity: Int, block: () -> Unit) {
|
||||||
@@ -98,7 +97,7 @@ internal class ClassVtablesBuilder(val irClass: IrClass, val context: Context) {
|
|||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
val superClass = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
val superClass = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||||
context.getVtableBuilder(superClass).vtableEntries
|
context.getLayoutBuilder(superClass).vtableEntries
|
||||||
}
|
}
|
||||||
|
|
||||||
val methods = irClass.sortedOverridableOrOverridingMethods
|
val methods = irClass.sortedOverridableOrOverridingMethods
|
||||||
@@ -172,6 +171,71 @@ internal class ClassVtablesBuilder(val irClass: IrClass, val context: Context) {
|
|||||||
// TODO: probably method table should contain all accessible methods to improve binary compatibility
|
// TODO: probably method table should contain all accessible methods to improve binary compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All fields of the class instance.
|
||||||
|
* The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix.
|
||||||
|
*/
|
||||||
|
val fields: List<IrField> by lazy {
|
||||||
|
val superClass = irClass.getSuperClassNotAny() // TODO: what if Any has fields?
|
||||||
|
val superFields = if (superClass != null) context.getLayoutBuilder(superClass).fields else emptyList()
|
||||||
|
|
||||||
|
superFields + getDeclaredFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
val associatedObjects by lazy {
|
||||||
|
val result = mutableMapOf<IrClass, IrClass>()
|
||||||
|
|
||||||
|
irClass.annotations.forEach {
|
||||||
|
val irFile = irClass.getContainingFile()
|
||||||
|
|
||||||
|
val annotationClass = (it.symbol.owner as? IrConstructor)?.constructedClass
|
||||||
|
?: error(irFile, it, "unexpected annotation")
|
||||||
|
|
||||||
|
if (annotationClass.hasAnnotation(RuntimeNames.associatedObjectKey)) {
|
||||||
|
val argument = it.getValueArgument(0)
|
||||||
|
|
||||||
|
val irClassReference = argument as? IrClassReference
|
||||||
|
?: error(irFile, argument, "unexpected annotation argument")
|
||||||
|
|
||||||
|
val associatedObject = irClassReference.symbol.owner
|
||||||
|
|
||||||
|
if (associatedObject !is IrClass || !associatedObject.isObject) {
|
||||||
|
error(irFile, irClassReference, "argument is not a singleton")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotationClass in result) {
|
||||||
|
error(
|
||||||
|
irFile,
|
||||||
|
it,
|
||||||
|
"duplicate value for ${annotationClass.name}, previous was ${result[annotationClass]?.name}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[annotationClass] = associatedObject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields declared in the class.
|
||||||
|
*/
|
||||||
|
private fun getDeclaredFields(): List<IrField> {
|
||||||
|
val fields = irClass.declarations.mapNotNull {
|
||||||
|
when (it) {
|
||||||
|
is IrField -> it.takeIf { it.isReal }
|
||||||
|
is IrProperty -> it.takeIf { it.isReal }?.backingField
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irClass.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields"))))
|
||||||
|
return fields
|
||||||
|
|
||||||
|
return fields.sortedBy { it.fqNameForIrSerialization.localHash.value }
|
||||||
|
}
|
||||||
|
|
||||||
private val IrClass.sortedOverridableOrOverridingMethods: List<IrSimpleFunction>
|
private val IrClass.sortedOverridableOrOverridingMethods: List<IrSimpleFunction>
|
||||||
get() =
|
get() =
|
||||||
this.simpleFunctions()
|
this.simpleFunctions()
|
||||||
+1
-1
@@ -722,7 +722,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
|
|
||||||
val llvmMethod = if (!owner.isInterface) {
|
val llvmMethod = if (!owner.isInterface) {
|
||||||
// If this is a virtual method of the class - we can call via vtable.
|
// If this is a virtual method of the class - we can call via vtable.
|
||||||
val index = context.getVtableBuilder(owner).vtableIndex(anyMethod ?: irFunction)
|
val index = context.getLayoutBuilder(owner).vtableIndex(anyMethod ?: irFunction)
|
||||||
val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1
|
val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1
|
||||||
val vtable = bitcast(kInt8PtrPtr, vtablePlace)
|
val vtable = bitcast(kInt8PtrPtr, vtablePlace)
|
||||||
val slot = gep(vtable, Int32(index).llvm)
|
val slot = gep(vtable, Int32(index).llvm)
|
||||||
|
|||||||
+4
-52
@@ -65,7 +65,6 @@ internal class LlvmDeclarations(
|
|||||||
|
|
||||||
internal class ClassLlvmDeclarations(
|
internal class ClassLlvmDeclarations(
|
||||||
val bodyType: LLVMTypeRef,
|
val bodyType: LLVMTypeRef,
|
||||||
val fields: List<IrField>, // TODO: it is not an LLVM declaration.
|
|
||||||
val typeInfoGlobal: StaticData.Global,
|
val typeInfoGlobal: StaticData.Global,
|
||||||
val writableTypeInfoGlobal: StaticData.Global?,
|
val writableTypeInfoGlobal: StaticData.Global?,
|
||||||
val typeInfo: ConstPointer,
|
val typeInfo: ConstPointer,
|
||||||
@@ -88,53 +87,6 @@ internal class StaticFieldLlvmDeclarations(val storage: LLVMValueRef)
|
|||||||
|
|
||||||
internal class UniqueLlvmDeclarations(val pointer: ConstPointer)
|
internal class UniqueLlvmDeclarations(val pointer: ConstPointer)
|
||||||
|
|
||||||
// TODO: rework getFields and getDeclaredFields.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All fields of the class instance.
|
|
||||||
* The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix.
|
|
||||||
*/
|
|
||||||
internal fun ContextUtils.getFields(irClass: IrClass) = context.getFields(irClass)
|
|
||||||
|
|
||||||
internal fun Context.getFields(irClass: IrClass): List<IrField> {
|
|
||||||
val superClass = irClass.getSuperClassNotAny() // TODO: what if Any has fields?
|
|
||||||
val superFields = if (superClass != null) getFields(superClass) else emptyList()
|
|
||||||
|
|
||||||
return superFields + getDeclaredFields(irClass)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fields declared in the class.
|
|
||||||
*/
|
|
||||||
private fun Context.getDeclaredFields(irClass: IrClass): List<IrField> {
|
|
||||||
// TODO: Here's what is going on here:
|
|
||||||
// The existence of a backing field for a property is only described in the IR,
|
|
||||||
// but not in the PropertyDescriptor.
|
|
||||||
//
|
|
||||||
// We mark serialized properties with a Konan protobuf extension bit,
|
|
||||||
// so it is present in DeserializedPropertyDescriptor.
|
|
||||||
//
|
|
||||||
// In this function we check the presence of the backing field
|
|
||||||
// two ways: first we check IR, then we check the protobuf extension.
|
|
||||||
|
|
||||||
val fields = irClass.declarations.mapNotNull {
|
|
||||||
when (it) {
|
|
||||||
is IrField -> it.takeIf { it.isReal }
|
|
||||||
is IrProperty -> it.takeIf { it.isReal }?.konanBackingField
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: hack over missed parents in deserialized fields/property declarations.
|
|
||||||
fields.forEach{it.parent = irClass}
|
|
||||||
|
|
||||||
if (irClass.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields"))))
|
|
||||||
return fields
|
|
||||||
|
|
||||||
return fields.sortedBy {
|
|
||||||
it.fqNameForIrSerialization.localHash.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
||||||
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) }
|
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) }
|
||||||
// TODO: consider adding synthetic ObjHeader field to Any.
|
// TODO: consider adding synthetic ObjHeader field to Any.
|
||||||
@@ -213,7 +165,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
||||||
val internalName = qualifyInternalName(declaration)
|
val internalName = qualifyInternalName(declaration)
|
||||||
|
|
||||||
val fields = getFields(declaration)
|
val fields = context.getLayoutBuilder(declaration).fields
|
||||||
val bodyType = createClassBodyType("kclassbody:$internalName", fields)
|
val bodyType = createClassBodyType("kclassbody:$internalName", fields)
|
||||||
|
|
||||||
val typeInfoPtr: ConstPointer
|
val typeInfoPtr: ConstPointer
|
||||||
@@ -232,7 +184,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
|
|
||||||
val typeInfoWithVtableType = structType(
|
val typeInfoWithVtableType = structType(
|
||||||
runtime.typeInfoType,
|
runtime.typeInfoType,
|
||||||
LLVMArrayType(int8TypePtr, context.getVtableBuilder(declaration).vtableEntries.size)!!
|
LLVMArrayType(int8TypePtr, context.getLayoutBuilder(declaration).vtableEntries.size)!!
|
||||||
)
|
)
|
||||||
|
|
||||||
typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false)
|
typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false)
|
||||||
@@ -290,7 +242,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
it.setZeroInitializer()
|
it.setZeroInitializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
return ClassLlvmDeclarations(bodyType, fields, typeInfoGlobal, writableTypeInfoGlobal, typeInfoPtr,
|
return ClassLlvmDeclarations(bodyType, typeInfoGlobal, writableTypeInfoGlobal, typeInfoPtr,
|
||||||
singletonDeclarations, objCDeclarations)
|
singletonDeclarations, objCDeclarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +319,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
if (containingClass != null) {
|
if (containingClass != null) {
|
||||||
val classDeclarations = this.classes[containingClass] ?:
|
val classDeclarations = this.classes[containingClass] ?:
|
||||||
error(containingClass.descriptor.toString())
|
error(containingClass.descriptor.toString())
|
||||||
val allFields = classDeclarations.fields
|
val allFields = context.getLayoutBuilder(containingClass).fields
|
||||||
this.fields[declaration] = FieldLlvmDeclarations(
|
this.fields[declaration] = FieldLlvmDeclarations(
|
||||||
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
|
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
|
||||||
classDeclarations.bodyType
|
classDeclarations.bodyType
|
||||||
|
|||||||
+6
-43
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.konan.ir.isAnonymousObject
|
|||||||
import org.jetbrains.kotlin.backend.konan.ir.isLocal
|
import org.jetbrains.kotlin.backend.konan.ir.isLocal
|
||||||
import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod
|
import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
@@ -47,7 +46,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
private fun checkAcyclicClass(irClass: IrClass): Boolean = when {
|
private fun checkAcyclicClass(irClass: IrClass): Boolean = when {
|
||||||
irClass.symbol == context.ir.symbols.array -> false
|
irClass.symbol == context.ir.symbols.array -> false
|
||||||
irClass.isArray -> true
|
irClass.isArray -> true
|
||||||
context.llvmDeclarations.forClass(irClass).fields.all { checkAcyclicFieldType(it.type) } -> true
|
context.getLayoutBuilder(irClass).fields.all { checkAcyclicFieldType(it.type) } -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +247,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
fun vtable(irClass: IrClass): ConstArray {
|
fun vtable(irClass: IrClass): ConstArray {
|
||||||
// TODO: compile-time resolution limits binary compatibility.
|
// TODO: compile-time resolution limits binary compatibility.
|
||||||
val vtableEntries = context.getVtableBuilder(irClass).vtableEntries.map {
|
val vtableEntries = context.getLayoutBuilder(irClass).vtableEntries.map {
|
||||||
val implementation = it.implementation
|
val implementation = it.implementation
|
||||||
if (implementation == null || implementation.isExternalObjCClassMethod()) {
|
if (implementation == null || implementation.isExternalObjCClassMethod()) {
|
||||||
NullPointer(int8Type)
|
NullPointer(int8Type)
|
||||||
@@ -261,7 +260,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
fun methodTableRecords(irClass: IrClass): List<MethodTableRecord> {
|
fun methodTableRecords(irClass: IrClass): List<MethodTableRecord> {
|
||||||
val functionNames = mutableMapOf<Long, OverriddenFunctionInfo>()
|
val functionNames = mutableMapOf<Long, OverriddenFunctionInfo>()
|
||||||
return context.getVtableBuilder(irClass).methodTableEntries.map {
|
return context.getLayoutBuilder(irClass).methodTableEntries.map {
|
||||||
val functionName = it.overriddenFunction.functionName
|
val functionName = it.overriddenFunction.functionName
|
||||||
val nameSignature = functionName.localHash
|
val nameSignature = functionName.localHash
|
||||||
val previous = functionNames.putIfAbsent(nameSignature.value, it)
|
val previous = functionNames.putIfAbsent(nameSignature.value, it)
|
||||||
@@ -295,11 +294,11 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr))
|
NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr))
|
||||||
} else {
|
} else {
|
||||||
data class FieldRecord(val offset: Int, val type: Int, val name: String)
|
data class FieldRecord(val offset: Int, val type: Int, val name: String)
|
||||||
val fields = getStructElements(bodyType).drop(1).mapIndexedNotNull { index, type ->
|
val fields = getStructElements(bodyType).drop(1).mapIndexed { index, type ->
|
||||||
FieldRecord(
|
FieldRecord(
|
||||||
LLVMOffsetOfElement(llvmTargetData, bodyType, index + 1).toInt(),
|
LLVMOffsetOfElement(llvmTargetData, bodyType, index + 1).toInt(),
|
||||||
mapRuntimeType(type),
|
mapRuntimeType(type),
|
||||||
llvmDeclarations.fields[index].name.asString())
|
context.getLayoutBuilder(irClass).fields[index].name.asString())
|
||||||
}
|
}
|
||||||
val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", int32Type,
|
val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", int32Type,
|
||||||
fields.map { Int32(it.offset) })
|
fields.map { Int32(it.offset) })
|
||||||
@@ -315,7 +314,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun genAssociatedObjects(irClass: IrClass): ConstPointer? {
|
private fun genAssociatedObjects(irClass: IrClass): ConstPointer? {
|
||||||
val associatedObjects = getAssociatedObjects(irClass)
|
val associatedObjects = context.getLayoutBuilder(irClass).associatedObjects
|
||||||
if (associatedObjects.isEmpty()) {
|
if (associatedObjects.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -425,42 +424,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAssociatedObjects(irClass: IrClass): Map<IrClass, IrClass> {
|
|
||||||
val result = mutableMapOf<IrClass, IrClass>()
|
|
||||||
|
|
||||||
irClass.annotations.forEach {
|
|
||||||
val irFile = irClass.getContainingFile()
|
|
||||||
|
|
||||||
val annotationClass = (it.symbol.owner as? IrConstructor)?.constructedClass
|
|
||||||
?: error(irFile, it, "unexpected annotation")
|
|
||||||
|
|
||||||
if (annotationClass.hasAnnotation(RuntimeNames.associatedObjectKey)) {
|
|
||||||
val argument = it.getValueArgument(0)
|
|
||||||
|
|
||||||
val irClassReference = argument as? IrClassReference
|
|
||||||
?: error(irFile, argument, "unexpected annotation argument")
|
|
||||||
|
|
||||||
val associatedObject = irClassReference.symbol.owner
|
|
||||||
|
|
||||||
if (associatedObject !is IrClass || !associatedObject.isObject) {
|
|
||||||
error(irFile, irClassReference, "argument is not a singleton")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (annotationClass in result) {
|
|
||||||
error(
|
|
||||||
irFile,
|
|
||||||
it,
|
|
||||||
"duplicate value for ${annotationClass.name}, previous was ${result[annotationClass]?.name}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
result[annotationClass] = associatedObject
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep in sync with Konan_TypeFlags in TypeInfo.h.
|
// Keep in sync with Konan_TypeFlags in TypeInfo.h.
|
||||||
private const val TF_IMMUTABLE = 1
|
private const val TF_IMMUTABLE = 1
|
||||||
private const val TF_ACYCLIC = 2
|
private const val TF_ACYCLIC = 2
|
||||||
|
|||||||
+1
-1
@@ -102,7 +102,7 @@ internal fun StaticData.createConstArrayList(array: ConstPointer, length: Int):
|
|||||||
// Now sort these values according to the order of fields returned by getFields()
|
// Now sort these values according to the order of fields returned by getFields()
|
||||||
// to match the sorting order of the real ArrayList().
|
// to match the sorting order of the real ArrayList().
|
||||||
val sorted = linkedMapOf<String, ConstValue>()
|
val sorted = linkedMapOf<String, ConstValue>()
|
||||||
getFields(arrayListClass).forEach {
|
context.getLayoutBuilder(arrayListClass).fields.forEach {
|
||||||
val fqName = it.fqNameForIrSerialization.asString()
|
val fqName = it.fqNameForIrSerialization.asString()
|
||||||
sorted.put(fqName, arrayListFields[fqName]!!)
|
sorted.put(fqName, arrayListFields[fqName]!!)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -901,7 +901,7 @@ private fun ObjCExportCodeGenerator.vtableIndex(irFunction: IrSimpleFunction): I
|
|||||||
return if (irClass.isInterface) {
|
return if (irClass.isInterface) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
context.getVtableBuilder(irClass).vtableIndex(irFunction)
|
context.getLayoutBuilder(irClass).vtableIndex(irFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -974,7 +974,7 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
|||||||
val vtableSize = if (irClass.kind == ClassKind.INTERFACE) {
|
val vtableSize = if (irClass.kind == ClassKind.INTERFACE) {
|
||||||
-1
|
-1
|
||||||
} else {
|
} else {
|
||||||
context.getVtableBuilder(irClass).vtableEntries.size
|
context.getLayoutBuilder(irClass).vtableEntries.size
|
||||||
}
|
}
|
||||||
|
|
||||||
val vtable = if (!irClass.isInterface && !irClass.typeInfoHasVtableAttached) {
|
val vtable = if (!irClass.isInterface && !irClass.typeInfoHasVtableAttached) {
|
||||||
|
|||||||
+1
-2
@@ -651,8 +651,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val vTableBuilder = context.getVtableBuilder(owner)
|
val vtableIndex = context.getLayoutBuilder(owner).vtableIndex(callee)
|
||||||
val vtableIndex = vTableBuilder.vtableIndex(callee)
|
|
||||||
DataFlowIR.Node.VtableCall(
|
DataFlowIR.Node.VtableCall(
|
||||||
symbolTable.mapFunction(callee.target),
|
symbolTable.mapFunction(callee.target),
|
||||||
receiverType,
|
receiverType,
|
||||||
|
|||||||
+3
-3
@@ -530,9 +530,9 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
type.superTypes += irClass.superTypes.map { mapClassReferenceType(it.getClass()!!) }
|
type.superTypes += irClass.superTypes.map { mapClassReferenceType(it.getClass()!!) }
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
val vtableBuilder = context.getVtableBuilder(irClass)
|
val layoutBuilder = context.getLayoutBuilder(irClass)
|
||||||
type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) }
|
type.vtable += layoutBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) }
|
||||||
vtableBuilder.methodTableEntries.forEach {
|
layoutBuilder.methodTableEntries.forEach {
|
||||||
type.itable[it.overriddenFunction.functionName.localHash.value] = mapFunction(it.getImplementation(context)!!)
|
type.itable[it.overriddenFunction.functionName.localHash.value] = mapFunction(it.getImplementation(context)!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user