[IR] Reduce unnecessary allocations

This commit is contained in:
Evgeniy.Zhelenskiy
2023-08-25 02:48:48 +02:00
committed by Space Team
parent 0121686a7f
commit 6ede1bcf85
5 changed files with 52 additions and 20 deletions
@@ -138,11 +138,11 @@ public class JvmSignatureWriter extends JvmDescriptorTypeWriter<Type> {
@NotNull @NotNull
public JvmMethodGenericSignature makeJvmMethodSignature(@NotNull String name) { public JvmMethodGenericSignature makeJvmMethodSignature(@NotNull String name) {
List<Type> types = new ArrayList<>(kotlinParameterTypes.size()); Type[] types = new Type[kotlinParameterTypes.size()];
for (JvmMethodParameterSignature parameter : kotlinParameterTypes) { for (int i = 0; i < kotlinParameterTypes.size(); i++) {
types.add(parameter.getAsmType()); types[i] = kotlinParameterTypes.get(i).getAsmType();
} }
Method asmMethod = new Method(name, jvmReturnType, types.toArray(new Type[types.size()])); Method asmMethod = new Method(name, jvmReturnType, types);
return new JvmMethodGenericSignature(asmMethod, kotlinParameterTypes, makeJavaGenericSignature()); return new JvmMethodGenericSignature(asmMethod, kotlinParameterTypes, makeJavaGenericSignature());
} }
@@ -12,29 +12,40 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.Name
internal val uniqueLoopLabelsPhase = makeIrFilePhase( internal val uniqueLoopLabelsPhase = makeIrFilePhase(
::UniqueLoopLabelsLowering, { _: JvmBackendContext -> UniqueLoopLabelsLowering() },
name = "UniqueLoopLabels", name = "UniqueLoopLabels",
description = "Label all loops for non-local break/continue" description = "Label all loops for non-local break/continue"
) )
private class UniqueLoopLabelsLowering(val context: JvmBackendContext) : FileLoweringPass { private class UniqueLoopLabelsLowering : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.accept(object : IrElementVisitor<Unit, String> { irFile.acceptVoid(object : IrElementVisitorVoid {
// This counter is intentionally not local to every declaration because their names might clash. // This counter is intentionally not local to every declaration because their names might clash.
private var counter = 0 private var counter = 0
private val stack = ArrayList<Name>()
override fun visitElement(element: IrElement, data: String) = override fun visitElement(element: IrElement) {
element.acceptChildren(this, if (element is IrDeclarationWithName) "$data${element.name}$" else data) if (element is IrDeclarationWithName) {
stack.add(element.name)
element.acceptChildrenVoid(this)
stack.removeLast()
} else {
element.acceptChildrenVoid(this)
}
}
override fun visitLoop(loop: IrLoop, data: String) { override fun visitLoop(loop: IrLoop) {
// Give all loops unique labels so that we can generate unambiguous instructions for non-local // Give all loops unique labels so that we can generate unambiguous instructions for non-local
// `break`/`continue` statements. // `break`/`continue` statements.
loop.label = "$data${++counter}" loop.label = stack.joinToString("$", postfix = (++counter).toString())
super.visitLoop(loop, data) super.visitLoop(loop)
} }
}, "") })
} }
} }
@@ -35,9 +35,12 @@ class BridgeLoweringCache(private val context: JvmBackendContext) {
return true return true
// Function name could be mangled by inline class rules // Function name could be mangled by inline class rules
val functionName = function.name.asString() val functionName = function.name.asString()
if (specialBridgeMethods.specialMethodNames.any { functionName.startsWith(it.asString() + "-") }) return specialBridgeMethods.specialMethodNames.any {
return true // Optimized version of functionName.startsWith(it.asString() + "-") which is a hot spot
return false val specialMethodNameString = it.asString()
val specialMethodNameLength = specialMethodNameString.length
functionName.startsWith(specialMethodNameString) && functionName.length > specialMethodNameLength && functionName[specialMethodNameLength] == '-'
}
} }
fun computeSpecialBridge(function: IrSimpleFunction): SpecialBridge? { fun computeSpecialBridge(function: IrSimpleFunction): SpecialBridge? {
@@ -14,6 +14,7 @@ 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.IdSignature
import org.jetbrains.kotlin.ir.util.hasEqualFqName import org.jetbrains.kotlin.ir.util.hasEqualFqName
import org.jetbrains.kotlin.ir.util.hasTopLevelEqualFqName
import org.jetbrains.kotlin.name.FqName 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.name.Name
@@ -74,8 +75,7 @@ private fun IrType.isClassType(signature: IdSignature.CommonSignature, nullable:
} }
private fun IrClass.hasFqNameEqualToSignature(signature: IdSignature.CommonSignature): Boolean = private fun IrClass.hasFqNameEqualToSignature(signature: IdSignature.CommonSignature): Boolean =
name.asString() == signature.shortName && name.asString() == signature.shortName && hasTopLevelEqualFqName(signature.packageFqName, signature.declarationFqName)
hasEqualFqName(FqName("${signature.packageFqName}.${signature.declarationFqName}"))
fun IrClassifierSymbol.isClassWithFqName(fqName: FqNameUnsafe): Boolean = fun IrClassifierSymbol.isClassWithFqName(fqName: FqNameUnsafe): Boolean =
this is IrClassSymbol && classFqNameEquals(this, fqName) this is IrClassSymbol && classFqNameEquals(this, fqName)
@@ -146,9 +146,27 @@ fun IrDeclarationWithName.hasEqualFqName(fqName: FqName): Boolean =
else -> false else -> false
} }
fun IrDeclarationWithName.hasTopLevelEqualFqName(packageName: String, declarationName: String): Boolean =
symbol.hasTopLevelEqualFqName(packageName, declarationName) || name.asString() == declarationName && when (val parent = parent) {
is IrPackageFragment -> parent.packageFqName.asString() == packageName
else -> false
}
fun IrSymbol.hasEqualFqName(fqName: FqName): Boolean { fun IrSymbol.hasEqualFqName(fqName: FqName): Boolean {
return this is IrClassPublicSymbolImpl && with(signature as? IdSignature.CommonSignature ?: return false) { return this is IrClassPublicSymbolImpl && with(signature as? IdSignature.CommonSignature ?: return false) {
FqName("$packageFqName.$declarationFqName") == fqName // optimized version of FqName("$packageFqName.$declarationFqName") == fqName
val fqNameAsString = fqName.asString()
fqNameAsString.length == packageFqName.length + 1 + declarationFqName.length &&
fqNameAsString[packageFqName.length] == '.' &&
fqNameAsString.startsWith(packageFqName) &&
fqNameAsString.endsWith(declarationFqName)
}
}
private fun IrSymbol.hasTopLevelEqualFqName(packageName: String, declarationName: String): Boolean {
return this is IrClassPublicSymbolImpl && with(signature as? IdSignature.CommonSignature ?: return false) {
// optimized version of FqName("$packageFqName.$declarationFqName") == fqName
packageFqName == packageName && declarationFqName == declarationName
} }
} }