From 059046a2b1dc9ff352ebe09d222ddc1dca6272ef Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 29 Aug 2023 23:44:17 +0600 Subject: [PATCH] [JVM] Micro-optimize method signature mapping This commit optimizes functions related to method signature mapping on the JVM backend. The most significant change is avoiding re-allocations in StringBuilder when building internal names. The commit also includes minor optimizations, such as removing redundant allocations of strings and other objects. --- .../kotlin/types/AbstractTypeMapper.kt | 12 ++++++-- .../jetbrains/kotlin/codegen/codegenUtil.kt | 2 +- .../backend/jvm/mapping/IrTypeMapper.kt | 30 ++++++++++++++----- .../jvm/mapping/MethodSignatureMapper.kt | 19 +++++++----- .../load/java/SpecialGenericSignatures.kt | 2 +- .../kotlin/SignatureBuildingComponents.kt | 2 +- .../load/kotlin/typeSignatureMapping.kt | 2 +- .../kotlin/resolve/jvm/JvmClassName.java | 9 ++++-- .../load/kotlin/methodSignatureMapping.kt | 2 +- .../kotlin/utils/capitalizeDecapitalize.kt | 5 +++- 10 files changed, 58 insertions(+), 27 deletions(-) diff --git a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt index a244a89afbb..99e2a7e0904 100644 --- a/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt +++ b/compiler/backend.common.jvm/src/org/jetbrains/kotlin/types/AbstractTypeMapper.kt @@ -151,9 +151,15 @@ object AbstractTypeMapper { materialized: Boolean ): Type { val typeArgument = type.asArgumentList()[0] - val (variance, memberType) = when { - typeArgument.isStarProjection() -> Variance.OUT_VARIANCE to nullableAnyType() - else -> typeArgument.getVariance().toVariance() to typeArgument.getType() + val variance: Variance + val memberType: KotlinTypeMarker + + if (typeArgument.isStarProjection()) { + variance = Variance.OUT_VARIANCE + memberType = nullableAnyType() + } else { + variance = typeArgument.getVariance().toVariance() + memberType = typeArgument.getType() } val arrayElementType: Type diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index 1b053ea3ba7..307d207bd18 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -317,7 +317,7 @@ val CallableDescriptor.arity: Int (if (extensionReceiverParameter != null) 1 else 0) + (if (dispatchReceiverParameter != null) 1 else 0) -fun FqName.topLevelClassInternalName() = JvmClassName.byClassId(ClassId(parent(), shortName())).internalName +fun FqName.topLevelClassInternalName() = JvmClassName.internalNameByClassId(ClassId(parent(), shortName())) fun FqName.topLevelClassAsmType(): Type = Type.getObjectType(topLevelClassInternalName()) fun initializeVariablesForDestructuredLambdaParameters(codegen: ExpressionCodegen, valueParameters: List, endLabel: Label?) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/IrTypeMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/IrTypeMapper.kt index abf94768dcf..0bb0bd5b537 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/IrTypeMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/IrTypeMapper.kt @@ -55,7 +55,15 @@ open class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapp override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type = mapType(type as IrType, mode) - private fun computeClassInternalName(irClass: IrClass): StringBuilder { + private fun computeClassInternalNameAsString(irClass: IrClass): String { + context.getLocalClassType(irClass)?.internalName?.let { + return it + } + + return computeClassInternalName(irClass, 0).toString() + } + + private fun computeClassInternalName(irClass: IrClass, capacity: Int): StringBuilder { context.getLocalClassType(irClass)?.internalName?.let { return StringBuilder(it) } @@ -63,20 +71,26 @@ open class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapp val shortName = SpecialNames.safeIdentifier(irClass.name).identifier when (val parent = irClass.parent) { - is IrPackageFragment -> - return StringBuilder().apply { - val fqName = parent.packageFqName + is IrPackageFragment -> { + val fqName = parent.packageFqName + var ourCapacity = shortName.length + if (!fqName.isRoot) { + ourCapacity += fqName.asString().length + 1 + } + return StringBuilder(ourCapacity + capacity).apply { if (!fqName.isRoot) { append(fqName.asString().replace('.', '/')).append("/") } append(shortName) } + } is IrClass -> - return computeClassInternalName(parent).append("$").append(shortName) + return computeClassInternalName(parent, 1 + shortName.length).append("$").append(shortName) is IrFunction -> if (parent.isSuspend && parent.parentAsClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) { - return computeClassInternalName(parent.parentAsClass.parentAsClass) - .append("$").append(parent.name.asString()) + val parentName = parent.name.asString() + return computeClassInternalName(parent.parentAsClass.parentAsClass, 1 + parentName.length) + .append("$").append(parentName) } } @@ -92,7 +106,7 @@ open class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapp context.classNameOverride[irClass]?.let { return it.internalName } return JvmCodegenUtil.sanitizeNameIfNeeded( - computeClassInternalName(irClass).toString(), + computeClassInternalNameAsString(irClass), context.state.languageVersionSettings ) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/MethodSignatureMapper.kt index 82df40c043b..7914c201101 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/mapping/MethodSignatureMapper.kt @@ -79,7 +79,12 @@ class MethodSignatureMapper(private val context: JvmBackendContext, private val if (property != null) { val propertyName = property.name.asString() val propertyParent = property.parentAsClass - if (propertyParent.isAnnotationClass || propertyParent.superTypes.any { it.isJavaLangRecord() }) return propertyName + + if (propertyParent.isAnnotationClass) return propertyName + + for (i in propertyParent.superTypes.indices) { + if (propertyParent.superTypes[i].isJavaLangRecord()) return propertyName + } // The enum property getters and have special names which also // apply to their fake overrides. Unfortunately, getJvmMethodNameIfSpecial does not handle @@ -248,8 +253,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext, private val sw.writeParametersStart() - val contextReceivers = function.valueParameters.subList(0, function.contextReceiverParametersCount) - for (contextReceiver in contextReceivers) { + for (i in 0 until function.contextReceiverParametersCount) { + val contextReceiver = function.valueParameters[i] writeParameter(sw, JvmMethodParameterKind.CONTEXT_RECEIVER, contextReceiver.type, function) } @@ -258,9 +263,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext, private val writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function) } - val regularValueParameters = - function.valueParameters.subList(function.contextReceiverParametersCount, function.valueParameters.size) - for (parameter in regularValueParameters) { + for (i in function.contextReceiverParametersCount until function.valueParameters.size) { + val parameter = function.valueParameters[i] val kind = when (parameter.origin) { JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS -> JvmMethodParameterKind.OUTER JvmLoweredDeclarationOrigin.ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER -> JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL @@ -468,11 +472,10 @@ class MethodSignatureMapper(private val context: JvmBackendContext, private val if (!isBuiltIn) return null return allOverridden(includeSelf = true) .filter { it.isBuiltIn } - .mapNotNull { + .firstNotNullOfOrNull { val signature = it.computeJvmSignature() SpecialGenericSignatures.SIGNATURE_TO_JVM_REPRESENTATION_NAME[signature]?.asString() } - .firstOrNull() } private fun IrSimpleFunction.getBuiltinSpecialPropertyGetterName(): String? { diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/SpecialGenericSignatures.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/SpecialGenericSignatures.kt index 2028483663b..86639a1982f 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/SpecialGenericSignatures.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/SpecialGenericSignatures.kt @@ -134,7 +134,7 @@ open class SpecialGenericSignatures { signatureAndName.copy(name = jdkName).signature } - val ORIGINAL_SHORT_NAMES: List = NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.keys.map { it.name } + val ORIGINAL_SHORT_NAMES: Set = NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.keys.mapTo(HashSet()) { it.name } val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map = NAME_AND_SIGNATURE_TO_JVM_REPRESENTATION_NAME_MAP.entries diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/SignatureBuildingComponents.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/SignatureBuildingComponents.kt index eeb2dc8bd9e..bef1cd3aee3 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/SignatureBuildingComponents.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/SignatureBuildingComponents.kt @@ -34,5 +34,5 @@ object SignatureBuildingComponents { val ClassId.internalName: String get() { - return JvmClassName.byClassId(JavaToKotlinClassMap.mapKotlinToJava(asSingleFqName().toUnsafe()) ?: this).internalName + return JvmClassName.internalNameByClassId(JavaToKotlinClassMap.mapKotlinToJava(asSingleFqName().toUnsafe()) ?: this) } diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index 286f80c3ee2..ed07677d20f 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -55,7 +55,7 @@ fun TypeSystemCommonBackendContext.mapBuiltInType( if (!mode.kotlinCollectionsToJavaCollections && JavaToKotlinClassMap.mutabilityMappings.any { it.javaClass == classId }) return null - return typeFactory.createObjectType(JvmClassName.byClassId(classId).internalName) + return typeFactory.createObjectType(JvmClassName.internalNameByClassId(classId)) } } diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java b/core/compiler.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java index 359e7f4b9e5..3b3b9a1dd67 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/JvmClassName.java @@ -28,11 +28,16 @@ public class JvmClassName { @NotNull public static JvmClassName byClassId(@NotNull ClassId classId) { + return new JvmClassName(internalNameByClassId(classId)); + } + + @NotNull + public static String internalNameByClassId(@NotNull ClassId classId) { FqName packageFqName = classId.getPackageFqName(); String relativeClassName = classId.getRelativeClassName().asString().replace('.', '$'); return packageFqName.isRoot() - ? new JvmClassName(relativeClassName) - : new JvmClassName(packageFqName.asString().replace('.', '/') + "/" + relativeClassName); + ? relativeClassName + : packageFqName.asString().replace('.', '/') + "/" + relativeClassName; } /** diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt index bd64253c3cf..d5ffd2de23b 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/methodSignatureMapping.kt @@ -93,7 +93,7 @@ internal fun CallableDescriptor.computeJvmSignature(): String? = signatures { internal val ClassDescriptor.internalName: String get() { JavaToKotlinClassMap.mapKotlinToJava(fqNameSafe.toUnsafe())?.let { - return JvmClassName.byClassId(it).internalName + return JvmClassName.internalNameByClassId(it) } return computeInternalName(this) diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/capitalizeDecapitalize.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/capitalizeDecapitalize.kt index a1275021f3f..9c9d1d3e35f 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/capitalizeDecapitalize.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/capitalizeDecapitalize.kt @@ -109,7 +109,10 @@ fun String.capitalizeAsciiOnly(): String { if (isEmpty()) return this val c = this[0] return if (c in 'a'..'z') - c.uppercaseChar() + substring(1) + buildString(length) { + append(c.uppercaseChar()) + append(this@capitalizeAsciiOnly, 1, this@capitalizeAsciiOnly.length) + } else this }