[Commonizer] Improve performance of 'backwardsTypeDistance'

This commit also introduces common sealed interfaces to represent
classifiers and types coming form dependencies or 'sources'

^KT-48288
This commit is contained in:
sebastian.sellmair
2021-09-17 09:21:11 +02:00
committed by Space
parent fadb91fa35
commit 64d2ba4029
20 changed files with 195 additions and 145 deletions
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cir
sealed interface AnyClassifier
sealed interface AnyClass : CirHasVisibility
sealed interface AnyTypeAlias {
val underlyingType: AnyType
}
sealed interface AnyType {
val isMarkedNullable: Boolean
}
sealed interface AnyClassOrTypeAliasType {
val classifierId: CirEntityId
}
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
interface CirClass : CirClassifier, CirContainingClass {
interface CirClass : CirClassifier, CirContainingClass, AnyClass {
var companion: CirName? // null means no companion object
val isCompanion: Boolean
val isValue: Boolean
@@ -10,4 +10,5 @@ sealed interface CirClassifier :
CirHasAnnotations,
CirHasName,
CirHasTypeParameters,
CirHasVisibility
CirHasVisibility,
AnyClassifier
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.commonizer.cir
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
internal fun CirProvided.ClassOrTypeAliasType.toCirClassOrTypeAliasTypeOrNull(classifiers: CirProvidedClassifiers): CirClassOrTypeAliasType? {
@@ -41,7 +41,6 @@ interface CirHasModality {
val modality: Modality
}
interface CirMaybeCallableMemberOfClass {
val containingClass: CirContainingClass? // null assumes no containing class
@@ -0,0 +1,112 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer.cir
import org.jetbrains.kotlin.commonizer.cir.ArtificialSupertypes.artificialSupertypes
import org.jetbrains.kotlin.commonizer.utils.CNAMES_STRUCTS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_CLASSES_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_PROTOCOLS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.types.Variance
object CirProvided {
/* Classifiers */
sealed interface Classifier: AnyClassifier {
val typeParameters: List<TypeParameter>
}
sealed interface Class : Classifier, AnyClass {
override val visibility: Visibility
val supertypes: List<Type>
}
data class RegularClass(
override val typeParameters: List<TypeParameter>,
override val supertypes: List<Type>,
override val visibility: Visibility,
val kind: ClassKind
) : Class
data class ExportedForwardDeclarationClass(val syntheticClassId: CirEntityId) : Class {
init {
check(syntheticClassId.packageName.isUnderKotlinNativeSyntheticPackages)
}
override val typeParameters: List<TypeParameter> get() = emptyList()
override val visibility: Visibility get() = Visibilities.Public
override val supertypes: List<Type> = syntheticClassId.artificialSupertypes()
}
data class TypeAlias(
override val typeParameters: List<TypeParameter>,
override val underlyingType: ClassOrTypeAliasType
) : Classifier, AnyTypeAlias
/* Type parameter */
data class TypeParameter(val index: Int, val variance: Variance)
/* Types */
sealed interface Type: AnyType {
override val isMarkedNullable: Boolean
}
sealed interface ClassOrTypeAliasType : Type, AnyClassOrTypeAliasType {
override val classifierId: CirEntityId
val arguments: List<TypeProjection>
}
data class TypeParameterType(
val index: Int,
override val isMarkedNullable: Boolean
) : Type
data class ClassType(
override val classifierId: CirEntityId,
override val arguments: List<TypeProjection>,
override val isMarkedNullable: Boolean,
val outerType: ClassType?
) : ClassOrTypeAliasType
data class TypeAliasType(
override val classifierId: CirEntityId,
override val arguments: List<TypeProjection>,
override val isMarkedNullable: Boolean
) : ClassOrTypeAliasType
/* Type projections */
sealed interface TypeProjection
object StarTypeProjection : TypeProjection
data class RegularTypeProjection(val variance: Variance, val type: Type) : TypeProjection
}
/**
* Analog to "KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule" which also
* automatically assumes relevant supertypes for forward declarations based upon the package they are in.
*/
private object ArtificialSupertypes {
private fun createType(classId: String): CirProvided.ClassType {
return CirProvided.ClassType(
classifierId = CirEntityId.create(classId),
outerType = null, arguments = emptyList(), isMarkedNullable = false
)
}
private val cOpaqueType = listOf(createType("kotlinx/cinterop/COpaque"))
private val objcObjectBase = listOf(createType("kotlinx/cinterop/ObjCObjectBase"))
private val objcCObject = listOf(createType("kotlinx/cinterop/ObjCObject"))
fun CirEntityId.artificialSupertypes(): List<CirProvided.Type> {
return when (packageName) {
CNAMES_STRUCTS_PACKAGE -> cOpaqueType
OBJCNAMES_CLASSES_PACKAGE -> objcObjectBase
OBJCNAMES_PROTOCOLS_PACKAGE -> objcCObject
else -> emptyList()
}
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.commonizer.cir
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.findClass
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.commonizer.utils.hashCode
import org.jetbrains.kotlin.types.Variance
/**
* The hierarchy of [CirType]:
*
@@ -40,8 +39,8 @@ data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSim
/**
* Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost.
*/
sealed class CirSimpleType : CirType() {
abstract val isMarkedNullable: Boolean
sealed class CirSimpleType : CirType(), AnyType {
abstract override val isMarkedNullable: Boolean
override fun appendDescriptionTo(builder: StringBuilder) {
if (isMarkedNullable) builder.append('?')
@@ -71,8 +70,8 @@ abstract class CirTypeParameterType : CirSimpleType() {
}
}
sealed class CirClassOrTypeAliasType : CirSimpleType() {
abstract val classifierId: CirEntityId
sealed class CirClassOrTypeAliasType : CirSimpleType(), AnyClassOrTypeAliasType {
abstract override val classifierId: CirEntityId
abstract val arguments: List<CirTypeProjection>
override fun appendDescriptionTo(builder: StringBuilder) = appendDescriptionTo(builder, shortNameOnly = false)
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.commonizer.cir
import org.jetbrains.kotlin.descriptors.Visibility
interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration {
val underlyingType: CirClassOrTypeAliasType
interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration, AnyTypeAlias {
override val underlyingType: CirClassOrTypeAliasType
val expandedType: CirClassType
companion object {
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.SimpleCirSupertypesResolver
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.findClass
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -11,6 +11,7 @@ import gnu.trove.THashMap
import gnu.trove.THashSet
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.cir.CirTypeAlias
internal fun AssociatedClassifierIdsResolver(
@@ -9,6 +9,7 @@ import gnu.trove.THashMap
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.types.Variance
@@ -7,15 +7,9 @@ package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.ModulesProvider
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.mergedtree.ArtificialSupertypes.artificialSupertypes
import org.jetbrains.kotlin.commonizer.utils.CNAMES_STRUCTS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_CLASSES_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.OBJCNAMES_PROTOCOLS_PACKAGE
import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.types.Variance
/** A set of classes and type aliases provided by libraries (either the libraries to commonize, or their dependency libraries)/ */
interface CirProvidedClassifiers {
@@ -74,98 +68,3 @@ interface CirProvidedClassifiers {
}
}
object CirProvided {
/* Classifiers */
sealed interface Classifier {
val typeParameters: List<TypeParameter>
}
sealed interface Class : Classifier {
val visibility: Visibility
val supertypes: List<Type>
}
data class RegularClass(
override val typeParameters: List<TypeParameter>,
override val supertypes: List<Type>,
override val visibility: Visibility,
val kind: ClassKind
) : Class
data class ExportedForwardDeclarationClass(val syntheticClassId: CirEntityId) : Class {
init {
check(syntheticClassId.packageName.isUnderKotlinNativeSyntheticPackages)
}
override val typeParameters: List<TypeParameter> get() = emptyList()
override val visibility: Visibility get() = Visibilities.Public
override val supertypes: List<Type> = syntheticClassId.artificialSupertypes()
}
data class TypeAlias(
override val typeParameters: List<TypeParameter>,
val underlyingType: ClassOrTypeAliasType
) : Classifier
/* Type parameter */
data class TypeParameter(val index: Int, val variance: Variance)
/* Types */
sealed interface Type {
val isMarkedNullable: Boolean
}
sealed interface ClassOrTypeAliasType : Type {
val classifierId: CirEntityId
val arguments: List<TypeProjection>
}
data class TypeParameterType(
val index: Int,
override val isMarkedNullable: Boolean
) : Type
data class ClassType(
override val classifierId: CirEntityId,
override val arguments: List<TypeProjection>,
override val isMarkedNullable: Boolean,
val outerType: ClassType?
) : ClassOrTypeAliasType
data class TypeAliasType(
override val classifierId: CirEntityId,
override val arguments: List<TypeProjection>,
override val isMarkedNullable: Boolean
) : ClassOrTypeAliasType
/* Type projections */
sealed interface TypeProjection
object StarTypeProjection : TypeProjection
data class RegularTypeProjection(val variance: Variance, val type: Type) : TypeProjection
}
/**
* Analog to "KlibResolvedModuleDescriptorsFactoryImpl.createForwardDeclarationsModule" which also
* automatically assumes relevant supertypes for forward declarations based upon the package they are in.
*/
private object ArtificialSupertypes {
private fun createType(classId: String): CirProvided.ClassType {
return CirProvided.ClassType(
classifierId = CirEntityId.create(classId),
outerType = null, arguments = emptyList(), isMarkedNullable = false
)
}
private val cOpaqueType = listOf(createType("kotlinx/cinterop/COpaque"))
private val objcObjectBase = listOf(createType("kotlinx/cinterop/ObjCObjectBase"))
private val objcCObject = listOf(createType("kotlinx/cinterop/ObjCObject"))
fun CirEntityId.artificialSupertypes(): List<CirProvided.Type> {
return when (packageName) {
CNAMES_STRUCTS_PACKAGE -> cOpaqueType
OBJCNAMES_CLASSES_PACKAGE -> objcObjectBase
OBJCNAMES_PROTOCOLS_PACKAGE -> objcCObject
else -> emptyList()
}
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.commonizer.ModulesProvider.CInteropModuleAttributes
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers.Companion.FALLBACK_FORWARD_DECLARATION_CLASS
import org.jetbrains.kotlin.commonizer.utils.*
import org.jetbrains.kotlin.library.SerializedMetadata
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.CommonizerTarget
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirTypeDistance.Companion.unreachable
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@JvmInline
value class CirTypeDistance(private val value: Int) : Comparable<CirTypeDistance> {
@@ -100,10 +101,11 @@ internal fun typeDistance(
val fromExpansion = from.expandedType()
val distanceToExpansion = typeDistance(classifiers, targetIndex, from, fromExpansion.classifierId)
return backwardsTypeDistance(classifiers, targetIndex, from.expandedType().classifierId, to) - distanceToExpansion
return backwardsTypeDistance(classifiers, targetIndex, fromExpansion.classifierId, to) - distanceToExpansion
}
private fun forwardTypeDistance(from: CirClassOrTypeAliasType, to: CirEntityId): CirTypeDistance {
internal fun forwardTypeDistance(from: CirClassOrTypeAliasType, to: CirEntityId): CirTypeDistance {
if (from.classifierId == to) return CirTypeDistance(0)
if (from !is CirTypeAliasType) return unreachable
var iteration = 0
@@ -117,31 +119,50 @@ private fun forwardTypeDistance(from: CirClassOrTypeAliasType, to: CirEntityId):
}
}
private fun backwardsTypeDistance(
internal fun backwardsTypeDistance(
classifiers: CirKnownClassifiers, targetIndex: Int, from: CirEntityId, to: CirEntityId
): CirTypeDistance {
val resolvedDependencyClassifier =
classifiers.commonDependencies.classifier(to) ?: classifiers.targetDependencies[targetIndex].classifier(to)
if (resolvedDependencyClassifier != null) {
return backwardsTypeDistance(classifiers, targetIndex, from, resolvedDependencyClassifier)
if (from == to) return CirTypeDistance(0)
generateUnderlyingTypeSequence(classifiers, targetIndex, to)
.forEachIndexed { index, type -> if (type.classifierId == from) return CirTypeDistance(-index - 1) }
return unreachable
}
internal fun generateUnderlyingTypeSequence(
classifiers: CirKnownClassifiers, targetIndex: Int, id: CirEntityId
): Sequence<AnyClassOrTypeAliasType> {
val resolvedClassifier = classifiers.classifierIndices[targetIndex].findClassifier(id)
if (resolvedClassifier != null) {
return generateUnderlyingTypeSequence(resolvedClassifier)
}
val resolvedClassifier = classifiers.classifierIndices[targetIndex].findClassifier(to) ?: return unreachable
return backwardsTypeDistance(classifiers, targetIndex, from, resolvedClassifier)
val resolvedFromCommonDependencies = classifiers.commonDependencies.classifier(id)
if (resolvedFromCommonDependencies != null) {
return generateUnderlyingTypeSequence(classifiers.commonDependencies, resolvedFromCommonDependencies)
}
val resolvedFromTargetDependencies = classifiers.targetDependencies[targetIndex].classifier(id)
if (resolvedFromTargetDependencies != null) {
return generateUnderlyingTypeSequence(
CirProvidedClassifiers.of(classifiers.commonDependencies, classifiers.targetDependencies[targetIndex]),
resolvedFromTargetDependencies
)
}
return emptySequence()
}
private fun backwardsTypeDistance(
classifiers: CirKnownClassifiers, targetIndex: Int, from: CirEntityId, to: CirProvided.Classifier
): CirTypeDistance {
if (to !is CirProvided.TypeAlias) return unreachable
if (to.underlyingType.classifierId == from) return CirTypeDistance(-1)
return backwardsTypeDistance(classifiers, targetIndex, from, to.underlyingType.classifierId) - 1
internal fun generateUnderlyingTypeSequence(classifier: CirClassifier): Sequence<CirClassOrTypeAliasType> {
if (classifier !is CirTypeAlias) return emptySequence()
return generateSequence(classifier.underlyingType) { type -> if (type is CirTypeAliasType) type.underlyingType else null }
}
private fun backwardsTypeDistance(
classifiers: CirKnownClassifiers, targetIndex: Int, from: CirEntityId, to: CirClassifier
): CirTypeDistance {
if (to !is CirTypeAlias) return unreachable
if (to.underlyingType.classifierId == from) return CirTypeDistance(-1)
return backwardsTypeDistance(classifiers, targetIndex, from, to.underlyingType.classifierId) - 1
}
internal fun generateUnderlyingTypeSequence(
classifiers: CirProvidedClassifiers, classifier: CirProvided.Classifier
): Sequence<CirProvided.ClassOrTypeAliasType> {
if (classifier !is CirProvided.TypeAlias) return emptySequence()
return generateSequence(classifier.underlyingType) next@{ type ->
if (type !is CirProvided.TypeAliasType) return@next null
classifiers.classifier(type.classifierId)?.safeAs<CirProvided.TypeAlias>()?.underlyingType
}
}
@@ -12,7 +12,7 @@ import kotlinx.metadata.klib.compileTimeValue
import kotlinx.metadata.klib.getterAnnotations
import kotlinx.metadata.klib.setterAnnotations
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.utils.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.types.Variance
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.commonizer.metadata
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.utils.compactMapIndexed
import org.jetbrains.kotlin.types.Variance
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.commonizer.metadata
import gnu.trove.TIntObjectHashMap
import kotlinx.metadata.KmTypeParameter
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
import org.jetbrains.kotlin.commonizer.tree.deserializer.ClassesToProcess
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.commonizer.cir
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiers
import org.jetbrains.kotlin.commonizer.mergedtree.CirProvidedClassifiersByModules
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot
@@ -2,10 +2,7 @@ package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mapValue
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.tree.CirTreeRoot