IC mangling: Change mangling rules
1. Use 'x' for each parameter, which is not an inline class, every possible clash is handled by signature rather than name. This change makes more API changes binary-compatible. So, the changes are in line with the vision of inline classes are value classes, like primitives. 2. Take return type into account when mangling a function if the return type is inline class. Otherwise, boxing bridge will not be generated, which leads to CCE at runtime.
This commit is contained in:
+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.returnHashSuffix(callee)
|
||||
val suffix = InlineClassAbi.hashSuffix(callee, true)
|
||||
Name.identifier("${superMethod.owner.name.asString()}-${suffix}")
|
||||
} else superMethod.owner.name
|
||||
returnType = callee.returnType
|
||||
|
||||
+9
-12
@@ -72,10 +72,8 @@ object InlineClassAbi {
|
||||
}
|
||||
|
||||
val suffix = when {
|
||||
irFunction.fullValueParameterList.any { it.type.requiresMangling } ->
|
||||
hashSuffix(irFunction)
|
||||
mangleReturnTypes && irFunction.hasMangledReturnType ->
|
||||
returnHashSuffix(irFunction)
|
||||
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"
|
||||
@@ -100,27 +98,26 @@ object InlineClassAbi {
|
||||
private val IrFunction.propertyName: Name
|
||||
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.name
|
||||
|
||||
fun returnHashSuffix(irFunction: IrFunction) =
|
||||
md5base64(":${irFunction.returnType.eraseToString()}")
|
||||
|
||||
private fun hashSuffix(irFunction: IrFunction): String {
|
||||
fun hashSuffix(irFunction: IrFunction, mangleReturnTypes: Boolean): String {
|
||||
val signatureElementsForMangling =
|
||||
irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString() }
|
||||
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 += "Lkotlin.coroutines.Continuation;"
|
||||
signatureElementsForMangling += "x"
|
||||
}
|
||||
return md5base64(signatureElementsForMangling.joinToString())
|
||||
val signatureString = signatureElementsForMangling.joinToString() +
|
||||
if (mangleReturnTypes && irFunction.hasMangledReturnType) ":${irFunction.returnType.eraseToString()}" else ""
|
||||
return md5base64(signatureString)
|
||||
}
|
||||
|
||||
private fun IrType.eraseToString() = buildString {
|
||||
private fun IrType.eraseToString() = if (getClass()?.isInline == true) buildString {
|
||||
append('L')
|
||||
append(erasedUpperBound.fqNameWhenAvailable!!)
|
||||
if (isNullable()) append('?')
|
||||
append(';')
|
||||
}
|
||||
} else "x"
|
||||
}
|
||||
|
||||
internal val IrType.requiresMangling: Boolean
|
||||
|
||||
Reference in New Issue
Block a user