[Commonzer] Fix ISE during commonization, improve interner performance
Issue #MMPP-191
This commit is contained in:
@@ -20,6 +20,7 @@ dependencies {
|
||||
compileOnly(project(":compiler:frontend"))
|
||||
compileOnly(project(":native:frontend.native"))
|
||||
compileOnly(project(":kotlin-util-klib-metadata"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
// This dependency is necessary to keep the right dependency record inside of POM file:
|
||||
mavenCompileScope(project(":kotlin-compiler"))
|
||||
|
||||
+10
-8
@@ -6,7 +6,9 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.NonThreadSafeInterner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -25,7 +27,7 @@ class CirAnnotation private constructor(original: AnnotationDescriptor) {
|
||||
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
|
||||
private var cachedHashCode = 0
|
||||
|
||||
private fun computeHashCode() = fqName.hashCode() * 31 + allValueArguments.hashCode()
|
||||
private fun computeHashCode() = hashCode(fqName).appendHashCode(allValueArguments)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var currentHashCode = cachedHashCode
|
||||
@@ -36,14 +38,14 @@ class CirAnnotation private constructor(original: AnnotationDescriptor) {
|
||||
return currentHashCode
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
if (other is CirAnnotation) {
|
||||
fqName == other.fqName && allValueArguments == other.allValueArguments
|
||||
} else
|
||||
false
|
||||
override fun equals(other: Any?): Boolean = when {
|
||||
other === this -> true
|
||||
other is CirAnnotation -> fqName == other.fqName && allValueArguments == other.allValueArguments
|
||||
else -> false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val interner = NonThreadSafeInterner<CirAnnotation>()
|
||||
private val interner = Interner<CirAnnotation>()
|
||||
|
||||
fun create(original: AnnotationDescriptor): CirAnnotation = interner.intern(CirAnnotation(original))
|
||||
}
|
||||
|
||||
+17
-16
@@ -6,7 +6,9 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.NonThreadSafeInterner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -85,16 +87,13 @@ class CirValueParameterImpl private constructor(original: ValueParameterDescript
|
||||
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
|
||||
private var cachedHashCode = 0
|
||||
|
||||
private fun computeHashCode(): Int {
|
||||
var result = name.hashCode()
|
||||
result += 31 * result + annotations.hashCode()
|
||||
result += 31 * result + returnType.hashCode()
|
||||
result += 31 * result + varargElementType.hashCode()
|
||||
result += 31 * result + declaresDefaultValue.hashCode()
|
||||
result += 31 * result + isCrossinline.hashCode()
|
||||
result += 31 * result + isNoinline.hashCode()
|
||||
return result
|
||||
}
|
||||
private fun computeHashCode() = hashCode(name)
|
||||
.appendHashCode(annotations)
|
||||
.appendHashCode(returnType)
|
||||
.appendHashCode(varargElementType)
|
||||
.appendHashCode(declaresDefaultValue)
|
||||
.appendHashCode(isCrossinline)
|
||||
.appendHashCode(isNoinline)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var currentHashCode = cachedHashCode
|
||||
@@ -105,8 +104,9 @@ class CirValueParameterImpl private constructor(original: ValueParameterDescript
|
||||
return currentHashCode
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
if (other is CirValueParameterImpl) {
|
||||
override fun equals(other: Any?): Boolean = when {
|
||||
other === this -> true
|
||||
other is CirValueParameterImpl -> {
|
||||
name == other.name
|
||||
&& returnType == other.returnType
|
||||
&& annotations == other.annotations
|
||||
@@ -114,11 +114,12 @@ class CirValueParameterImpl private constructor(original: ValueParameterDescript
|
||||
&& declaresDefaultValue == other.declaresDefaultValue
|
||||
&& isCrossinline == other.isCrossinline
|
||||
&& isNoinline == other.isNoinline
|
||||
} else
|
||||
false
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val interner = NonThreadSafeInterner<CirValueParameterImpl>()
|
||||
private val interner = Interner<CirValueParameterImpl>()
|
||||
|
||||
fun create(original: ValueParameterDescriptor): CirValueParameterImpl = interner.intern(CirValueParameterImpl(original))
|
||||
}
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirGetter.Companion.toGetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirSetter.Companion.toSetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.NonThreadSafeInterner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
|
||||
interface CirProperty : CirFunctionOrProperty {
|
||||
@@ -78,7 +78,7 @@ data class CirGetter private constructor(
|
||||
override val isInline: Boolean
|
||||
) : CirPropertyAccessor {
|
||||
companion object {
|
||||
private val interner = NonThreadSafeInterner<CirGetter>()
|
||||
private val interner = Interner<CirGetter>()
|
||||
|
||||
val DEFAULT_NO_ANNOTATIONS = interner.intern(
|
||||
CirGetter(
|
||||
@@ -114,7 +114,7 @@ data class CirSetter private constructor(
|
||||
override val isInline: Boolean
|
||||
) : CirPropertyAccessor, CirDeclarationWithVisibility {
|
||||
companion object {
|
||||
private val interner = NonThreadSafeInterner<CirSetter>()
|
||||
private val interner = Interner<CirSetter>()
|
||||
|
||||
fun createDefaultNoAnnotations(visibility: Visibility) = interner.intern(
|
||||
CirSetter(
|
||||
|
||||
+31
-45
@@ -60,54 +60,44 @@ class CirSimpleType private constructor(original: SimpleType) : CirType() {
|
||||
inline val isClassOrTypeAlias get() = (kind == CLASS || kind == TYPE_ALIAS)
|
||||
val fqNameWithTypeParameters = original.fqNameWithTypeParameters
|
||||
|
||||
// Note: equals() and hashCode() are implemented in a way that only right-hand side declaration
|
||||
// is compared for typealiases (well, actually "fqNameWithTypeParameters" for the right-hand side).
|
||||
// This is sufficient for unit tests and for evaluating commonized supertypes, but is absolutely
|
||||
// unsuitable for comparison of CirSimpleType for the purposes of interning, etc.
|
||||
override fun equals(other: Any?) = fqNameWithTypeParameters == (other as? CirSimpleType)?.fqNameWithTypeParameters
|
||||
override fun hashCode() = fqNameWithTypeParameters.hashCode()
|
||||
|
||||
private class Interned(val type: CirSimpleType) {
|
||||
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
|
||||
private var cachedHashCode = 0
|
||||
|
||||
private fun computeHashCode(): Int {
|
||||
var result = type.annotations.hashCode()
|
||||
result = 31 * result + type.kind.hashCode()
|
||||
result = 31 * result + type.fqName.hashCode()
|
||||
result = 31 * result + type.arguments.hashCode()
|
||||
result = 31 * result + type.isMarkedNullable.hashCode()
|
||||
result = 31 * result + type.isDefinitelyNotNullType.hashCode()
|
||||
result = 31 * result + type.fqNameWithTypeParameters.hashCode()
|
||||
return result
|
||||
override fun equals(other: Any?) = when {
|
||||
other === this -> true
|
||||
other is CirSimpleType -> {
|
||||
isMarkedNullable == other.isMarkedNullable
|
||||
&& fqName == other.fqName
|
||||
&& kind == other.kind
|
||||
&& arguments == other.arguments
|
||||
&& fqNameWithTypeParameters == other.fqNameWithTypeParameters
|
||||
&& annotations == other.annotations
|
||||
&& isDefinitelyNotNullType == other.isDefinitelyNotNullType
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var currentHashCode = cachedHashCode
|
||||
if (currentHashCode != 0) return currentHashCode
|
||||
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
|
||||
private var cachedHashCode = 0
|
||||
|
||||
currentHashCode = computeHashCode()
|
||||
cachedHashCode = currentHashCode
|
||||
return currentHashCode
|
||||
}
|
||||
private fun computeHashCode() = hashCode(annotations)
|
||||
.appendHashCode(kind)
|
||||
.appendHashCode(fqName)
|
||||
.appendHashCode(arguments)
|
||||
.appendHashCode(isMarkedNullable)
|
||||
.appendHashCode(isDefinitelyNotNullType)
|
||||
.appendHashCode(fqNameWithTypeParameters)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
if (other is Interned) {
|
||||
type.isMarkedNullable == other.type.isMarkedNullable
|
||||
&& type.fqName == other.type.fqName
|
||||
&& type.kind == other.type.kind
|
||||
&& type.arguments == other.type.arguments
|
||||
&& type.fqNameWithTypeParameters == other.type.fqNameWithTypeParameters
|
||||
&& type.annotations == other.type.annotations
|
||||
&& type.isDefinitelyNotNullType == other.type.isDefinitelyNotNullType
|
||||
} else
|
||||
false
|
||||
override fun hashCode(): Int {
|
||||
var currentHashCode = cachedHashCode
|
||||
if (currentHashCode != 0) return currentHashCode
|
||||
|
||||
currentHashCode = computeHashCode()
|
||||
cachedHashCode = currentHashCode
|
||||
return currentHashCode
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val interner = NonThreadSafeInterner<Interned>()
|
||||
private val interner = Interner<CirSimpleType>()
|
||||
|
||||
fun create(original: SimpleType): CirSimpleType = interner.intern(Interned(CirSimpleType(original))).type
|
||||
fun create(original: SimpleType): CirSimpleType = interner.intern(CirSimpleType(original))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,11 +123,7 @@ data class CirTypeConstructorId(val fqName: FqName, val numberOfTypeParameters:
|
||||
constructor(type: SimpleType) : this(type.fqNameInterned, type.constructor.parameters.size)
|
||||
}
|
||||
|
||||
data class CirTypeProjection(
|
||||
val projectionKind: Variance,
|
||||
val isStarProjection: Boolean,
|
||||
val type: CirType
|
||||
) {
|
||||
data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType) {
|
||||
constructor(original: TypeProjection) : this(original.projectionKind, original.isStarProjection, CirType.create(original.type))
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import java.util.WeakHashMap
|
||||
import com.intellij.util.containers.WeakInterner
|
||||
|
||||
internal class NonThreadSafeInterner<T : Any> {
|
||||
private val pool = WeakHashMap<T, T>()
|
||||
class Interner<T : Any> {
|
||||
private val pool = WeakInterner<T>()
|
||||
|
||||
fun intern(value: T): T = pool.computeIfAbsent(value) { value }
|
||||
fun intern(value: T): T = pool.intern(value)
|
||||
}
|
||||
@@ -16,3 +16,9 @@ internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
|
||||
internal inline fun <reified T> Iterable<T?>.firstNonNull() = firstIsInstance<T>()
|
||||
|
||||
internal fun Any?.isNull(): Boolean = this == null
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun hashCode(value: Any?): Int = value.hashCode()
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun Int.appendHashCode(value: Any?): Int = 31 * this + hashCode(value)
|
||||
|
||||
@@ -74,7 +74,7 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor
|
||||
}
|
||||
|
||||
// dedicated to hold unique entries of "fqNameWithTypeParameters"
|
||||
private val stringInterner = NonThreadSafeInterner<String>()
|
||||
private val stringInterner = Interner<String>()
|
||||
|
||||
private val fqNameInterner = NonThreadSafeInterner<FqName>()
|
||||
private val nameInterner = NonThreadSafeInterner<Name>()
|
||||
private val fqNameInterner = Interner<FqName>()
|
||||
private val nameInterner = Interner<Name>()
|
||||
|
||||
Reference in New Issue
Block a user