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);
|
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(
|
public void invokeMethodWithArguments(
|
||||||
@@ -2900,6 +2912,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
sourceCompiler.initializeInlineFunctionContext(functionDescriptor);
|
sourceCompiler.initializeInlineFunctionContext(functionDescriptor);
|
||||||
JvmMethodSignature signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
|
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);
|
Type methodOwner = typeMapper.mapImplementationOwner(functionDescriptor);
|
||||||
if (isDefaultCompilation) {
|
if (isDefaultCompilation) {
|
||||||
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, methodOwner, signature, sourceCompiler);
|
return new InlineCodegenForDefaultBody(functionDescriptor, this, state, methodOwner, signature, sourceCompiler);
|
||||||
|
|||||||
@@ -5,15 +5,28 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
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.isInlineClassType
|
||||||
import org.jetbrains.kotlin.resolve.underlyingRepresentation
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
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 {
|
fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean {
|
||||||
if (!isInlineClassType()) return false
|
if (!isInlineClassType()) return false
|
||||||
@@ -27,3 +40,38 @@ fun CallableDescriptor.isGenericParameter(): Boolean {
|
|||||||
val index = containingDeclaration.valueParameters.indexOf(this)
|
val index = containingDeclaration.valueParameters.indexOf(this)
|
||||||
return containingDeclaration.overriddenDescriptors.any { it.original.valueParameters[index].type.isTypeParameter() }
|
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() {
|
) : KotlinTypeMapperBase() {
|
||||||
private val isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
private val isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||||
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
|
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
|
||||||
|
var useOldManglingRulesForFunctionAcceptingInlineClass: Boolean = false
|
||||||
|
|
||||||
private val typeMappingConfiguration = object : TypeMappingConfiguration<Type> {
|
private val typeMappingConfiguration = object : TypeMappingConfiguration<Type> {
|
||||||
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
|
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
|
// so that we don't have to repeat the same logic in reflection
|
||||||
// in case of properties without getter methods.
|
// in case of properties without getter methods.
|
||||||
if (kind !== OwnerKind.PROPERTY_REFERENCE_SIGNATURE || descriptor.isPropertyWithGetterSignaturePresent()) {
|
if (kind !== OwnerKind.PROPERTY_REFERENCE_SIGNATURE || descriptor.isPropertyWithGetterSignaturePresent()) {
|
||||||
val suffix = getManglingSuffixBasedOnKotlinSignature(descriptor, shouldMangleByReturnType)
|
val suffix = getManglingSuffixBasedOnKotlinSignature(
|
||||||
|
descriptor,
|
||||||
|
shouldMangleByReturnType,
|
||||||
|
useOldManglingRulesForFunctionAcceptingInlineClass
|
||||||
|
)
|
||||||
if (suffix != null) {
|
if (suffix != null) {
|
||||||
newName += suffix
|
newName += suffix
|
||||||
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
|
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
|
||||||
|
|||||||
+60
-26
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.state
|
package org.jetbrains.kotlin.codegen.state
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
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.requiresFunctionNameManglingForParameterTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun getManglingSuffixBasedOnKotlinSignature(
|
fun getManglingSuffixBasedOnKotlinSignature(
|
||||||
descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
shouldMangleByReturnType: Boolean
|
shouldMangleByReturnType: Boolean,
|
||||||
|
useOldManglingRules: Boolean
|
||||||
): String? {
|
): String? {
|
||||||
if (descriptor !is FunctionDescriptor) return null
|
if (descriptor !is FunctionDescriptor) return null
|
||||||
if (descriptor is ConstructorDescriptor) return null
|
if (descriptor is ConstructorDescriptor) return null
|
||||||
@@ -33,41 +32,76 @@ fun getManglingSuffixBasedOnKotlinSignature(
|
|||||||
|
|
||||||
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
|
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||||
|
|
||||||
// If a function accepts inline class parameters, mangle its name.
|
if (useOldManglingRules) {
|
||||||
if (requiresFunctionNameManglingForParameterTypes(descriptor) ||
|
if (requiresFunctionNameManglingForParameterTypes(descriptor)) {
|
||||||
(shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
return "-" + md5base64(collectSignatureForMangling(descriptor, useOldManglingRules))
|
||||||
) {
|
}
|
||||||
|
|
||||||
// If a class member function returns inline class value, mangle its name.
|
// 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',
|
// 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.
|
// should unwrap it and take original return type instead.
|
||||||
val signature = collectSignatureForMangling(descriptor) +
|
if (shouldMangleByReturnType) {
|
||||||
if (shouldMangleByReturnType && requiresFunctionNameManglingForReturnType(unwrappedDescriptor))
|
if (requiresFunctionNameManglingForReturnType(unwrappedDescriptor)) {
|
||||||
":" + getSignatureElementForMangling(unwrappedDescriptor.returnType!!)
|
return "-" + md5base64(
|
||||||
else ""
|
":" + getSignatureElementForMangling(
|
||||||
return "-" + md5base64(signature)
|
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
|
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 }
|
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 ""
|
val descriptor = type.constructor.declarationDescriptor ?: return ""
|
||||||
when (descriptor) {
|
if (useOldManglingRules) {
|
||||||
is ClassDescriptor -> if (descriptor.isInline) {
|
when (descriptor) {
|
||||||
append('L')
|
is ClassDescriptor -> {
|
||||||
append(descriptor.fqNameUnsafe)
|
append('L')
|
||||||
if (type.isMarkedNullable) append('?')
|
append(descriptor.fqNameUnsafe)
|
||||||
append(';')
|
if (type.isMarkedNullable) append('?')
|
||||||
} else {
|
append(';')
|
||||||
append('x')
|
}
|
||||||
}
|
|
||||||
|
|
||||||
is TypeParameterDescriptor -> {
|
is TypeParameterDescriptor -> {
|
||||||
append(getSignatureElementForMangling(descriptor.representativeUpperBound))
|
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