JVM IR: link via descriptors instead of signatures by default
Doing so speeds up psi2ir ~2 times, and thus improves total compiler performance by about 6-8%. Unless JVM IR is in the mode where linking via signatures is the only way (-Xserialize-ir, -Xklib), signatures are actually not needed at all, SymbolTable can use the frontend representation (descriptors for FE1.0, and hopefully FIR elements for K2) as hash table keys. The only catch is that since other backends still need to work with signatures, all the common IR utilities, such as irTypePredicates.kt, need to work correctly for IR elements both with signatures and without. Also, introduce a fallback compiler flag -Xlink-via-signatures, in case something goes wrong, to be able to troubleshoot and workaround any issues. #KT-48233
This commit is contained in:
+11
-2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.DescriptorByIdSignatureFinderImpl
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getKtFile
|
||||
import org.jetbrains.kotlin.backend.jvm.serialization.DisabledIdSignatureDescriptor
|
||||
import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
|
||||
import org.jetbrains.kotlin.codegen.CodegenFactory
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
@@ -73,11 +74,18 @@ open class JvmIrCodegenFactory(
|
||||
) : CodegenFactory.CodegenInput
|
||||
|
||||
override fun convertToIr(input: CodegenFactory.IrConversionInput): JvmIrBackendInput {
|
||||
val enableIdSignatures =
|
||||
input.configuration.getBoolean(JVMConfigurationKeys.LINK_VIA_SIGNATURES) ||
|
||||
input.configuration[JVMConfigurationKeys.SERIALIZE_IR, JvmSerializeIrMode.NONE] != JvmSerializeIrMode.NONE ||
|
||||
input.configuration[JVMConfigurationKeys.KLIB_PATHS, emptyList()].isNotEmpty()
|
||||
val (mangler, symbolTable) =
|
||||
if (externalSymbolTable != null) externalMangler!! to externalSymbolTable
|
||||
else {
|
||||
val mangler = JvmDescriptorMangler(MainFunctionDetector(input.bindingContext, input.languageVersionSettings))
|
||||
val symbolTable = SymbolTable(JvmIdSignatureDescriptor(mangler), IrFactoryImpl)
|
||||
val signaturer =
|
||||
if (enableIdSignatures) JvmIdSignatureDescriptor(mangler)
|
||||
else DisabledIdSignatureDescriptor
|
||||
val symbolTable = SymbolTable(signaturer, IrFactoryImpl)
|
||||
mangler to symbolTable
|
||||
}
|
||||
val psi2ir = Psi2IrTranslator(input.languageVersionSettings, Psi2IrConfiguration(input.ignoreErrors))
|
||||
@@ -114,7 +122,8 @@ open class JvmIrCodegenFactory(
|
||||
symbolTable,
|
||||
frontEndContext,
|
||||
stubGenerator,
|
||||
mangler
|
||||
mangler,
|
||||
enableIdSignatures,
|
||||
)
|
||||
|
||||
val pluginContext by lazy {
|
||||
|
||||
+3
-6
@@ -121,7 +121,9 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
}
|
||||
|
||||
annotations =
|
||||
if (isMultifilePart) irFile.annotations.filterNot { it.symbol.owner.parentAsClass.symbol.signature == JVM_NAME }
|
||||
if (isMultifilePart) irFile.annotations.filterNot {
|
||||
it.symbol.owner.parentAsClass.hasEqualFqName(JvmFileClassUtil.JVM_NAME)
|
||||
}
|
||||
else irFile.annotations
|
||||
|
||||
metadata = irFile.metadata
|
||||
@@ -142,13 +144,8 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val JVM_NAME = IdSignature.CommonSignature("kotlin.jvm", "JvmName", null, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun IrFile.getFileClassInfo(): JvmFileClassInfo =
|
||||
when (val fileEntry = this.fileEntry) {
|
||||
is PsiIrFileEntry ->
|
||||
|
||||
+12
-12
@@ -24,12 +24,7 @@ import org.jetbrains.kotlin.ir.builders.irSetField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.copyWithOffsets
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -43,11 +38,16 @@ internal val jvmOptimizationLoweringPhase = makeIrFilePhase(
|
||||
)
|
||||
|
||||
class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
|
||||
companion object {
|
||||
fun isNegation(expression: IrExpression, context: JvmBackendContext): Boolean =
|
||||
expression is IrCall &&
|
||||
(expression.symbol as? IrPublicSymbolBase<*>)?.signature == context.irBuiltIns.booleanNotSymbol.signature
|
||||
private companion object {
|
||||
private fun isNegation(expression: IrExpression): Boolean =
|
||||
expression is IrCall && expression.symbol.owner.let { not ->
|
||||
not.name == OperatorNameConventions.NOT &&
|
||||
not.extensionReceiverParameter == null &&
|
||||
not.valueParameters.isEmpty() &&
|
||||
not.dispatchReceiverParameter.let { receiver ->
|
||||
receiver != null && receiver.type.isBoolean()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val IrFunction.isObjectEquals
|
||||
@@ -98,7 +98,7 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
return optimizePropertyAccess(expression, data)
|
||||
}
|
||||
|
||||
if (isNegation(expression, context) && isNegation(expression.dispatchReceiver!!, context)) {
|
||||
if (isNegation(expression) && isNegation(expression.dispatchReceiver!!)) {
|
||||
return (expression.dispatchReceiver as IrCall).dispatchReceiver!!
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -144,9 +145,10 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin
|
||||
copyAttributes(reference)
|
||||
|
||||
val function = reference.symbol.owner
|
||||
val isRestricted = reference.symbol.owner.extensionReceiverParameter?.type?.classOrNull?.owner?.annotations?.any {
|
||||
it.type.classOrNull?.signature == IdSignature.CommonSignature("kotlin.coroutines", "RestrictsSuspension", null, 0)
|
||||
} == true
|
||||
val extensionReceiver = function.extensionReceiverParameter?.type?.classOrNull
|
||||
val isRestricted = extensionReceiver != null && extensionReceiver.owner.annotations.any {
|
||||
it.type.classOrNull?.isClassWithFqName(FqNameUnsafe("kotlin.coroutines.RestrictsSuspension")) == true
|
||||
}
|
||||
val suspendLambda =
|
||||
if (isRestricted) context.ir.symbols.restrictedSuspendLambdaClass.owner
|
||||
else context.ir.symbols.suspendLambdaClass.owner
|
||||
|
||||
Reference in New Issue
Block a user