[IR] Reduce memory pollution during by mangler

- Make some ObjCInterop utils garbage-free

(cherry picked from commit 6388b9ca72c7f96f85df32cde4b53a262467333e)
This commit is contained in:
Roman Artemev
2020-07-27 18:04:34 +03:00
committed by Vasily Levchenko
parent 7680722f23
commit 2c1e9a9e2d
@@ -14,8 +14,10 @@ import org.jetbrains.kotlin.backend.konan.descriptors.getStringValueOrNull
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
@@ -28,6 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal val interopPackageName = InteropFqNames.packageName
internal val objCObjectFqName = interopPackageName.child(Name.identifier("ObjCObject"))
@@ -40,17 +43,20 @@ private val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFa
private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames")
fun ClassDescriptor.isObjCClass(): Boolean =
this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } && // TODO: this is not cheap. Cache me!
this.containingDeclaration.fqNameSafe != interopPackageName
this.containingDeclaration.fqNameSafe != interopPackageName &&
this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } // TODO: this is not cheap. Cache me!
fun KotlinType.isObjCObjectType(): Boolean =
(this.supertypes() + this).any { TypeUtils.getClassDescriptor(it)?.fqNameSafe == objCObjectFqName }
private fun IrClass.getAllSuperClassifiers(): List<IrClass> =
listOf(this) + this.superTypes.flatMap { (it.classifierOrFail.owner as IrClass).getAllSuperClassifiers() }
private fun IrClass.selfOrAnySuperClass(pred: (IrClass) -> Boolean): Boolean {
if (pred(this)) return true
internal fun IrClass.isObjCClass() = this.getAllSuperClassifiers().any { it.fqNameForIrSerialization == objCObjectFqName } &&
this.parent.fqNameForIrSerialization != interopPackageName
return superTypes.any { it.classOrNull!!.owner.selfOrAnySuperClass(pred) }
}
internal fun IrClass.isObjCClass() = this.parent.fqNameForIrSerialization != interopPackageName &&
selfOrAnySuperClass { it.fqNameForIrSerialization == objCObjectFqName }
fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() &&
this.parentsWithSelf.filterIsInstance<ClassDescriptor>().any {
@@ -68,7 +74,7 @@ fun ClassDescriptor.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().a
it.fqNameSafe == objCClassFqName
}
fun IrClass.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().any {
fun IrClass.isObjCMetaClass(): Boolean = selfOrAnySuperClass {
it.fqNameForIrSerialization == objCClassFqName
}
@@ -142,7 +148,7 @@ private fun FunctionDescriptor.getObjCMethodInfo(onlyExternal: Boolean): ObjCMet
}
}
return this.overriddenDescriptors.asSequence().mapNotNull { it.getObjCMethodInfo(onlyExternal) }.firstOrNull()
return overriddenDescriptors.firstNotNullResult { it.getObjCMethodInfo(onlyExternal) }
}
/**
@@ -157,7 +163,7 @@ private fun IrSimpleFunction.getObjCMethodInfo(onlyExternal: Boolean): ObjCMetho
}
}
return this.overriddenSymbols.mapNotNull { it.owner.getObjCMethodInfo(onlyExternal) }.firstOrNull()
return overriddenSymbols.firstNotNullResult { it.owner.getObjCMethodInfo(onlyExternal) }
}
fun FunctionDescriptor.getExternalObjCMethodInfo(): ObjCMethodInfo? = this.getObjCMethodInfo(onlyExternal = true)
@@ -268,9 +274,16 @@ fun IrConstructor.getObjCInitMethod(): IrSimpleFunction? {
fun ConstructorDescriptor.getObjCInitMethod(): FunctionDescriptor? {
return this.annotations.findAnnotation(objCConstructorFqName)?.let {
val initSelector = it.getAnnotationStringValue("initSelector")
this.constructedClass.unsubstitutedMemberScope.getContributedDescriptors().asSequence()
.filterIsInstance<FunctionDescriptor>()
.single { it.getExternalObjCMethodInfo()?.selector == initSelector }
val memberScope = constructedClass.unsubstitutedMemberScope
val functionNames = memberScope.getFunctionNames()
for (name in functionNames) {
val functions = memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
for (function in functions) {
val objectInfo = function.getExternalObjCMethodInfo() ?: continue
if (objectInfo.selector == initSelector) return function
}
}
error("Cannot find ObjInitMethod for $this")
}
}