[IR] Eliminated expensive calculating of fqNames (#3815)

This commit is contained in:
LepilkinaElena
2020-10-16 21:07:04 +03:00
committed by GitHub
parent 4f5b2b8e22
commit cc4d93ac71
7 changed files with 132 additions and 49 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irString import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.util.IdSignature
interface LoggingContext { interface LoggingContext {
var inVerbosePhase: Boolean var inVerbosePhase: Boolean
@@ -80,9 +80,10 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
// Suppress since it is used in native // Suppress since it is used in native
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
protected fun IrCall.isReturnIfSuspendedCall() = protected fun IrCall.isReturnIfSuspendedCall() =
symbol.owner.run { fqNameWhenAvailable == context.internalPackageFqn.child(Name.identifier("returnIfSuspended")) } symbol.isPublicApi && context.ir.symbols.returnIfSuspended.signature == symbol.signature
private fun tryTransformSuspendFunction(element: IrElement) = private fun tryTransformSuspendFunction(element: IrElement) =
if (element is IrSimpleFunction && element.isSuspend && element.modality != Modality.ABSTRACT) if (element is IrSimpleFunction && element.isSuspend && element.modality != Modality.ABSTRACT)
transformSuspendFunction(element, suspendLambdas[element]) transformSuspendFunction(element, suspendLambdas[element])
else null else null
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi2ir.PsiErrorBuilder import org.jetbrains.kotlin.psi2ir.PsiErrorBuilder
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -5,20 +5,60 @@
package org.jetbrains.kotlin.ir.types package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.hasEqualFqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
private fun IrType.isNotNullClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = false) @Suppress("ObjectPropertyName")
private fun IrType.isNullableClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = true) object IdSignatureValues {
@JvmField val any = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Any")
@JvmField val nothing = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Nothing")
@JvmField val unit = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Unit")
@JvmField val _boolean = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Boolean")
@JvmField val _char = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Char")
@JvmField val _byte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Byte")
@JvmField val _short = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Short")
@JvmField val _int = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Int")
@JvmField val _long = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Long")
@JvmField val _float = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Float")
@JvmField val _double = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Double")
@JvmField val number = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Number")
@JvmField val uByte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UByte")
@JvmField val uShort = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UShort")
@JvmField val uInt = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UInt")
@JvmField val uLong = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"ULong")
@JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"String")
@JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Array")
@JvmField val collection = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Collection")
@JvmField val kClass = getPublicSignature(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KClass")
@JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Comparable")
@JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"CharSequence")
@JvmField val iterable = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Iterable")
@JvmField val continuation = getPublicSignature(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE,"Continuation")
@JvmField val result = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Result")
@JvmField val sequence = IdSignature.PublicSignature("kotlin.sequences", "Sequence", null, 0)
}
private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean? = null): Boolean { private fun IrType.isNotNullClassType(signature: IdSignature.PublicSignature) = isClassType(signature, hasQuestionMark = false)
private fun IrType.isNullableClassType(signature: IdSignature.PublicSignature) = isClassType(signature, hasQuestionMark = true)
fun getPublicSignature(packageFqName: FqName, name: String) =
IdSignature.PublicSignature(packageFqName.asString(), name, null, 0)
private fun IrType.isClassType(signature: IdSignature.PublicSignature, hasQuestionMark: Boolean? = null): Boolean {
if (this !is IrSimpleType) return false if (this !is IrSimpleType) return false
if (hasQuestionMark != null && this.hasQuestionMark != hasQuestionMark) return false if (hasQuestionMark != null && this.hasQuestionMark != hasQuestionMark) return false
return classifier.isClassWithFqName(fqName) if (!classifier.isPublicApi || !classifier.signature.isPublic) return false
return signature == classifier.signature
} }
fun IrClassifierSymbol.isClassWithFqName(fqName: FqNameUnsafe): Boolean = fun IrClassifierSymbol.isClassWithFqName(fqName: FqNameUnsafe): Boolean =
@@ -29,55 +69,84 @@ private fun classFqNameEquals(symbol: IrClassSymbol, fqName: FqNameUnsafe): Bool
return classFqNameEquals(symbol.owner, fqName) return classFqNameEquals(symbol.owner, fqName)
} }
private val idSignatureToPrimitiveType: Map<IdSignature.PublicSignature, PrimitiveType> =
newHashMapWithExpectedSize<IdSignature.PublicSignature, PrimitiveType>(PrimitiveType.values().size).apply {
for (primitiveType in PrimitiveType.values()) {
this[getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, primitiveType.typeName.asString())] = primitiveType
}
}
val primitiveArrayTypesSignatures: Map<PrimitiveType, IdSignature.PublicSignature> =
newHashMapWithExpectedSize<PrimitiveType, IdSignature.PublicSignature>(PrimitiveType.values().size).apply {
for (primitiveType in PrimitiveType.values()) {
this[primitiveType] =
getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "${primitiveType.typeName.asString()}Array")
}
}
private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean = private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean =
declaration.name == fqName.shortName() && fqName == declaration.fqNameWhenAvailable?.toUnsafe() declaration.hasEqualFqName(fqName.toSafe())
fun IrType.isAny(): Boolean = isNotNullClassType(StandardNames.FqNames.any) fun IrType.isAny(): Boolean = isNotNullClassType(IdSignatureValues.any)
fun IrType.isNullableAny(): Boolean = isNullableClassType(StandardNames.FqNames.any) fun IrType.isNullableAny(): Boolean = isNullableClassType(IdSignatureValues.any)
fun IrType.isString(): Boolean = isNotNullClassType(StandardNames.FqNames.string) fun IrType.isString(): Boolean = isNotNullClassType(IdSignatureValues.string)
fun IrType.isNullableString(): Boolean = isNullableClassType(StandardNames.FqNames.string) fun IrType.isNullableString(): Boolean = isNullableClassType(IdSignatureValues.string)
fun IrType.isStringClassType(): Boolean = isClassType(StandardNames.FqNames.string) fun IrType.isStringClassType(): Boolean = isClassType(IdSignatureValues.string)
fun IrType.isArray(): Boolean = isNotNullClassType(StandardNames.FqNames.array) fun IrType.isArray(): Boolean = isNotNullClassType(IdSignatureValues.array)
fun IrType.isNullableArray(): Boolean = isNullableClassType(StandardNames.FqNames.array) fun IrType.isNullableArray(): Boolean = isNullableClassType(IdSignatureValues.array)
fun IrType.isCollection(): Boolean = isNotNullClassType(StandardNames.FqNames.collection.toUnsafe()) fun IrType.isCollection(): Boolean = isNotNullClassType(IdSignatureValues.collection)
fun IrType.isNothing(): Boolean = isNotNullClassType(StandardNames.FqNames.nothing) fun IrType.isNothing(): Boolean = isNotNullClassType(IdSignatureValues.nothing)
fun IrType.isKClass(): Boolean = isNotNullClassType(StandardNames.FqNames.kClass)
fun IrType.isPrimitiveType(): Boolean = StandardNames.FqNames.fqNameToPrimitiveType.keys.any { isNotNullClassType(it) } fun IrType.isPrimitiveType(hasQuestionMark: Boolean = false): Boolean =
fun IrType.isNullablePrimitiveType(): Boolean = StandardNames.FqNames.fqNameToPrimitiveType.keys.any { isNullableClassType(it) } (this is IrSimpleType && hasQuestionMark == this.hasQuestionMark) &&
classOrNull?.takeIf(IrClassSymbol::isPublicApi)?.signature in idSignatureToPrimitiveType
fun IrType.isNullablePrimitiveType(): Boolean = isPrimitiveType(true)
fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false
fun IrType.isUnit() = isNotNullClassType(StandardNames.FqNames.unit) fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit)
fun IrType.isBoolean(): Boolean = isNotNullClassType(StandardNames.FqNames._boolean) fun IrType.isBoolean(): Boolean = isNotNullClassType(IdSignatureValues._boolean)
fun IrType.isChar(): Boolean = isNotNullClassType(StandardNames.FqNames._char) fun IrType.isChar(): Boolean = isNotNullClassType(IdSignatureValues._char)
fun IrType.isByte(): Boolean = isNotNullClassType(StandardNames.FqNames._byte) fun IrType.isByte(): Boolean = isNotNullClassType(IdSignatureValues._byte)
fun IrType.isShort(): Boolean = isNotNullClassType(StandardNames.FqNames._short) fun IrType.isShort(): Boolean = isNotNullClassType(IdSignatureValues._short)
fun IrType.isInt(): Boolean = isNotNullClassType(StandardNames.FqNames._int) fun IrType.isInt(): Boolean = isNotNullClassType(IdSignatureValues._int)
fun IrType.isLong(): Boolean = isNotNullClassType(StandardNames.FqNames._long) fun IrType.isLong(): Boolean = isNotNullClassType(IdSignatureValues._long)
fun IrType.isUByte(): Boolean = isNotNullClassType(StandardNames.FqNames.uByteFqName.toUnsafe()) fun IrType.isUByte(): Boolean = isNotNullClassType(IdSignatureValues.uByte)
fun IrType.isUShort(): Boolean = isNotNullClassType(StandardNames.FqNames.uShortFqName.toUnsafe()) fun IrType.isUShort(): Boolean = isNotNullClassType(IdSignatureValues.uShort)
fun IrType.isUInt(): Boolean = isNotNullClassType(StandardNames.FqNames.uIntFqName.toUnsafe()) fun IrType.isUInt(): Boolean = isNotNullClassType(IdSignatureValues.uInt)
fun IrType.isULong(): Boolean = isNotNullClassType(StandardNames.FqNames.uLongFqName.toUnsafe()) fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong)
fun IrType.isFloat(): Boolean = isNotNullClassType(StandardNames.FqNames._float) fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float)
fun IrType.isDouble(): Boolean = isNotNullClassType(StandardNames.FqNames._double) fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double)
fun IrType.isNumber(): Boolean = isNotNullClassType(StandardNames.FqNames.number) fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number)
fun IrType.isComparable(): Boolean = isNotNullClassType(StandardNames.FqNames.comparable.toUnsafe()) fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable)
fun IrType.isCharSequence(): Boolean = isNotNullClassType(StandardNames.FqNames.charSequence) fun IrType.isCharSequence(): Boolean = isNotNullClassType(IdSignatureValues.charSequence)
fun IrType.isIterable(): Boolean = isNotNullClassType(StandardNames.FqNames.iterable.toUnsafe()) fun IrType.isIterable(): Boolean = isNotNullClassType(IdSignatureValues.iterable)
fun IrType.isSequence(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.sequences.Sequence")) fun IrType.isSequence(): Boolean = isNotNullClassType(IdSignatureValues.sequence)
fun IrType.isBooleanArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.BooleanArray")) fun IrType.isBooleanArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.BOOLEAN]!!)
fun IrType.isCharArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.CharArray")) fun IrType.isCharArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.CHAR]!!)
fun IrType.isByteArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.ByteArray")) fun IrType.isByteArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.BYTE]!!)
fun IrType.isShortArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.ShortArray")) fun IrType.isShortArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.SHORT]!!)
fun IrType.isIntArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.IntArray")) fun IrType.isIntArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.INT]!!)
fun IrType.isLongArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.LongArray")) fun IrType.isLongArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.LONG]!!)
fun IrType.isFloatArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.FloatArray")) fun IrType.isFloatArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.FLOAT]!!)
fun IrType.isDoubleArray(): Boolean = isNotNullClassType(FqNameUnsafe("kotlin.DoubleArray")) fun IrType.isDoubleArray(): Boolean = isNotNullClassType(primitiveArrayTypesSignatures[PrimitiveType.DOUBLE]!!)
fun IrType.isKotlinResult(): Boolean = isNotNullClassType(StandardNames.RESULT_FQ_NAME.toUnsafe()) // TODO: remove this method using FqNames.
fun IrType.isNullableContinuation(): Boolean = isNullableClassType(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.toUnsafe()) // Need to refactor declarationBuilders.kt: visibilty is known, need to add info about package in IrFactory.buildClass (similar to name).
fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
return classifier.isClassWithFqName(fqName)
}
fun IrType.isKotlinResult(): Boolean = isClassType(StandardNames.RESULT_FQ_NAME.toUnsafe(), false)
fun IrType.isNullableContinuation(): Boolean = isClassType(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.toUnsafe(), true)
// FIR and backend instances have different mask.
fun IrType.isKClass(): Boolean = isClassType(StandardNames.FqNames.kClass, false)
@@ -85,11 +85,21 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
private val IrConstructorCall.annotationClass private val IrConstructorCall.annotationClass
get() = this.symbol.owner.constructedClass get() = this.symbol.owner.constructedClass
val IrClass.packageFqName: FqName?
get() = if (symbol.isPublicApi) symbol.signature.packageFqName() else parent.getPackageFragment()?.fqName
fun IrDeclarationWithName.hasEqualFqName(fqName: FqName): Boolean =
name == fqName.shortName() && when (val parent = parent) {
is IrPackageFragment -> parent.fqName == fqName.parent()
is IrDeclarationWithName -> parent.hasEqualFqName(fqName.parent())
else -> false
}
fun List<IrConstructorCall>.hasAnnotation(fqName: FqName): Boolean = fun List<IrConstructorCall>.hasAnnotation(fqName: FqName): Boolean =
any { it.annotationClass.fqNameWhenAvailable == fqName } any { it.annotationClass.hasEqualFqName(fqName) }
fun List<IrConstructorCall>.findAnnotation(fqName: FqName): IrConstructorCall? = fun List<IrConstructorCall>.findAnnotation(fqName: FqName): IrConstructorCall? =
firstOrNull { it.annotationClass.fqNameWhenAvailable == fqName } firstOrNull { it.annotationClass.hasEqualFqName(fqName) }
val IrDeclaration.fileEntry: SourceManager.FileEntry val IrDeclaration.fileEntry: SourceManager.FileEntry
get() = parent.let { get() = parent.let {
@@ -285,7 +285,7 @@ fun IrAnnotationContainer.getAnnotation(name: FqName): IrConstructorCall? =
fun IrAnnotationContainer.hasAnnotation(name: FqName) = fun IrAnnotationContainer.hasAnnotation(name: FqName) =
annotations.any { annotations.any {
it.symbol.owner.parentAsClass.fqNameWhenAvailable == name it.symbol.owner.parentAsClass.hasEqualFqName(name)
} }
fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol) = fun IrAnnotationContainer.hasAnnotation(symbol: IrClassSymbol) =