mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[Commonizer] Use AssociativeCommonizer signature to implement ClassOrTypeAliasTypeCommonizer
This drastically improves performance for now, since the previous Adapter implementation was at least O(n^2). While the Adapter implementation could have been reduced to O(n), the Signature of StatelessCommonizer was misleading. StatelessCommonizer will be introduced back later when other Commonizer implementations are ready to be converted to a new Signature.
This commit is contained in:
committed by
Space
parent
20f55ef0b7
commit
b29fd17d26
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.core
|
||||
|
||||
internal interface AssociativeCommonizer<T> {
|
||||
fun commonize(first: T, second: T): T?
|
||||
}
|
||||
|
||||
internal open class AssociativeCommonizerAdapter<T : Any>(
|
||||
private val commonizer: AssociativeCommonizer<T>
|
||||
) : AbstractStandardCommonizer<T, T>() {
|
||||
|
||||
private var _result: T? = null
|
||||
|
||||
override fun commonizationResult(): T {
|
||||
return _result ?: failInEmptyState()
|
||||
}
|
||||
|
||||
override fun initialize(first: T) = Unit
|
||||
|
||||
override fun doCommonizeWith(next: T): Boolean {
|
||||
val currentResult = _result
|
||||
|
||||
if (currentResult == null) {
|
||||
_result = next
|
||||
return true
|
||||
}
|
||||
|
||||
_result = commonizer.commonize(currentResult, next)
|
||||
return _result != null
|
||||
}
|
||||
}
|
||||
@@ -10,52 +10,49 @@ import org.jetbrains.kotlin.commonizer.cir.CirClassType
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirTypeAliasType
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||
|
||||
internal class ClassOrTypeAliasTypeStatelessCommonizer(
|
||||
internal class ClassOrTypeAliasTypeAssociativeCommonizer(
|
||||
private val classifiers: CirKnownClassifiers
|
||||
) : StatelessCommonizer<CirClassOrTypeAliasType, CirClassOrTypeAliasType> {
|
||||
) : AssociativeCommonizer<CirClassOrTypeAliasType> {
|
||||
|
||||
override fun commonize(values: List<CirClassOrTypeAliasType>): CirClassOrTypeAliasType? {
|
||||
if (values.isEmpty()) return null
|
||||
values.singleOrNull()?.let { return it }
|
||||
|
||||
val classTypes = values.filterIsInstance<CirClassType>()
|
||||
val typeAliasTypes = values.filterIsInstance<CirTypeAliasType>()
|
||||
val expandedTypeAliasTypes = typeAliasTypes.map { it.expandedType() }
|
||||
|
||||
if (values.all { it is CirClassType }) {
|
||||
return ClassTypeCommonizer(classifiers).commonize(classTypes)
|
||||
override fun commonize(first: CirClassOrTypeAliasType, second: CirClassOrTypeAliasType): CirClassOrTypeAliasType? {
|
||||
if (first is CirClassType && second is CirClassType) {
|
||||
return ClassTypeCommonizer(classifiers).commonize(listOf(first, second))
|
||||
}
|
||||
|
||||
if (values.all { it is CirTypeAliasType }) {
|
||||
if (first is CirTypeAliasType && second is CirTypeAliasType) {
|
||||
/*
|
||||
In case regular type-alias-type commonization fails, we try to expand all type-aliases and
|
||||
try our luck with commonizing those class types
|
||||
*/
|
||||
return TypeAliasTypeCommonizer(classifiers).commonize(typeAliasTypes)
|
||||
?: ClassTypeCommonizer(classifiers).commonize(expandedTypeAliasTypes)
|
||||
return TypeAliasTypeCommonizer(classifiers).commonize(listOf(first, second))
|
||||
?: ClassTypeCommonizer(classifiers).commonize(listOf(first.expandedType(), second.expandedType()))
|
||||
}
|
||||
|
||||
val classType = when {
|
||||
first is CirClassType -> first
|
||||
second is CirClassType -> second
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val typeAliasType = when {
|
||||
first is CirTypeAliasType -> first
|
||||
second is CirTypeAliasType -> second
|
||||
else -> return null
|
||||
}
|
||||
|
||||
/*
|
||||
There are type-alias types & class types enqueued for commonization.
|
||||
We reduce all classes to a common representation and all type aliases to a common representation.
|
||||
TypeAliasCommonizer will be able to figure out if the typealias will be represented as expect class in common.
|
||||
If so, re-use this class type, otherwise: try to expand the typeAlias
|
||||
*/
|
||||
val commonizedClass = ClassTypeCommonizer(classifiers).commonize(classTypes) ?: return null
|
||||
val commonizedTypeAlias = TypeAliasTypeCommonizer(classifiers).commonize(typeAliasTypes)
|
||||
val typeAliasClassType = TypeAliasTypeCommonizer(classifiers).commonize(listOf(typeAliasType))?.expandedType()
|
||||
?: typeAliasType.expandedType()
|
||||
|
||||
if (commonizedTypeAlias != null) {
|
||||
return ClassTypeCommonizer(classifiers).commonize(listOf(commonizedClass, commonizedTypeAlias.expandedType()))
|
||||
}
|
||||
|
||||
/*
|
||||
If type-alias type commonization failed:
|
||||
Last attempt: Try to commonize all type-alias expansions with the commonized class
|
||||
*/
|
||||
return ClassTypeCommonizer(classifiers).commonize(expandedTypeAliasTypes + commonizedClass)
|
||||
return ClassTypeCommonizer(classifiers).commonize(listOf(classType, typeAliasClassType))
|
||||
}
|
||||
}
|
||||
|
||||
internal class ClassOrTypeAliasTypeCommonizer(classifiers: CirKnownClassifiers) :
|
||||
StatelessCommonizerAdapter<CirClassOrTypeAliasType, CirClassOrTypeAliasType>(ClassOrTypeAliasTypeStatelessCommonizer(classifiers))
|
||||
AssociativeCommonizerAdapter<CirClassOrTypeAliasType>(ClassOrTypeAliasTypeAssociativeCommonizer(classifiers))
|
||||
|
||||
internal tailrec fun CirClassOrTypeAliasType.expandedType(): CirClassType = when (this) {
|
||||
is CirClassType -> this
|
||||
|
||||
@@ -11,11 +11,6 @@ interface Commonizer<T, R> {
|
||||
}
|
||||
|
||||
fun <T, R> Commonizer<T, R>.commonize(values: List<T>): R? {
|
||||
/* Fast path: If commonizer supports StatelessCommonizer interface */
|
||||
if (this is StatelessCommonizerAdapter) {
|
||||
return commonize(values)
|
||||
}
|
||||
|
||||
values.forEach { value -> if (!commonizeWith(value)) return null }
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.core
|
||||
|
||||
interface StatelessCommonizer<T, R> {
|
||||
fun commonize(values: List<T>): R?
|
||||
}
|
||||
|
||||
open class StatelessCommonizerAdapter<T, R : Any>(
|
||||
private val commonizer: StatelessCommonizer<T, R>
|
||||
) : AbstractStandardCommonizer<T, R>(), StatelessCommonizer<T, R> by commonizer {
|
||||
private val values = mutableListOf<T>()
|
||||
|
||||
override fun commonizationResult(): R {
|
||||
try {
|
||||
return checkNotNull(commonize(values.toList()))
|
||||
} finally {
|
||||
values.clear()
|
||||
}
|
||||
}
|
||||
|
||||
override fun initialize(first: T) = Unit
|
||||
|
||||
override fun doCommonizeWith(next: T): Boolean {
|
||||
values.add(next)
|
||||
return commonize(values.toList()) != null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user