[Commonzer] Fix ISE during commonization, improve interner performance

Issue #MMPP-191
This commit is contained in:
Dmitriy Dolovov
2020-03-06 12:44:38 +07:00
parent 7da220b0a2
commit ed96b81a42
8 changed files with 75 additions and 79 deletions
+1
View File
@@ -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"))
@@ -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))
}
@@ -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))
}
@@ -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(
@@ -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))
}
@@ -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>()