[FIR] Optimize synthetic function symbol provider with ClassId heuristic

- Similar to the implementation of `isNameForFunctionClass` in
  `FirSymbolProvider`, `FirSyntheticFunctionInterfaceProvider` benefits
  from checking the `ClassId` for a digit before accessing its class
  cache.
This commit is contained in:
Marco Pennekamp
2023-03-08 22:48:00 +01:00
committed by Space Team
parent 79457ec074
commit 09ab192205
2 changed files with 15 additions and 8 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirSyntheticFunctionInterfaceProviderBase.Companion.mayBeSyntheticFunctionClassName
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
import org.jetbrains.kotlin.fir.scopes.getFunctions
@@ -16,14 +17,10 @@ import org.jetbrains.kotlin.fir.scopes.getProperties
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.types.functionTypeService
@RequiresOptIn
annotation class FirSymbolProviderInternals
@@ -144,10 +141,9 @@ fun Set<String>.mayHaveTopLevelClassifier(
private inline fun Set<String>.mayHaveTopLevelClassifier(shortClassName: Name): Boolean =
shortClassName.asString() in this || shortClassName.isSpecial
@OptIn(FirSymbolProviderInternals::class)
private fun isNameForFunctionClass(classId: ClassId, session: FirSession): Boolean {
// Optimization: `classId` can only be a name for a generated function class if it ends with a digit. See `FunctionTypeKind`.
if (classId.relativeClassName.asString().lastOrNull()?.isDigit() != true) return false
if (!classId.mayBeSyntheticFunctionClassName()) return false
return session.functionTypeService.getKindByClassNamePrefix(classId.packageFqName, classId.shortClassName.asString()) != null
}
@@ -70,6 +70,7 @@ abstract class FirSyntheticFunctionInterfaceProviderBase(
val kotlinScopeProvider: FirKotlinScopeProvider
) : FirSymbolProvider(session) {
override fun getClassLikeSymbolByClassId(classId: ClassId): FirRegularClassSymbol? {
if (!classId.mayBeSyntheticFunctionClassName()) return null
return cache.getValue(classId)
}
@@ -233,4 +234,14 @@ abstract class FirSyntheticFunctionInterfaceProviderBase(
}
private fun FunctionTypeKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
companion object {
/**
* A [ClassId] can only be a name for a generated function class if it ends with a digit. See [FunctionTypeKind].
*
* Checking this first is usually faster than checking `functionTypeService.getKindByClassNamePrefix` or a class cache.
*/
@FirSymbolProviderInternals
fun ClassId.mayBeSyntheticFunctionClassName(): Boolean = relativeClassName.asString().lastOrNull()?.isDigit() == true
}
}