From 29596b9be7cabeb76fd58cdfb54989214c4dd996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Doln=C3=ADk?= Date: Fri, 12 Apr 2024 16:27:55 +0200 Subject: [PATCH] Optimize signature equals. --- .../skie/phases/memberconflicts/Signature.kt | 24 +++---- .../memberconflicts/SirHierarchyCache.kt | 62 +++---------------- .../memberconflicts/UniqueSignatureSet.kt | 46 +++++++++----- .../sir/element/SirCallableDeclaration.kt | 2 +- .../touchlab/skie/sir/element/SirFunction.kt | 2 +- .../touchlab/skie/sir/element/SirProperty.kt | 2 +- .../skie/sir/element/SirSimpleFunction.kt | 2 +- 7 files changed, 55 insertions(+), 85 deletions(-) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/Signature.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/Signature.kt index aff35760..730d53b4 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/Signature.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/Signature.kt @@ -100,13 +100,13 @@ sealed class Signature { if (this === other) return true if (other !is Signature) return false + if (this is EnumCase && other is Function || this is Function && other is EnumCase) return false + if (receiver != other.receiver) return false - if (identifier != other.identifier) return false - if (valueParameters != other.valueParameters) return false if (returnType != other.returnType) return false + if (valueParameters != other.valueParameters) return false if (scope != other.scope) return false - - if (this is EnumCase && other is Function || this is Function && other is EnumCase) return false + if (identifier != other.identifier) return false return true } @@ -213,11 +213,11 @@ sealed class Signature { other as Class - if (typeArguments != other.typeArguments) return false - - return with(sirHierarchyCache) { - sirClass.sharesDirectInheritanceHierarchy(other.sirClass) + with(sirHierarchyCache) { + if (!sirClass.sharesDirectInheritanceHierarchy(other.sirClass)) return false } + + return typeArguments == other.typeArguments } override fun hashCode(): Int = typeArguments.hashCode() @@ -284,7 +284,7 @@ sealed class Signature { companion object { - operator fun invoke(enumCase: SirEnumCase, sirHierarchyCache: SirHierarchyCache): Signature = + operator fun invoke(enumCase: SirEnumCase, sirHierarchyCache: SirHierarchyCache = SirHierarchyCache()): Signature = with(sirHierarchyCache) { EnumCase( receiver = Receiver.Simple(enumCase.parent.asReceiverType, emptySet()), @@ -292,14 +292,14 @@ sealed class Signature { ) } - operator fun invoke(callableDeclaration: SirCallableDeclaration, sirHierarchyCache: SirHierarchyCache): Signature = + operator fun invoke(callableDeclaration: SirCallableDeclaration, sirHierarchyCache: SirHierarchyCache = SirHierarchyCache()): Signature = when (callableDeclaration) { is SirSimpleFunction -> Signature(callableDeclaration, sirHierarchyCache) is SirConstructor -> Signature(callableDeclaration, sirHierarchyCache) is SirProperty -> Signature(callableDeclaration, sirHierarchyCache) } - operator fun invoke(function: SirSimpleFunction, sirHierarchyCache: SirHierarchyCache): Signature = + operator fun invoke(function: SirSimpleFunction, sirHierarchyCache: SirHierarchyCache = SirHierarchyCache()): Signature = with(sirHierarchyCache) { SimpleFunction( receiver = function.receiver, @@ -310,7 +310,7 @@ sealed class Signature { ) } - operator fun invoke(constructor: SirConstructor, sirHierarchyCache: SirHierarchyCache): Signature { + operator fun invoke(constructor: SirConstructor, sirHierarchyCache: SirHierarchyCache = SirHierarchyCache()): Signature { val receiver = with(sirHierarchyCache) { constructor.receiver } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/SirHierarchyCache.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/SirHierarchyCache.kt index 5c029afd..d8229afa 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/SirHierarchyCache.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/SirHierarchyCache.kt @@ -5,62 +5,18 @@ import co.touchlab.skie.sir.element.resolveAsSirClass class SirHierarchyCache { - private val primaryCache = mutableMapOf>() + private val allSuperTypesAndSelfCache = mutableMapOf>() - private val inheritanceCache = mutableMapOf>() + fun SirClass.sharesDirectInheritanceHierarchy(other: SirClass): Boolean = + this.isSelfOrInheritsFrom(other) || other.isSelfOrInheritsFrom(this) - fun SirClass.sharesDirectInheritanceHierarchy(other: SirClass): Boolean { - if (this == other) { - return true - } - - if (!this.canTheoreticallyShareDirectInheritanceHierarchy(other)) { - return false - } - - primaryCache[this]?.get(other)?.let { return it } - - val result = this.inheritsFrom(other) || other.inheritsFrom(this) - - primaryCache.getOrPut(this) { mutableMapOf() }[other] = result - primaryCache.getOrPut(other) { mutableMapOf() }[this] = result - - return result - } - - private fun SirClass.inheritsFrom(other: SirClass): Boolean { - if (!this.canTheoreticallyInheritFrom(other)) { - return false - } - - inheritanceCache[this]?.get(other)?.let { return it } + private fun SirClass.isSelfOrInheritsFrom(other: SirClass): Boolean = + other in this.getAllSuperTypesAndSelf() - val superClasses = superTypes.mapNotNull { it.resolveAsSirClass() } + private fun SirClass.getAllSuperTypesAndSelf(): Set = + allSuperTypesAndSelfCache.getOrPut(this) { + val superTypes = superTypes.mapNotNull { it.resolveAsSirClass() }.toSet() - val inheritsFrom = other in superClasses || superClasses.any { it.inheritsFrom(other) } - - inheritanceCache.getOrPut(this) { mutableMapOf() }[other] = inheritsFrom - if (inheritsFrom) { - inheritanceCache.getOrPut(other) { mutableMapOf() }[this] = false + superTypes + superTypes.flatMap { it.getAllSuperTypesAndSelf() } + this } - - return inheritsFrom - } - - private fun SirClass.canTheoreticallyShareDirectInheritanceHierarchy(other: SirClass): Boolean { - // TODO Implement based on open/close if added to SirClass - if ((this.kind.isStruct || this.kind.isEnum) && !other.kind.isProtocol) return false - if ((other.kind.isStruct || other.kind.isEnum) && !this.kind.isProtocol) return false - - return true - } - - private fun SirClass.canTheoreticallyInheritFrom(other: SirClass): Boolean { - // TODO Implement based on open/close if added to SirClass - if (other.kind.isStruct) return false - if (other.kind.isEnum) return false - if (other.kind.isClass && !this.kind.isClass) return false - - return true - } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/UniqueSignatureSet.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/UniqueSignatureSet.kt index f21884e6..d5093920 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/UniqueSignatureSet.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/UniqueSignatureSet.kt @@ -14,7 +14,9 @@ class UniqueSignatureSet { private val alreadyAddedDeclarations = mutableSetOf() private val alreadyAddedEnumCase = mutableSetOf() - // Map so that we can get the signatures for conflicts + // Map so that we can get the signatures for conflicts by identifier (for performance reasons) + // Map of signature to signature instead of set because we need to know which declaration is conflicting + // The algorithm utilises custom equality which checks if the signature is the same from the overload resolution perspective. private val existingSignaturesMap = mutableMapOf() private val sirHierarchyCache = SirHierarchyCache() @@ -30,8 +32,10 @@ class UniqueSignatureSet { group.resolveCollisionWithWarning { val signature = signature - if (signature in existingSignaturesMap) { - "an another declaration '${existingSignaturesMap[signature]}'" + val conflictingSignature = findConflictingSignature(signature) + + if (conflictingSignature != null) { + "an another declaration '$conflictingSignature'" } else { null } @@ -49,18 +53,27 @@ class UniqueSignatureSet { enumCase.resolveCollisionWithWarning { val signature = signature - if (signature in existingSignaturesMap) { - "an another declaration '${existingSignaturesMap[signature]}'" + val conflictingSignature = findConflictingSignature(signature) + + if (conflictingSignature != null) { + "an another declaration '${conflictingSignature}'" } else { null } } - val signature = enumCase.signature - existingSignaturesMap.putIfAbsent(signature, signature) + addSignature(enumCase.signature) + alreadyAddedEnumCase.add(enumCase) } + private fun findConflictingSignature(signature: Signature): Signature? = + existingSignaturesMap[signature] + + private fun addSignature(signature: Signature) { + existingSignaturesMap[signature] = signature + } + private inner class Group( private val representative: SirCallableDeclaration, ) { @@ -72,11 +85,14 @@ class UniqueSignatureSet { do { var changed = false - callableDeclarations.forEach { - // Avoid short-circuiting - changed = it.resolveCollisionWithWarning(collisionReasonProvider) || changed + for (callableDeclaration in callableDeclarations) { + changed = callableDeclaration.resolveCollisionWithWarning(collisionReasonProvider) + + if (changed) { + unifyNames(callableDeclaration) - unifyNames(it) + break + } } } while (changed) } @@ -94,14 +110,12 @@ class UniqueSignatureSet { } fun addToCaches() { - val representativeSignature = representative.signature - existingSignaturesMap.putIfAbsent(representativeSignature, representativeSignature) + addSignature(representative.signature) alreadyAddedDeclarations.addAll(callableDeclarations) - callableDeclarations.forEach { - val signature = it.signature - existingSignaturesMap.putIfAbsent(signature, signature) + callableDeclarations.forEach { + addSignature(it.signature) } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirCallableDeclaration.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirCallableDeclaration.kt index 702de1a6..8979cf0a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirCallableDeclaration.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirCallableDeclaration.kt @@ -49,7 +49,7 @@ sealed interface SirCallableDeclaration : SirDeclaration, SirElementWithModifier val deprecationLevel: DeprecationLevel fun toReadableString(): String = - Signature(this, SirHierarchyCache()).toString() + Signature(this).toString() } val SirCallableDeclaration.receiverDeclaration: SirClass? diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirFunction.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirFunction.kt index 77d883a0..e3093a68 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirFunction.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirFunction.kt @@ -54,7 +54,7 @@ sealed class SirFunction( protected abstract val identifierForReference: String override fun toString(): String = - Signature(this, SirHierarchyCache()).toString() + Signature(this).toString() } fun SirFunction.call(arguments: List): String = diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirProperty.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirProperty.kt index ec5e87f2..10ccb3da 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirProperty.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirProperty.kt @@ -76,7 +76,7 @@ class SirProperty( } override fun toString(): String = - Signature(this, SirHierarchyCache()).toString() + Signature(this).toString() companion object { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirSimpleFunction.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirSimpleFunction.kt index 96706b28..e9d0509a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirSimpleFunction.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/element/SirSimpleFunction.kt @@ -61,7 +61,7 @@ class SirSimpleFunction( } override fun toString(): String = - Signature(this, SirHierarchyCache()).toString() + Signature(this).toString() companion object {