JVM IR: implement MethodSignatureMapper.mapSignature directly
As well as mapFieldSignature, mapReturnType, mapAsmMethod and smaller methods. This removes yet another dependency on KotlinTypeMapper in the IR backend.
This commit is contained in:
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -73,15 +72,18 @@ val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean
|
||||
get() {
|
||||
if (this !is CallableMemberDescriptor) return false
|
||||
return original.firstOverridden(useOriginal = true) {
|
||||
METHODS_WITH_DECLARATION_SITE_WILDCARDS.contains(it.propertyIfAccessor.fqNameOrNull())
|
||||
it.propertyIfAccessor.fqNameOrNull().isMethodWithDeclarationSiteWildcardsFqName
|
||||
} != null
|
||||
}
|
||||
|
||||
val FqName?.isMethodWithDeclarationSiteWildcardsFqName: Boolean
|
||||
get() = this in METHODS_WITH_DECLARATION_SITE_WILDCARDS
|
||||
|
||||
private fun FqName.child(name: String): FqName = child(Name.identifier(name))
|
||||
private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf(
|
||||
BUILTIN_NAMES.mutableCollection.child("addAll"),
|
||||
BUILTIN_NAMES.mutableList.child("addAll"),
|
||||
BUILTIN_NAMES.mutableMap.child("putAll")
|
||||
BUILTIN_NAMES.mutableCollection.child("addAll"),
|
||||
BUILTIN_NAMES.mutableList.child("addAll"),
|
||||
BUILTIN_NAMES.mutableMap.child("putAll")
|
||||
)
|
||||
|
||||
fun TypeMappingMode.updateArgumentModeFromAnnotations(
|
||||
@@ -108,25 +110,35 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations(
|
||||
}
|
||||
|
||||
internal fun extractTypeMappingModeFromAnnotation(
|
||||
callableDescriptor: CallableDescriptor?,
|
||||
outerType: KotlinType,
|
||||
isForAnnotationParameter: Boolean
|
||||
callableDescriptor: CallableDescriptor?,
|
||||
outerType: KotlinType,
|
||||
isForAnnotationParameter: Boolean
|
||||
): TypeMappingMode? =
|
||||
(outerType.suppressWildcardsMode(SimpleClassicTypeSystemContext) ?: callableDescriptor?.suppressWildcardsMode())?.let {
|
||||
if (outerType.arguments.isNotEmpty())
|
||||
TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards = it,
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
needInlineClassWrapping = !outerType.isInlineClassType()
|
||||
)
|
||||
else
|
||||
TypeMappingMode.DEFAULT
|
||||
}
|
||||
SimpleClassicTypeSystemContext.extractTypeMappingModeFromAnnotation(
|
||||
callableDescriptor?.suppressWildcardsMode(), outerType, isForAnnotationParameter
|
||||
)
|
||||
|
||||
fun TypeSystemCommonBackendContext.extractTypeMappingModeFromAnnotation(
|
||||
callableSuppressWildcardsMode: Boolean?,
|
||||
outerType: KotlinTypeMarker,
|
||||
isForAnnotationParameter: Boolean
|
||||
): TypeMappingMode? {
|
||||
val suppressWildcards =
|
||||
outerType.suppressWildcardsMode(this) ?: callableSuppressWildcardsMode ?: return null
|
||||
|
||||
if (outerType.argumentsCount() == 0) return TypeMappingMode.DEFAULT
|
||||
|
||||
return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode(
|
||||
skipDeclarationSiteWildcards = suppressWildcards,
|
||||
isForAnnotationParameter = isForAnnotationParameter,
|
||||
needInlineClassWrapping = !outerType.typeConstructor().isInlineClass()
|
||||
)
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.suppressWildcardsMode(): Boolean? =
|
||||
parentsWithSelf.mapNotNull {
|
||||
it.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)
|
||||
}.firstOrNull()?.suppressWildcardsMode()
|
||||
parentsWithSelf.mapNotNull {
|
||||
it.annotations.findAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)
|
||||
}.firstOrNull()?.suppressWildcardsMode()
|
||||
|
||||
private fun KotlinTypeMarker.suppressWildcardsMode(typeSystem: TypeSystemCommonBackendContext): Boolean? =
|
||||
with(typeSystem) {
|
||||
|
||||
+182
-18
@@ -5,21 +5,35 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.allOverridden
|
||||
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.replaceValueParametersIn
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.codegen.state.extractTypeMappingModeFromAnnotation
|
||||
import org.jetbrains.kotlin.codegen.state.isMethodWithDeclarationSiteWildcardsFqName
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunctionBase
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.load.kotlin.forceSingleValueParameterBoxing
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -27,31 +41,181 @@ import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
|
||||
class MethodSignatureMapper(context: JvmBackendContext) {
|
||||
private val typeMapper: IrTypeMapper = context.typeMapper
|
||||
private val typeSystem: IrTypeSystemContext = typeMapper.typeSystem
|
||||
private val kotlinTypeMapper: KotlinTypeMapper = context.state.typeMapper
|
||||
|
||||
fun mapAsmMethod(irFunction: IrFunction): Method =
|
||||
kotlinTypeMapper.mapAsmMethod(irFunction.descriptor)
|
||||
fun mapAsmMethod(function: IrFunction): Method =
|
||||
mapSignatureSkipGeneric(function).asmMethod
|
||||
|
||||
fun mapFieldSignature(irField: IrField): String? =
|
||||
kotlinTypeMapper.mapFieldSignature(irField.type.toKotlinType(), irField.descriptor)
|
||||
fun mapFieldSignature(field: IrField): String? {
|
||||
val sw = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
if (field.correspondingPropertySymbol?.owner?.isVar == true) {
|
||||
writeParameterType(sw, field.type, field)
|
||||
} else {
|
||||
mapReturnType(field, field.type, sw)
|
||||
}
|
||||
return sw.makeJavaGenericSignature()
|
||||
}
|
||||
|
||||
fun mapFunctionName(irFunction: IrFunction): String =
|
||||
kotlinTypeMapper.mapFunctionName(irFunction.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
fun mapAnnotationParameterName(field: IrField): String =
|
||||
kotlinTypeMapper.mapAnnotationParameterName(field.descriptor)
|
||||
mapFunctionName(field.correspondingPropertySymbol!!.owner.getter ?: error("No getter for annotation property: ${field.render()}"))
|
||||
|
||||
fun mapReturnType(irField: IrField): Type =
|
||||
kotlinTypeMapper.mapReturnType(irField.descriptor)
|
||||
fun mapReturnType(declaration: IrDeclaration, sw: JvmSignatureWriter? = null): Type {
|
||||
if (declaration !is IrFunction) {
|
||||
require(declaration is IrField) { "Unsupported declaration: $declaration" }
|
||||
return mapReturnType(declaration, declaration.type, sw)
|
||||
}
|
||||
|
||||
fun mapReturnType(irFunction: IrFunction): Type =
|
||||
kotlinTypeMapper.mapReturnType(irFunction.descriptor)
|
||||
return when {
|
||||
hasVoidReturnType(declaration) -> {
|
||||
sw?.writeAsmType(Type.VOID_TYPE)
|
||||
Type.VOID_TYPE
|
||||
}
|
||||
forceBoxedReturnType(declaration) -> {
|
||||
typeMapper.mapType(declaration.returnType, TypeMappingMode.RETURN_TYPE_BOXED, sw)
|
||||
}
|
||||
else -> mapReturnType(declaration, declaration.returnType, sw)
|
||||
}
|
||||
}
|
||||
|
||||
fun mapSignatureSkipGeneric(f: IrFunction): JvmMethodSignature =
|
||||
kotlinTypeMapper.mapSignatureSkipGeneric(f.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
private fun mapReturnType(declaration: IrDeclaration, returnType: IrType, sw: JvmSignatureWriter?): Type {
|
||||
val isAnnotationMethod = declaration.parent.let { it is IrClass && it.isAnnotationClass }
|
||||
if (sw == null || sw.skipGenericSignature()) {
|
||||
return typeMapper.mapType(returnType, TypeMappingMode.getModeForReturnTypeNoGeneric(isAnnotationMethod), sw)
|
||||
}
|
||||
|
||||
fun mapSignatureWithGeneric(f: IrFunction): JvmMethodGenericSignature =
|
||||
kotlinTypeMapper.mapSignatureWithGeneric(f.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val typeMappingModeFromAnnotation =
|
||||
typeSystem.extractTypeMappingModeFromAnnotation(declaration.suppressWildcardsMode(), returnType, isAnnotationMethod)
|
||||
if (typeMappingModeFromAnnotation != null) {
|
||||
return typeMapper.mapType(returnType, typeMappingModeFromAnnotation, sw)
|
||||
}
|
||||
|
||||
val mappingMode = TypeMappingMode.getOptimalModeForReturnType(returnType.toKotlinType(), isAnnotationMethod)
|
||||
|
||||
return typeMapper.mapType(returnType, mappingMode, sw)
|
||||
}
|
||||
|
||||
private fun hasVoidReturnType(function: IrFunction): Boolean =
|
||||
function is IrConstructor || (function.returnType.isUnit() && !function.isPropertyGetter)
|
||||
|
||||
private val IrFunction.isPropertyGetter: Boolean
|
||||
get() = isPropertyAccessor && valueParameters.isEmpty()
|
||||
|
||||
// Copied from KotlinTypeMapper.forceBoxedReturnType.
|
||||
private fun forceBoxedReturnType(function: IrFunction): Boolean {
|
||||
if (isBoxMethodForInlineClass(function)) return true
|
||||
|
||||
return isJvmPrimitive(function.returnType) &&
|
||||
function is IrSimpleFunction && function.allOverridden().any { !isJvmPrimitive(it.returnType) }
|
||||
}
|
||||
|
||||
private fun isBoxMethodForInlineClass(function: IrFunction): Boolean =
|
||||
function.parent.let { it is IrClass && it.isInline } &&
|
||||
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER &&
|
||||
function.name.asString() == "box-impl"
|
||||
|
||||
private fun isJvmPrimitive(type: IrType): Boolean {
|
||||
if (type.isPrimitiveType()) return true
|
||||
return type.getClass()?.isInline == true && AsmUtil.isPrimitive(typeMapper.mapType(type))
|
||||
}
|
||||
|
||||
fun mapSignatureSkipGeneric(function: IrFunction): JvmMethodSignature =
|
||||
mapSignature(function, true)
|
||||
|
||||
fun mapSignatureWithGeneric(function: IrFunction): JvmMethodGenericSignature =
|
||||
mapSignature(function, false)
|
||||
|
||||
private fun mapSignature(function: IrFunction, skipGenericSignature: Boolean): JvmMethodGenericSignature {
|
||||
if (function is IrLazyFunctionBase && function.initialSignatureFunction != null) {
|
||||
// Overrides of special builtin in Kotlin classes always have special signature
|
||||
if (function.descriptor.getOverriddenBuiltinReflectingJvmDescriptor() == null ||
|
||||
function.descriptor.containingDeclaration.original is JavaClassDescriptor
|
||||
) {
|
||||
return mapSignature(function.initialSignatureFunction!!, skipGenericSignature)
|
||||
}
|
||||
}
|
||||
|
||||
val sw = if (skipGenericSignature) JvmSignatureWriter() else BothSignatureWriter(BothSignatureWriter.Mode.METHOD)
|
||||
|
||||
typeMapper.writeFormalTypeParameters(function.typeParameters, sw)
|
||||
|
||||
sw.writeParametersStart()
|
||||
|
||||
val receiverParameter = function.extensionReceiverParameter
|
||||
if (receiverParameter != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function)
|
||||
}
|
||||
|
||||
for (parameter in function.valueParameters) {
|
||||
val type = if (forceSingleValueParameterBoxing(function.descriptor)) parameter.type.makeNullable() else parameter.type
|
||||
writeParameter(sw, JvmMethodParameterKind.VALUE, type, function)
|
||||
}
|
||||
|
||||
sw.writeReturnType()
|
||||
mapReturnType(function, sw)
|
||||
sw.writeReturnTypeEnd()
|
||||
|
||||
val signature = sw.makeJvmMethodSignature(mapFunctionName(function))
|
||||
|
||||
val specialSignatureInfo = with(BuiltinMethodsWithSpecialGenericSignature) { function.descriptor.getSpecialSignatureInfo() }
|
||||
|
||||
if (specialSignatureInfo != null) {
|
||||
val newGenericSignature = specialSignatureInfo.replaceValueParametersIn(signature.genericsSignature)
|
||||
return JvmMethodGenericSignature(signature.asmMethod, signature.valueParameters, newGenericSignature)
|
||||
}
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
private fun writeParameter(sw: JvmSignatureWriter, kind: JvmMethodParameterKind, type: IrType, function: IrFunction) {
|
||||
sw.writeParameterType(kind)
|
||||
writeParameterType(sw, type, function)
|
||||
sw.writeParameterTypeEnd()
|
||||
}
|
||||
|
||||
private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration) {
|
||||
if (sw.skipGenericSignature()) {
|
||||
typeMapper.mapType(type, TypeMappingMode.DEFAULT, sw)
|
||||
return
|
||||
}
|
||||
|
||||
val mode = with(typeSystem) {
|
||||
extractTypeMappingModeFromAnnotation(declaration.suppressWildcardsMode(), type, isForAnnotationParameter = false)
|
||||
?: if (declaration.isMethodWithDeclarationSiteWildcards && type.argumentsCount() != 0) {
|
||||
TypeMappingMode.GENERIC_ARGUMENT // Render all wildcards
|
||||
} else {
|
||||
TypeMappingMode.getOptimalModeForValueParameter(type.toKotlinType())
|
||||
}
|
||||
}
|
||||
|
||||
typeMapper.mapType(type, mode, sw)
|
||||
}
|
||||
|
||||
private val IrDeclaration.isMethodWithDeclarationSiteWildcards: Boolean
|
||||
get() = this is IrSimpleFunction && allOverridden().any {
|
||||
it.fqNameWhenAvailable.isMethodWithDeclarationSiteWildcardsFqName
|
||||
}
|
||||
|
||||
private fun IrDeclaration.suppressWildcardsMode(): Boolean? =
|
||||
parentsWithSelf.mapNotNull { declaration ->
|
||||
when (declaration) {
|
||||
is IrField -> {
|
||||
// Annotations on properties (JvmSuppressWildcards has PROPERTY, not FIELD, in its targets) have been moved
|
||||
// to the synthetic "$annotations" method, but the copy can still be found via the property symbol.
|
||||
declaration.correspondingPropertySymbol?.owner?.getSuppressWildcardsAnnotationValue()
|
||||
}
|
||||
is IrAnnotationContainer -> declaration.getSuppressWildcardsAnnotationValue()
|
||||
else -> null
|
||||
}
|
||||
}.firstOrNull()
|
||||
|
||||
private fun IrAnnotationContainer.getSuppressWildcardsAnnotationValue(): Boolean? =
|
||||
getAnnotation(JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME)?.run {
|
||||
if (valueArgumentsCount > 0) (getValueArgument(0) as? IrConst<*>)?.value as? Boolean ?: true else null
|
||||
}
|
||||
|
||||
fun mapToCallableMethod(expression: IrFunctionAccessExpression): IrCallableMethod {
|
||||
val callee = expression.symbol.owner
|
||||
|
||||
+4
@@ -32,6 +32,10 @@ abstract class IrLazyFunctionBase(
|
||||
IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
|
||||
IrFunction {
|
||||
|
||||
val initialSignatureFunction: IrFunction? by lazyVar {
|
||||
descriptor.initialSignatureDescriptor?.takeIf { it != descriptor }?.original?.let(stubGenerator::generateFunctionStub)
|
||||
}
|
||||
|
||||
override var dispatchReceiverParameter: IrValueParameter? by lazyVar {
|
||||
typeTranslator.buildWithScope(this) {
|
||||
descriptor.dispatchReceiverParameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase }
|
||||
|
||||
Reference in New Issue
Block a user