JVM: Mangle functions returning inline class values
Mangling suffix is base64-encoded MD5 of ":<returnTypeFQN>"
This commit is contained in:
@@ -35,10 +35,10 @@ abstract class ArgumentGenerator {
|
||||
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
|
||||
*/
|
||||
open fun generate(
|
||||
valueArgumentsByIndex: List<ResolvedValueArgument>,
|
||||
actualArgs: List<ResolvedValueArgument>,
|
||||
// may be null for a constructor of an object literal
|
||||
calleeDescriptor: CallableDescriptor?
|
||||
valueArgumentsByIndex: List<ResolvedValueArgument>,
|
||||
actualArgs: List<ResolvedValueArgument>,
|
||||
// may be null for a constructor of an object literal
|
||||
calleeDescriptor: CallableDescriptor?
|
||||
): DefaultCallArgs {
|
||||
assert(valueArgumentsByIndex.size == actualArgs.size) {
|
||||
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
|
||||
@@ -50,9 +50,9 @@ abstract class ArgumentGenerator {
|
||||
ArgumentAndDeclIndex(it, arg2Index[it]!!)
|
||||
}.toMutableList()
|
||||
|
||||
valueArgumentsByIndex.withIndex().forEach {
|
||||
if (it.value is DefaultValueArgument) {
|
||||
actualArgsWithDeclIndex.add(it.index, ArgumentAndDeclIndex(it.value, it.index))
|
||||
for ((index, value) in valueArgumentsByIndex.withIndex()) {
|
||||
if (value is DefaultValueArgument) {
|
||||
actualArgsWithDeclIndex.add(index, ArgumentAndDeclIndex(value, index))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,7 @@ abstract class ArgumentGenerator {
|
||||
is DefaultValueArgument -> {
|
||||
if (calleeDescriptor?.defaultValueFromJava(declIndex) == true) {
|
||||
generateDefaultJava(declIndex, argument)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
defaultArgs.mark(declIndex)
|
||||
generateDefault(declIndex, argument)
|
||||
}
|
||||
@@ -116,11 +115,11 @@ abstract class ArgumentGenerator {
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.defaultValueFromJava(index: Int): Boolean = DFS.ifAny(
|
||||
listOf(this),
|
||||
{ current -> current.original.overriddenDescriptors.map { it.original } },
|
||||
{ descriptor ->
|
||||
descriptor.original.overriddenDescriptors.isEmpty() &&
|
||||
descriptor is JavaCallableMemberDescriptor &&
|
||||
descriptor.valueParameters[index].declaresDefaultValue()
|
||||
}
|
||||
listOf(this),
|
||||
{ current -> current.original.overriddenDescriptors.map { it.original } },
|
||||
{ descriptor ->
|
||||
descriptor.original.overriddenDescriptors.isEmpty() &&
|
||||
descriptor is JavaCallableMemberDescriptor &&
|
||||
descriptor.valueParameters[index].declaresDefaultValue()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.util.Printer
|
||||
class CallableMethod(
|
||||
override val owner: Type,
|
||||
private val defaultImplOwner: Type?,
|
||||
computeDefaultMethodDesc: () -> String,
|
||||
computeDefaultMethod: () -> Method,
|
||||
private val signature: JvmMethodSignature,
|
||||
val invokeOpcode: Int,
|
||||
override val dispatchReceiverType: Type?,
|
||||
@@ -32,7 +32,10 @@ class CallableMethod(
|
||||
val isInterfaceMethod: Boolean,
|
||||
private val isDefaultMethodInInterface: Boolean
|
||||
) : Callable {
|
||||
private val defaultMethodDesc: String by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethodDesc)
|
||||
private val defaultImplMethod: Method by lazy(LazyThreadSafetyMode.PUBLICATION, computeDefaultMethod)
|
||||
|
||||
private val defaultImplMethodName: String get() = defaultImplMethod.name
|
||||
private val defaultMethodDesc: String get() = defaultImplMethod.descriptor
|
||||
|
||||
fun getValueParameters(): List<JvmMethodParameterSignature> =
|
||||
signature.valueParameters
|
||||
@@ -68,10 +71,14 @@ class CallableMethod(
|
||||
} else {
|
||||
v.visitMethodInsn(
|
||||
INVOKESTATIC, defaultImplOwner.internalName,
|
||||
method.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodDesc, isDefaultMethodInInterface
|
||||
defaultImplMethodName, defaultMethodDesc, isDefaultMethodInInterface
|
||||
)
|
||||
|
||||
StackValue.coerce(Type.getReturnType(defaultMethodDesc), Type.getReturnType(signature.asmMethod.descriptor), v)
|
||||
StackValue.coerce(
|
||||
Type.getReturnType(defaultMethodDesc),
|
||||
Type.getReturnType(signature.asmMethod.descriptor),
|
||||
v
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return parentCodegen;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KotlinTypeMapper getTypeMapper() {
|
||||
return typeMapper;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ObjectLiteralResult generateObjectLiteral(@NotNull KtObjectLiteralExpression literal) {
|
||||
KtObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||
|
||||
@@ -1038,10 +1038,7 @@ public class FunctionCodegen {
|
||||
// or all return types are supertypes of inline class (and can't be inline classes).
|
||||
|
||||
for (DescriptorBasedFunctionHandleForJvm handle : bridge.getOriginalFunctions()) {
|
||||
KotlinType returnType = handle.getDescriptor().getReturnType();
|
||||
if (returnType != null) {
|
||||
return returnType;
|
||||
}
|
||||
return state.getTypeMapper().getReturnValueType(handle.getDescriptor());
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode().mightBeIncorrectCode) {
|
||||
@@ -1450,8 +1447,8 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
StackValue.coerce(delegateTo.getReturnType(), returnType, bridge.getReturnType(), bridgeReturnType, iv);
|
||||
KotlinType returnValueType = state.getTypeMapper().getReturnValueType(descriptor);
|
||||
StackValue.coerce(delegateTo.getReturnType(), returnValueType, bridge.getReturnType(), bridgeReturnType, iv);
|
||||
iv.areturn(bridge.getReturnType());
|
||||
|
||||
endVisit(mv, "bridge method", origin);
|
||||
@@ -1619,7 +1616,7 @@ public class FunctionCodegen {
|
||||
)
|
||||
);
|
||||
|
||||
stackValue.put(delegateMethod.getReturnType(), delegatedTo.getReturnType(), iv);
|
||||
stackValue.put(delegateMethod.getReturnType(), delegateFunction.getReturnType(), iv);
|
||||
|
||||
iv.areturn(delegateMethod.getReturnType());
|
||||
}
|
||||
|
||||
@@ -467,7 +467,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
Name.special("<clinit>"), SYNTHESIZED, KotlinSourceElementKt.toSourceElement(element));
|
||||
clInit.initialize(null, null, Collections.emptyList(), Collections.emptyList(),
|
||||
DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(),
|
||||
null, Visibilities.PRIVATE);
|
||||
Modality.FINAL, Visibilities.PRIVATE);
|
||||
return clInit;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -53,7 +53,8 @@ internal class ObjectSuperCallArgumentGenerator(
|
||||
valueArgumentsByIndex: List<ResolvedValueArgument>,
|
||||
actualArgs: List<ResolvedValueArgument>,
|
||||
calleeDescriptor: CallableDescriptor?
|
||||
): DefaultCallArgs = super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
|
||||
): DefaultCallArgs =
|
||||
super.generate(valueArgumentsByIndex, valueArgumentsByIndex, calleeDescriptor)
|
||||
|
||||
public override fun generateExpression(i: Int, argument: ExpressionValueArgument) {
|
||||
generateSuperCallArgument(i)
|
||||
|
||||
+9
-8
@@ -51,10 +51,11 @@ private constructor(
|
||||
private val INT_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Int", Type.INT_TYPE)
|
||||
private val LONG_PROGRESSION_ITERATOR_VALUE = ProgressionIteratorBasicValue("Long", Type.LONG_TYPE)
|
||||
|
||||
private val UINT_PROGRESSION_ITERATOR_VALUE =
|
||||
ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt"))
|
||||
private val ULONG_PROGRESSION_ITERATOR_VALUE =
|
||||
ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong"))
|
||||
// TODO functions returning inline classes are mangled now, should figure out how to work with UInt/ULong iterators here
|
||||
// private val UINT_PROGRESSION_ITERATOR_VALUE =
|
||||
// ProgressionIteratorBasicValue("UInt", Type.INT_TYPE, Type.getObjectType("kotlin/UInt"))
|
||||
// private val ULONG_PROGRESSION_ITERATOR_VALUE =
|
||||
// ProgressionIteratorBasicValue("ULong", Type.LONG_TYPE, Type.getObjectType("kotlin/ULong"))
|
||||
|
||||
private val PROGRESSION_CLASS_NAME_TO_ITERATOR_VALUE: Map<String, ProgressionIteratorBasicValue> =
|
||||
hashMapOf(
|
||||
@@ -64,10 +65,10 @@ private constructor(
|
||||
INT_PROGRESSION_FQN to INT_PROGRESSION_ITERATOR_VALUE,
|
||||
LONG_RANGE_FQN to LONG_PROGRESSION_ITERATOR_VALUE,
|
||||
LONG_PROGRESSION_FQN to LONG_PROGRESSION_ITERATOR_VALUE,
|
||||
UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
|
||||
UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
|
||||
ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE,
|
||||
ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE
|
||||
// UINT_RANGE_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
|
||||
// UINT_PROGRESSION_FQN to UINT_PROGRESSION_ITERATOR_VALUE,
|
||||
// ULONG_RANGE_FQN to ULONG_PROGRESSION_ITERATOR_VALUE,
|
||||
// ULONG_PROGRESSION_FQN to ULONG_PROGRESSION_ITERATOR_VALUE
|
||||
)
|
||||
|
||||
fun byProgressionClassType(progressionClassType: Type): ProgressionIteratorBasicValue? =
|
||||
|
||||
+1
-4
@@ -34,16 +34,13 @@ abstract class AbstractForInProgressionLoopGenerator(
|
||||
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
|
||||
|
||||
protected var incrementVar: Int = -1
|
||||
protected val asmLoopRangeType: Type
|
||||
protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!!
|
||||
protected val asmLoopRangeType: Type = codegen.asmType(rangeKotlinType)
|
||||
private val rangeElementKotlinType = getRangeOrProgressionElementType(rangeKotlinType)
|
||||
?: throw AssertionError("Unexpected loop range type: $rangeKotlinType")
|
||||
private val incrementKotlinType: KotlinType
|
||||
protected val incrementType: Type
|
||||
|
||||
init {
|
||||
asmLoopRangeType = codegen.asmType(rangeKotlinType)
|
||||
|
||||
val incrementProp = rangeKotlinType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND)
|
||||
assert(incrementProp.size == 1) { rangeKotlinType.toString() + " " + incrementProp.size }
|
||||
incrementKotlinType = incrementProp.single().type
|
||||
|
||||
+18
-2
@@ -17,8 +17,12 @@
|
||||
package org.jetbrains.kotlin.codegen.range.forLoop
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
@@ -28,6 +32,8 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
|
||||
private var loopParameter: StackValue? = null
|
||||
|
||||
protected val rangeKotlinType = bindingContext.getType(forExpression.loopRange!!)!!
|
||||
|
||||
init {
|
||||
assert(
|
||||
asmElementType.sort == Type.INT ||
|
||||
@@ -36,7 +42,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
asmElementType.sort == Type.CHAR ||
|
||||
asmElementType.sort == Type.LONG
|
||||
) {
|
||||
"Unexpected range element type: " + asmElementType
|
||||
"Unexpected range element type: $asmElementType"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +54,7 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
|
||||
protected fun checkPostCondition(loopExit: Label) {
|
||||
assert(endVar != -1) {
|
||||
"endVar must be allocated, endVar = " + endVar
|
||||
"endVar must be allocated, endVar = $endVar"
|
||||
}
|
||||
loopParameter().put(asmElementType, elementType, v)
|
||||
v.load(endVar, asmElementType)
|
||||
@@ -64,4 +70,14 @@ abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionC
|
||||
|
||||
protected fun loopParameter(): StackValue =
|
||||
loopParameter ?: StackValue.local(loopParameterVar, loopParameterType).also { loopParameter = it }
|
||||
|
||||
protected fun KotlinType.getPropertyGetterName(propertyName: String): String {
|
||||
// In case of unsigned ranges, getter methods for corresponding range/progression properties would be mangled.
|
||||
val propertyDescriptor = memberScope.getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull()
|
||||
?: throw AssertionError("No '$propertyName' in member scope of type $this")
|
||||
val getter = propertyDescriptor.getter
|
||||
?: throw AssertionError("Property has no getter: $propertyDescriptor")
|
||||
return codegen.typeMapper.mapFunctionName(getter, OwnerKind.IMPLEMENTATION)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -31,8 +31,12 @@ class ForInProgressionExpressionLoopGenerator(
|
||||
v.dup()
|
||||
v.dup()
|
||||
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar)
|
||||
val firstName = rangeKotlinType.getPropertyGetterName("first")
|
||||
val lastName = rangeKotlinType.getPropertyGetterName("last")
|
||||
val stepName = rangeKotlinType.getPropertyGetterName("step")
|
||||
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, stepName, incrementType, incrementType, incrementVar)
|
||||
}
|
||||
}
|
||||
|
||||
+14
-7
@@ -17,9 +17,13 @@
|
||||
package org.jetbrains.kotlin.codegen.range.forLoop
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class ForInRangeInstanceLoopGenerator(
|
||||
codegen: ExpressionCodegen,
|
||||
@@ -30,18 +34,21 @@ class ForInRangeInstanceLoopGenerator(
|
||||
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1, comparisonGenerator) {
|
||||
|
||||
override fun storeRangeStartAndEnd() {
|
||||
val loopRangeType = codegen.bindingContext.getType(rangeExpression)!!
|
||||
val asmLoopRangeType = codegen.asmType(loopRangeType)
|
||||
codegen.gen(rangeExpression, asmLoopRangeType, loopRangeType)
|
||||
val asmLoopRangeType = codegen.asmType(rangeKotlinType)
|
||||
codegen.gen(rangeExpression, asmLoopRangeType, rangeKotlinType)
|
||||
v.dup()
|
||||
|
||||
val firstName = rangeKotlinType.getPropertyGetterName("first")
|
||||
val lastName = rangeKotlinType.getPropertyGetterName("last")
|
||||
|
||||
// ranges inherit first and last from corresponding progressions
|
||||
if (reversed) {
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, asmElementType, endVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, asmElementType, endVar)
|
||||
} else {
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, firstName, asmElementType, loopParameterType, loopParameterVar)
|
||||
generateRangeOrProgressionProperty(asmLoopRangeType, lastName, asmElementType, asmElementType, endVar)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -364,39 +364,29 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
// and, more importantly, returns 'kotlin.Any' (so that it can return as a reference value or a special COROUTINE_SUSPENDED object).
|
||||
// This also causes boxing of primitives and inline class values.
|
||||
// If we have a function returning an inline class value that is mapped to a reference type, we want to avoid boxing.
|
||||
// However, we have to do that consistently both on declaration site and on call site in case of covariant overrides.
|
||||
// However, we have to do that consistently both on declaration site and on call site.
|
||||
|
||||
if (!functionDescriptor.isSuspend) return null
|
||||
|
||||
val originalSuspendFunction = functionDescriptor.unwrapInitialDescriptorForSuspendFunction()
|
||||
val originalReturnType = originalSuspendFunction.returnType!!
|
||||
|
||||
if (!originalReturnType.isInlineClassType()) return null
|
||||
|
||||
if (!originalReturnType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn()) {
|
||||
return originalSuspendFunction.module.builtIns.nullableAnyType
|
||||
// Force boxing for primitives
|
||||
if (AsmUtil.isPrimitive(mapType(originalReturnType))) {
|
||||
return functionDescriptor.builtIns.nullableAnyType
|
||||
}
|
||||
|
||||
// Lambdas, callable references, and function literals implicitly override corresponding generic method from a base class.
|
||||
// NB we don't have suspend function literals so far, but we support it in back-end, just in case.
|
||||
if (isFunctionLiteral(originalSuspendFunction) || isFunctionExpression(originalSuspendFunction)) {
|
||||
return originalSuspendFunction.module.builtIns.nullableAnyType
|
||||
}
|
||||
|
||||
// NB JVM view of a Kotlin function overrides JVM views of corresponding overridden functions
|
||||
val originalOverridden = getAllOverriddenDeclarations(functionDescriptor).map {
|
||||
it.unwrapInitialDescriptorForSuspendFunction().original
|
||||
}
|
||||
if (originalOverridden.any { !it.returnType!!.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn() }) {
|
||||
return originalSuspendFunction.module.builtIns.nullableAnyType
|
||||
// Force boxing for nullable inline class types with nullable underlying type
|
||||
if (originalReturnType.isMarkedNullable && originalReturnType.isNullableUnderlyingType()) {
|
||||
return functionDescriptor.builtIns.nullableAnyType
|
||||
}
|
||||
|
||||
// Don't box other inline classes
|
||||
return originalReturnType
|
||||
}
|
||||
|
||||
private fun KotlinType.isInlineClassTypeSafeToKeepUnboxedOnSuspendFunReturn(): Boolean =
|
||||
isInlineClassType() && !AsmUtil.isPrimitive(mapType(this)) && (!isMarkedNullable || !isNullableUnderlyingType())
|
||||
|
||||
|
||||
@JvmOverloads
|
||||
fun mapToCallableMethod(
|
||||
descriptor: FunctionDescriptor,
|
||||
@@ -410,7 +400,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
val owner = mapOwner(descriptor)
|
||||
val originalDescriptor = descriptor.original
|
||||
return CallableMethod(
|
||||
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION).descriptor }, method, INVOKESPECIAL,
|
||||
owner, owner, { mapDefaultMethod(originalDescriptor, OwnerKind.IMPLEMENTATION) }, method, INVOKESPECIAL,
|
||||
null, null, null, null, null, originalDescriptor.returnType, isInterfaceMethod = false, isDefaultMethodInInterface = false
|
||||
)
|
||||
}
|
||||
@@ -571,7 +561,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
|
||||
return CallableMethod(
|
||||
owner, ownerForDefaultImpl,
|
||||
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).descriptor },
|
||||
{ mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)) },
|
||||
signature, invokeOpcode, thisClass, dispatchReceiverKotlinType, receiverParameterType, extensionReceiverKotlinType,
|
||||
calleeType, returnKotlinType,
|
||||
if (jvmTarget >= JvmTarget.JVM_1_8) isInterfaceMember else invokeOpcode == INVOKEINTERFACE,
|
||||
@@ -663,11 +653,16 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
val suffix = getInlineClassSignatureManglingSuffix(descriptor)
|
||||
if (suffix != null) {
|
||||
newName += suffix
|
||||
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
|
||||
newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS
|
||||
// Skip inline class mangling for property reference signatures,
|
||||
// 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)
|
||||
if (suffix != null) {
|
||||
newName += suffix
|
||||
} else if (kind === OwnerKind.ERASED_INLINE_CLASS) {
|
||||
newName += JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS
|
||||
}
|
||||
}
|
||||
|
||||
newName = sanitizeNameIfNeeded(newName, languageVersionSettings)
|
||||
@@ -966,12 +961,12 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
// implicitly override generic 'invoke' from a corresponding base class.
|
||||
if ((isFunctionExpression(descriptor) || isFunctionLiteral(descriptor)) && returnType.isInlineClassType()) return true
|
||||
|
||||
return isJvmPrimitiveOrInlineClass(returnType) &&
|
||||
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitiveOrInlineClass(it.returnType!!) }
|
||||
return isJvmPrimitive(returnType) &&
|
||||
getAllOverriddenDescriptors(descriptor).any { !isJvmPrimitive(it.returnType!!) }
|
||||
}
|
||||
|
||||
private fun isJvmPrimitiveOrInlineClass(kotlinType: KotlinType) =
|
||||
KotlinBuiltIns.isPrimitiveType(kotlinType) || kotlinType.isInlineClassType()
|
||||
private fun isJvmPrimitive(kotlinType: KotlinType) =
|
||||
KotlinBuiltIns.isPrimitiveType(kotlinType)
|
||||
|
||||
private fun isBoxMethodForInlineClass(descriptor: FunctionDescriptor): Boolean {
|
||||
val containingDeclaration = descriptor.containingDeclaration
|
||||
|
||||
+18
-8
@@ -5,31 +5,41 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
|
||||
fun getInlineClassSignatureManglingSuffix(descriptor: CallableMemberDescriptor): String? {
|
||||
fun getManglingSuffixBasedOnKotlinSignature(descriptor: CallableMemberDescriptor): String? {
|
||||
if (descriptor !is FunctionDescriptor) return null
|
||||
if (descriptor is ConstructorDescriptor) return null
|
||||
if (InlineClassDescriptorResolver.isSynthesizedBoxOrUnboxMethod(descriptor)) return null
|
||||
|
||||
// If a function accepts inline class parameters, mangle its name.
|
||||
val actualValueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type }
|
||||
if (requiresFunctionNameMangling(actualValueParameterTypes)) {
|
||||
return "-" + md5base64(collectSignatureForMangling(actualValueParameterTypes))
|
||||
}
|
||||
|
||||
return getInlineClassSignatureManglingSuffix(actualValueParameterTypes)
|
||||
// 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 (descriptor.containingDeclaration is ClassDescriptor) {
|
||||
val returnType = descriptor.unwrapInitialDescriptorForSuspendFunction().returnType!!
|
||||
// NB functions returning all inline classes (including our special 'kotlin.Result') should be mangled.
|
||||
if (returnType.isInlineClassType()) {
|
||||
return "-" + md5base64(":" + getSignatureElementForMangling(returnType))
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getInlineClassSignatureManglingSuffix(valueParameterTypes: List<KotlinType>) =
|
||||
if (requiresFunctionNameMangling(valueParameterTypes))
|
||||
"-" + md5base64(collectSignatureForMangling(valueParameterTypes))
|
||||
else
|
||||
null
|
||||
|
||||
private fun collectSignatureForMangling(types: List<KotlinType>) =
|
||||
types.joinToString { getSignatureElementForMangling(it) }
|
||||
|
||||
|
||||
Generated
+5
@@ -12908,6 +12908,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ enum class RequestFields {
|
||||
ENUM_ONE
|
||||
}
|
||||
|
||||
data class RequestInputParameters(
|
||||
class RequestInputParameters(
|
||||
private val backingMap: Map<RequestFields, FieldValue>
|
||||
) : Map<RequestFields, FieldValue> by backingMap
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
|
||||
inline class IC(val s: String)
|
||||
|
||||
interface IFoo<T> {
|
||||
fun foo(x: T, s: String = "K"): String
|
||||
}
|
||||
|
||||
class FooImpl : IFoo<IC> {
|
||||
override fun foo(x: IC, s: String): String = x.s + s
|
||||
}
|
||||
|
||||
fun box(): String = FooImpl().foo(IC("O"))
|
||||
+5
@@ -14123,6 +14123,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
+5
@@ -14128,6 +14128,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
+5
@@ -12908,6 +12908,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
Generated
+5
@@ -11118,6 +11118,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
+5
@@ -11183,6 +11183,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt37998.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38680.kt")
|
||||
public void testKt38680() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt38680.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("mangledDefaultParameterFunction.kt")
|
||||
public void testMangledDefaultParameterFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
|
||||
|
||||
Reference in New Issue
Block a user