diff --git a/native/commonizer/build.gradle.kts b/native/commonizer/build.gradle.kts index 09c8ae9ab61..56d679db12e 100644 --- a/native/commonizer/build.gradle.kts +++ b/native/commonizer/build.gradle.kts @@ -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")) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirAnnotation.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirAnnotation.kt index 8a266468b82..e8001fcf74a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirAnnotation.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirAnnotation.kt @@ -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() + private val interner = Interner() fun create(original: AnnotationDescriptor): CirAnnotation = interner.intern(CirAnnotation(original)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirFunction.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirFunction.kt index 9e1fc970849..2d8876b0607 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirFunction.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirFunction.kt @@ -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() + private val interner = Interner() fun create(original: ValueParameterDescriptor): CirValueParameterImpl = interner.intern(CirValueParameterImpl(original)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirProperty.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirProperty.kt index f8da6e1e793..a3ad1c95b58 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirProperty.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirProperty.kt @@ -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() + private val interner = Interner() 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() + private val interner = Interner() fun createDefaultNoAnnotations(visibility: Visibility) = interner.intern( CirSetter( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt index ea2fd45add3..e5aa6379bd4 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt @@ -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() + private val interner = Interner() - 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)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/NonThreadSafeInterner.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/Interner.kt similarity index 59% rename from native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/NonThreadSafeInterner.kt rename to native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/Interner.kt index 111a7a81fe0..fa4aa613141 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/NonThreadSafeInterner.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/Interner.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils -import java.util.WeakHashMap +import com.intellij.util.containers.WeakInterner -internal class NonThreadSafeInterner { - private val pool = WeakHashMap() +class Interner { + private val pool = WeakInterner() - fun intern(value: T): T = pool.computeIfAbsent(value) { value } + fun intern(value: T): T = pool.intern(value) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt index 84cb2bdbf9c..a4445f4a970 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/misc.kt @@ -16,3 +16,9 @@ internal fun Sequence.toList(expectedCapacity: Int): List { internal inline fun Iterable.firstNonNull() = firstIsInstance() 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) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt index 3f01cd7cb56..8b215adeab6 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt @@ -74,7 +74,7 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, explor } // dedicated to hold unique entries of "fqNameWithTypeParameters" -private val stringInterner = NonThreadSafeInterner() +private val stringInterner = Interner() -private val fqNameInterner = NonThreadSafeInterner() -private val nameInterner = NonThreadSafeInterner() +private val fqNameInterner = Interner() +private val nameInterner = Interner()