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:
Ilmir Usmanov
2020-11-03 01:05:52 +01:00
parent d21a01ef59
commit c62093f54c
42 changed files with 250 additions and 83 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -13,6 +14,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
import java.security.MessageDigest
import java.util.*
@@ -29,19 +31,20 @@ fun getManglingSuffixBasedOnKotlinSignature(
// Some stdlib functions ('Result.success', 'Result.failure') are annotated with '@JvmName' as a workaround for forward compatibility.
if (DescriptorUtils.hasJvmNameAnnotation(descriptor)) return null
// If a function accepts inline class parameters, mangle its name.
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
return "-" + md5base64(collectSignatureForMangling(descriptor))
}
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
// If a class member function returns inline class value, mangle its name.
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
// should unwrap it and take original return type instead.
if (shouldMangleByReturnType) {
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
return "-" + md5base64(":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!))
}
// If a function accepts inline class parameters, mangle its name.
if (requiresFunctionNameManglingForParameterTypes(descriptor) ||
(shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
) {
// If a class member function returns inline class value, mangle its name.
// NB here function can be a suspend function JVM view with return type replaced with 'Any',
// should unwrap it and take original return type instead.
val signature = collectSignatureForMangling(descriptor) +
if (shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!)
else ""
return "-" + md5base64(signature)
}
return null
}
@@ -54,11 +57,13 @@ private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor): S
private fun getSignatureElementForMangling(type: KotlinType): String = buildString {
val descriptor = type.constructor.declarationDescriptor ?: return ""
when (descriptor) {
is ClassDescriptor -> {
is ClassDescriptor -> if (descriptor.isInline) {
append('L')
append(descriptor.fqNameUnsafe)
if (type.isMarkedNullable) append('?')
append(';')
} else {
append('x')
}
is TypeParameterDescriptor -> {