IC mangling: Old JVM BE: Fallback to old mangling rules
if classfile does not contain functions mangled in the new way.
This commit is contained in:
@@ -2684,7 +2684,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
fd = ArgumentGeneratorKt.getFunctionWithDefaultArguments(fd);
|
||||
}
|
||||
|
||||
return typeMapper.mapToCallableMethod(fd, superCall, null, resolvedCall);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(fd, superCall, null, resolvedCall);
|
||||
|
||||
if (method.getAsmMethod().getName().contains("-")) {
|
||||
Boolean classFileContainsMethod =
|
||||
InlineClassesCodegenUtilKt.classFileContainsMethod(fd, state, method.getAsmMethod());
|
||||
if (classFileContainsMethod != null && !classFileContainsMethod) {
|
||||
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(true);
|
||||
method = typeMapper.mapToCallableMethod(fd, superCall, null, resolvedCall);
|
||||
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(false);
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
public void invokeMethodWithArguments(
|
||||
@@ -2900,6 +2912,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
sourceCompiler.initializeInlineFunctionContext(functionDescriptor);
|
||||
JvmMethodSignature signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
|
||||
if (signature.getAsmMethod().getName().contains("-")) {
|
||||
Boolean classFileContainsMethod =
|
||||
InlineClassesCodegenUtilKt.classFileContainsMethod(functionDescriptor, state, signature.getAsmMethod());
|
||||
if (classFileContainsMethod != null && !classFileContainsMethod) {
|
||||
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(true);
|
||||
signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
|
||||
typeMapper.setUseOldManglingRulesForFunctionAcceptingInlineClass(false);
|
||||
}
|
||||
}
|
||||
Type methodOwner = typeMapper.mapImplementationOwner(functionDescriptor);
|
||||
if (isDefaultCompilation) {
|
||||
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, methodOwner, signature, sourceCompiler);
|
||||
|
||||
@@ -5,15 +5,28 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.underlyingRepresentation
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
|
||||
fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean {
|
||||
if (!isInlineClassType()) return false
|
||||
@@ -26,4 +39,39 @@ fun CallableDescriptor.isGenericParameter(): Boolean {
|
||||
if (containingDeclaration is AnonymousFunctionDescriptor) return true
|
||||
val index = containingDeclaration.valueParameters.indexOf(this)
|
||||
return containingDeclaration.overriddenDescriptors.any { it.original.valueParameters[index].type.isTypeParameter() }
|
||||
}
|
||||
|
||||
fun classFileContainsMethod(descriptor: FunctionDescriptor, state: GenerationState, method: Method): Boolean? {
|
||||
if (descriptor !is DeserializedSimpleFunctionDescriptor) return null
|
||||
|
||||
val classId: ClassId = when {
|
||||
descriptor.containingDeclaration is DeserializedClassDescriptor -> {
|
||||
(descriptor.containingDeclaration as DeserializedClassDescriptor).classId ?: return null
|
||||
}
|
||||
descriptor.containerSource is JvmPackagePartSource -> {
|
||||
(descriptor.containerSource as JvmPackagePartSource).classId
|
||||
}
|
||||
else -> {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
val bytes = VirtualFileFinder.getInstance(state.project, state.module).findVirtualFileWithHeader(classId)
|
||||
?.contentsToByteArray() ?: return null
|
||||
var found = false
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String?,
|
||||
descriptor: String?,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? {
|
||||
if (name == method.name && descriptor == method.descriptor) {
|
||||
found = true
|
||||
}
|
||||
return super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
}
|
||||
}, ClassReader.SKIP_FRAMES)
|
||||
return found
|
||||
}
|
||||
@@ -91,6 +91,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
) : KotlinTypeMapperBase() {
|
||||
private val isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
|
||||
var useOldManglingRulesForFunctionAcceptingInlineClass: Boolean = false
|
||||
|
||||
private val typeMappingConfiguration = object : TypeMappingConfiguration<Type> {
|
||||
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
|
||||
@@ -636,7 +637,11 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
// so that we don't have to repeat the same logic in reflection
|
||||
// in case of properties without getter methods.
|
||||
if (kind !== OwnerKind.PROPERTY_REFERENCE_SIGNATURE || descriptor.isPropertyWithGetterSignaturePresent()) {
|
||||
val suffix = getManglingSuffixBasedOnKotlinSignature(descriptor, shouldMangleByReturnType)
|
||||
val suffix = getManglingSuffixBasedOnKotlinSignature(
|
||||
descriptor,
|
||||
shouldMangleByReturnType,
|
||||
useOldManglingRulesForFunctionAcceptingInlineClass
|
||||
)
|
||||
if (suffix != null) {
|
||||
newName += suffix
|
||||
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
|
||||
|
||||
+60
-26
@@ -5,7 +5,6 @@
|
||||
|
||||
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
|
||||
@@ -14,14 +13,14 @@ 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.*
|
||||
|
||||
fun getManglingSuffixBasedOnKotlinSignature(
|
||||
descriptor: CallableMemberDescriptor,
|
||||
shouldMangleByReturnType: Boolean
|
||||
shouldMangleByReturnType: Boolean,
|
||||
useOldManglingRules: Boolean
|
||||
): String? {
|
||||
if (descriptor !is FunctionDescriptor) return null
|
||||
if (descriptor is ConstructorDescriptor) return null
|
||||
@@ -33,41 +32,76 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
||||
|
||||
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||
|
||||
// If a function accepts inline class parameters, mangle its name.
|
||||
if (requiresFunctionNameManglingForParameterTypes(descriptor) ||
|
||||
(shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
||||
) {
|
||||
if (useOldManglingRules) {
|
||||
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
|
||||
return "-" + md5base64(collectSignatureForMangling(descriptor, useOldManglingRules))
|
||||
}
|
||||
|
||||
// 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)
|
||||
if (shouldMangleByReturnType) {
|
||||
if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
|
||||
return "-" + md5base64(
|
||||
":" + getSignatureElementForMangling(
|
||||
unwrappedDescriptor.returnType!!, useOldManglingRules
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 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, useOldManglingRules) +
|
||||
if (shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
||||
":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!, useOldManglingRules)
|
||||
else ""
|
||||
return "-" + md5base64(signature)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor): String {
|
||||
private fun collectSignatureForMangling(descriptor: CallableMemberDescriptor, useOldManglingRules: Boolean): String {
|
||||
val types = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||
return types.joinToString { getSignatureElementForMangling(it) }
|
||||
return types.joinToString { getSignatureElementForMangling(it, useOldManglingRules) }
|
||||
}
|
||||
|
||||
private fun getSignatureElementForMangling(type: KotlinType): String = buildString {
|
||||
private fun getSignatureElementForMangling(type: KotlinType, useOldManglingRules: Boolean): String = buildString {
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return ""
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> if (descriptor.isInline) {
|
||||
append('L')
|
||||
append(descriptor.fqNameUnsafe)
|
||||
if (type.isMarkedNullable) append('?')
|
||||
append(';')
|
||||
} else {
|
||||
append('x')
|
||||
}
|
||||
if (useOldManglingRules) {
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> {
|
||||
append('L')
|
||||
append(descriptor.fqNameUnsafe)
|
||||
if (type.isMarkedNullable) append('?')
|
||||
append(';')
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound))
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound, useOldManglingRules))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> if (descriptor.isInline) {
|
||||
append('L')
|
||||
append(descriptor.fqNameUnsafe)
|
||||
if (type.isMarkedNullable) append('?')
|
||||
append(';')
|
||||
} else {
|
||||
append('x')
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> {
|
||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound, useOldManglingRules))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user