IC mangling: JVM_IR: Fallback to old mangling rules
if classfile does not contain functions mangled in the new way.
This commit is contained in:
@@ -133,7 +133,7 @@ class JvmBackendContext(
|
||||
|
||||
val staticDefaultStubs = mutableMapOf<IrSimpleFunctionSymbol, IrSimpleFunction>()
|
||||
|
||||
val inlineClassReplacements = MemoizedInlineClassReplacements(state.functionsWithInlineClassReturnTypesMangled, irFactory)
|
||||
val inlineClassReplacements = MemoizedInlineClassReplacements(state.functionsWithInlineClassReturnTypesMangled, irFactory, this)
|
||||
|
||||
internal fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol =
|
||||
symbolTable.lazyWrapper.referenceClass(descriptor)
|
||||
|
||||
+11
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
|
||||
class IrFrameMap : FrameMapBase<IrSymbol>() {
|
||||
private val typeMap = mutableMapOf<IrSymbol, Type>()
|
||||
@@ -376,3 +377,13 @@ val IrMemberAccessExpression<*>.psiElement: PsiElement?
|
||||
|
||||
fun IrSimpleType.isRawType(): Boolean =
|
||||
hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME)
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal fun classFileContainsMethod(function: IrFunction, context: JvmBackendContext, name: String): Boolean? {
|
||||
val originalDescriptor = context.methodSignatureMapper.mapSignatureWithGeneric(function).asmMethod.descriptor
|
||||
val descriptor = if (function.isSuspend)
|
||||
listOf(*Type.getArgumentTypes(originalDescriptor), Type.getObjectType("kotlin/coroutines/Continuation"))
|
||||
.joinToString(prefix = "(", postfix = ")", separator = "") + AsmTypes.OBJECT_TYPE
|
||||
else originalDescriptor
|
||||
return classFileContainsMethod(function.descriptor, context.state, Method(name, descriptor))
|
||||
}
|
||||
|
||||
+1
-1
@@ -369,7 +369,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
name = if (samSuperType == null && callee.returnType.erasedUpperBound.isInline && context.state.functionsWithInlineClassReturnTypesMangled) {
|
||||
// For functions with inline class return type we need to mangle the invoke method.
|
||||
// Otherwise, bridge lowering may fail to generate bridges for inline class types erasing to Any.
|
||||
val suffix = InlineClassAbi.hashSuffix(callee, true)
|
||||
val suffix = InlineClassAbi.hashSuffix(callee, mangleReturnTypes = true, useOldMangleRules = false)
|
||||
Name.identifier("${superMethod.owner.name.asString()}-${suffix}")
|
||||
} else superMethod.owner.name
|
||||
returnType = callee.returnType
|
||||
|
||||
+47
-19
@@ -62,7 +62,7 @@ object InlineClassAbi {
|
||||
* Returns a mangled name for a function taking inline class arguments
|
||||
* to avoid clashes between overloaded methods.
|
||||
*/
|
||||
fun mangledNameFor(irFunction: IrFunction, mangleReturnTypes: Boolean): Name {
|
||||
fun mangledNameFor(irFunction: IrFunction, mangleReturnTypes: Boolean, useOldMangleRules: Boolean): Name {
|
||||
if (irFunction is IrConstructor) {
|
||||
// Note that we might drop this convention and use standard mangling for constructors too, see KT-37186.
|
||||
assert(irFunction.constructedClass.isInline) {
|
||||
@@ -71,14 +71,28 @@ object InlineClassAbi {
|
||||
return Name.identifier("constructor-impl")
|
||||
}
|
||||
|
||||
val suffix = when {
|
||||
irFunction.fullValueParameterList.any { it.type.requiresMangling } || (mangleReturnTypes && irFunction.hasMangledReturnType) ->
|
||||
hashSuffix(irFunction, mangleReturnTypes)
|
||||
(irFunction.parent as? IrClass)?.isInline == true &&
|
||||
irFunction.origin != IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||
"impl"
|
||||
else ->
|
||||
return irFunction.name
|
||||
val suffix = if (useOldMangleRules) {
|
||||
when {
|
||||
irFunction.fullValueParameterList.any { it.type.requiresMangling } ->
|
||||
hashSuffix(irFunction, false, useOldMangleRules)
|
||||
mangleReturnTypes && irFunction.hasMangledReturnType ->
|
||||
returnHashSuffix(irFunction)
|
||||
(irFunction.parent as? IrClass)?.isInline == true &&
|
||||
irFunction.origin != IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||
"impl"
|
||||
else ->
|
||||
return irFunction.name
|
||||
}
|
||||
} else {
|
||||
when {
|
||||
irFunction.fullValueParameterList.any { it.type.requiresMangling } || (mangleReturnTypes && irFunction.hasMangledReturnType) ->
|
||||
hashSuffix(irFunction, mangleReturnTypes, useOldMangleRules)
|
||||
(irFunction.parent as? IrClass)?.isInline == true &&
|
||||
irFunction.origin != IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
||||
"impl"
|
||||
else ->
|
||||
return irFunction.name
|
||||
}
|
||||
}
|
||||
|
||||
val base = when {
|
||||
@@ -98,26 +112,40 @@ object InlineClassAbi {
|
||||
private val IrFunction.propertyName: Name
|
||||
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.name
|
||||
|
||||
fun hashSuffix(irFunction: IrFunction, mangleReturnTypes: Boolean): String {
|
||||
fun hashSuffix(irFunction: IrFunction, mangleReturnTypes: Boolean, useOldMangleRules: Boolean): String {
|
||||
val signatureElementsForMangling =
|
||||
irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString() }
|
||||
irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString(useOldMangleRules) }
|
||||
if (irFunction.isSuspend) {
|
||||
// The JVM backend computes mangled names after creating suspend function views, but before default argument
|
||||
// stub insertion. It would be nice if this part of the continuation lowering happened earlier in the pipeline.
|
||||
// TODO: Move suspend function view creation before JvmInlineClassLowering.
|
||||
signatureElementsForMangling += "x"
|
||||
signatureElementsForMangling += if (useOldMangleRules) "Lkotlin.coroutines.Continuation;" else "x"
|
||||
}
|
||||
val signatureString = signatureElementsForMangling.joinToString() +
|
||||
if (mangleReturnTypes && irFunction.hasMangledReturnType) ":${irFunction.returnType.eraseToString()}" else ""
|
||||
if (mangleReturnTypes && irFunction.hasMangledReturnType && !useOldMangleRules)
|
||||
":${irFunction.returnType.eraseToString(useOldMangleRules)}" else ""
|
||||
return md5base64(signatureString)
|
||||
}
|
||||
|
||||
private fun IrType.eraseToString() = if (getClass()?.isInline == true) buildString {
|
||||
append('L')
|
||||
append(erasedUpperBound.fqNameWhenAvailable!!)
|
||||
if (isNullable()) append('?')
|
||||
append(';')
|
||||
} else "x"
|
||||
private fun returnHashSuffix(irFunction: IrFunction) =
|
||||
md5base64(":${irFunction.returnType.eraseToString(false)}")
|
||||
|
||||
private fun IrType.eraseToString(useOldMangleRules: Boolean) =
|
||||
if (useOldMangleRules) {
|
||||
buildString {
|
||||
append('L')
|
||||
append(erasedUpperBound.fqNameWhenAvailable!!)
|
||||
if (isNullable()) append('?')
|
||||
append(';')
|
||||
}
|
||||
} else {
|
||||
if (getClass()?.isInline == true) buildString {
|
||||
append('L')
|
||||
append(erasedUpperBound.fqNameWhenAvailable!!)
|
||||
if (isNullable()) append('?')
|
||||
append(';')
|
||||
} else "x"
|
||||
}
|
||||
}
|
||||
|
||||
internal val IrType.requiresMangling: Boolean
|
||||
|
||||
+11
-2
@@ -9,7 +9,9 @@ import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParameters
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
@@ -33,7 +35,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
/**
|
||||
* Keeps track of replacement functions and inline class box/unbox functions.
|
||||
*/
|
||||
class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean, private val irFactory: IrFactory) {
|
||||
class MemoizedInlineClassReplacements(
|
||||
private val mangleReturnTypes: Boolean,
|
||||
private val irFactory: IrFactory,
|
||||
private val context: JvmBackendContext
|
||||
) {
|
||||
private val storageManager = LockBasedStorageManager("inline-class-replacements")
|
||||
private val propertyMap = mutableMapOf<IrPropertySymbol, IrProperty>()
|
||||
|
||||
@@ -215,7 +221,10 @@ class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean, pr
|
||||
if (noFakeOverride) {
|
||||
isFakeOverride = false
|
||||
}
|
||||
name = mangledNameFor(function, mangleReturnTypes)
|
||||
name = mangledNameFor(function, mangleReturnTypes, false)
|
||||
if (name.asString().contains("-") && classFileContainsMethod(function, context, name.asString()) == false) {
|
||||
name = mangledNameFor(function, mangleReturnTypes, true)
|
||||
}
|
||||
returnType = function.returnType
|
||||
}.apply {
|
||||
parent = function.parent
|
||||
|
||||
Reference in New Issue
Block a user