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 staticDefaultStubs = mutableMapOf<IrSimpleFunctionSymbol, IrSimpleFunction>()
|
||||||
|
|
||||||
val inlineClassReplacements = MemoizedInlineClassReplacements(state.functionsWithInlineClassReturnTypesMangled, irFactory)
|
val inlineClassReplacements = MemoizedInlineClassReplacements(state.functionsWithInlineClassReturnTypesMangled, irFactory, this)
|
||||||
|
|
||||||
internal fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol =
|
internal fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol =
|
||||||
symbolTable.lazyWrapper.referenceClass(descriptor)
|
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.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
|
|
||||||
class IrFrameMap : FrameMapBase<IrSymbol>() {
|
class IrFrameMap : FrameMapBase<IrSymbol>() {
|
||||||
private val typeMap = mutableMapOf<IrSymbol, Type>()
|
private val typeMap = mutableMapOf<IrSymbol, Type>()
|
||||||
@@ -376,3 +377,13 @@ val IrMemberAccessExpression<*>.psiElement: PsiElement?
|
|||||||
|
|
||||||
fun IrSimpleType.isRawType(): Boolean =
|
fun IrSimpleType.isRawType(): Boolean =
|
||||||
hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME)
|
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) {
|
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.
|
// 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.
|
// 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}")
|
Name.identifier("${superMethod.owner.name.asString()}-${suffix}")
|
||||||
} else superMethod.owner.name
|
} else superMethod.owner.name
|
||||||
returnType = callee.returnType
|
returnType = callee.returnType
|
||||||
|
|||||||
+47
-19
@@ -62,7 +62,7 @@ object InlineClassAbi {
|
|||||||
* Returns a mangled name for a function taking inline class arguments
|
* Returns a mangled name for a function taking inline class arguments
|
||||||
* to avoid clashes between overloaded methods.
|
* 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) {
|
if (irFunction is IrConstructor) {
|
||||||
// Note that we might drop this convention and use standard mangling for constructors too, see KT-37186.
|
// Note that we might drop this convention and use standard mangling for constructors too, see KT-37186.
|
||||||
assert(irFunction.constructedClass.isInline) {
|
assert(irFunction.constructedClass.isInline) {
|
||||||
@@ -71,14 +71,28 @@ object InlineClassAbi {
|
|||||||
return Name.identifier("constructor-impl")
|
return Name.identifier("constructor-impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
val suffix = when {
|
val suffix = if (useOldMangleRules) {
|
||||||
irFunction.fullValueParameterList.any { it.type.requiresMangling } || (mangleReturnTypes && irFunction.hasMangledReturnType) ->
|
when {
|
||||||
hashSuffix(irFunction, mangleReturnTypes)
|
irFunction.fullValueParameterList.any { it.type.requiresMangling } ->
|
||||||
(irFunction.parent as? IrClass)?.isInline == true &&
|
hashSuffix(irFunction, false, useOldMangleRules)
|
||||||
irFunction.origin != IrDeclarationOrigin.IR_BUILTINS_STUB ->
|
mangleReturnTypes && irFunction.hasMangledReturnType ->
|
||||||
"impl"
|
returnHashSuffix(irFunction)
|
||||||
else ->
|
(irFunction.parent as? IrClass)?.isInline == true &&
|
||||||
return irFunction.name
|
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 {
|
val base = when {
|
||||||
@@ -98,26 +112,40 @@ object InlineClassAbi {
|
|||||||
private val IrFunction.propertyName: Name
|
private val IrFunction.propertyName: Name
|
||||||
get() = (this as IrSimpleFunction).correspondingPropertySymbol!!.owner.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 =
|
val signatureElementsForMangling =
|
||||||
irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString() }
|
irFunction.fullValueParameterList.mapTo(mutableListOf()) { it.type.eraseToString(useOldMangleRules) }
|
||||||
if (irFunction.isSuspend) {
|
if (irFunction.isSuspend) {
|
||||||
// The JVM backend computes mangled names after creating suspend function views, but before default argument
|
// 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.
|
// 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.
|
// TODO: Move suspend function view creation before JvmInlineClassLowering.
|
||||||
signatureElementsForMangling += "x"
|
signatureElementsForMangling += if (useOldMangleRules) "Lkotlin.coroutines.Continuation;" else "x"
|
||||||
}
|
}
|
||||||
val signatureString = signatureElementsForMangling.joinToString() +
|
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)
|
return md5base64(signatureString)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrType.eraseToString() = if (getClass()?.isInline == true) buildString {
|
private fun returnHashSuffix(irFunction: IrFunction) =
|
||||||
append('L')
|
md5base64(":${irFunction.returnType.eraseToString(false)}")
|
||||||
append(erasedUpperBound.fqNameWhenAvailable!!)
|
|
||||||
if (isNullable()) append('?')
|
private fun IrType.eraseToString(useOldMangleRules: Boolean) =
|
||||||
append(';')
|
if (useOldMangleRules) {
|
||||||
} else "x"
|
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
|
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.copyTypeParameters
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
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.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
|
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
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.
|
* 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 storageManager = LockBasedStorageManager("inline-class-replacements")
|
||||||
private val propertyMap = mutableMapOf<IrPropertySymbol, IrProperty>()
|
private val propertyMap = mutableMapOf<IrPropertySymbol, IrProperty>()
|
||||||
|
|
||||||
@@ -215,7 +221,10 @@ class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean, pr
|
|||||||
if (noFakeOverride) {
|
if (noFakeOverride) {
|
||||||
isFakeOverride = false
|
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
|
returnType = function.returnType
|
||||||
}.apply {
|
}.apply {
|
||||||
parent = function.parent
|
parent = function.parent
|
||||||
|
|||||||
Reference in New Issue
Block a user