JVM IR: do not use old KotlinTypeMapper when coercing inline classes
KotlinTypeMapper.mapInlineClassTypeAsDeclaration and mapUnderlyingTypeOfInlineClassType invoked mapType which is defined in descriptorBasedTypeSignatureMapping.kt and works on KotlinType. It didn't lead to any problems, other than the fact that we were constructing IrBasedClassDescriptor in JVM IR, and then KotlinType to pass it to mapType, on each call to StackValue.boxInlineClass or unboxInlineClass, which seems wasteful. Instead of this, refactor these utilities to use type markers instead, pass IrType and IrTypeMapper directly from JVM IR, and move the "static type mapper" logic (which is used only in the old backend) out of KotlinTypeMapper.
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.state.StaticTypeMapperForOldBackend
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -51,7 +52,7 @@ class CallableMethod(
|
|||||||
|
|
||||||
override fun genInvokeInstruction(v: InstructionAdapter) {
|
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||||
if (boxInlineClassBeforeInvoke) {
|
if (boxInlineClassBeforeInvoke) {
|
||||||
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v)
|
StackValue.boxInlineClass(dispatchReceiverKotlinType!!, v, StaticTypeMapperForOldBackend)
|
||||||
}
|
}
|
||||||
v.visitMethodInsn(
|
v.visitMethodInsn(
|
||||||
invokeOpcode,
|
invokeOpcode,
|
||||||
|
|||||||
+3
-2
@@ -34,7 +34,8 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.correctElementType;
|
||||||
|
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
||||||
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.*;
|
import static org.jetbrains.kotlin.codegen.DescriptorAsmUtil.*;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
|
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||||
@@ -306,7 +307,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
|
|||||||
|
|
||||||
iv.load(secondParameterIndex, OBJECT_TYPE);
|
iv.load(secondParameterIndex, OBJECT_TYPE);
|
||||||
iv.checkcast(wrapperType);
|
iv.checkcast(wrapperType);
|
||||||
StackValue.unboxInlineClass(wrapperType, wrapperKotlinType, iv);
|
StackValue.unboxInlineClass(wrapperType, wrapperKotlinType, iv, typeMapper);
|
||||||
iv.store(unboxedValueIndex, underlyingType.getType());
|
iv.store(unboxedValueIndex, underlyingType.getType());
|
||||||
|
|
||||||
return unboxedValueIndex;
|
return unboxedValueIndex;
|
||||||
|
|||||||
@@ -20,11 +20,14 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
|||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
|
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase;
|
||||||
|
import org.jetbrains.kotlin.codegen.state.StaticTypeMapperForOldBackend;
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
|
||||||
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
|
import org.jetbrains.kotlin.load.java.DescriptorsJvmAbiUtil;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.ValueArgument;
|
import org.jetbrains.kotlin.psi.ValueArgument;
|
||||||
@@ -43,6 +46,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
|||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.SimpleType;
|
import org.jetbrains.kotlin.types.SimpleType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker;
|
||||||
import org.jetbrains.org.objectweb.asm.Label;
|
import org.jetbrains.org.objectweb.asm.Label;
|
||||||
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;
|
||||||
@@ -452,11 +456,13 @@ public abstract class StackValue {
|
|||||||
v.invokevirtual(methodOwner.getInternalName(), type.getClassName() + "Value", "()" + type.getDescriptor(), false);
|
v.invokevirtual(methodOwner.getInternalName(), type.getClassName() + "Value", "()" + type.getDescriptor(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void boxInlineClass(@NotNull KotlinType kotlinType, @NotNull InstructionAdapter v) {
|
public static void boxInlineClass(
|
||||||
Type boxedType = KotlinTypeMapper.mapInlineClassTypeAsDeclaration(kotlinType);
|
@NotNull KotlinTypeMarker kotlinType, @NotNull InstructionAdapter v, @NotNull KotlinTypeMapperBase typeMapper
|
||||||
Type underlyingType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType);
|
) {
|
||||||
|
Type boxedType = typeMapper.mapTypeCommon(kotlinType, TypeMappingMode.CLASS_DECLARATION);
|
||||||
|
Type underlyingType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType, typeMapper);
|
||||||
|
|
||||||
if (TypeUtils.isNullableType(kotlinType) && !isPrimitive(underlyingType)) {
|
if (typeMapper.getTypeSystem().isNullableType(kotlinType) && !isPrimitive(underlyingType)) {
|
||||||
boxOrUnboxWithNullCheck(v, vv -> invokeBoxMethod(vv, boxedType, underlyingType));
|
boxOrUnboxWithNullCheck(v, vv -> invokeBoxMethod(vv, boxedType, underlyingType));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -477,14 +483,19 @@ public abstract class StackValue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unboxInlineClass(@NotNull Type type, @NotNull KotlinType targetInlineClassType, @NotNull InstructionAdapter v) {
|
public static void unboxInlineClass(
|
||||||
Type owner = KotlinTypeMapper.mapInlineClassTypeAsDeclaration(targetInlineClassType);
|
@NotNull Type type,
|
||||||
|
@NotNull KotlinTypeMarker targetInlineClassType,
|
||||||
|
@NotNull InstructionAdapter v,
|
||||||
|
@NotNull KotlinTypeMapperBase typeMapper
|
||||||
|
) {
|
||||||
|
Type owner = typeMapper.mapTypeCommon(targetInlineClassType, TypeMappingMode.CLASS_DECLARATION);
|
||||||
|
|
||||||
coerce(type, owner, v);
|
coerce(type, owner, v);
|
||||||
|
|
||||||
Type resultType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(targetInlineClassType);
|
Type resultType = KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(targetInlineClassType, typeMapper);
|
||||||
|
|
||||||
if (TypeUtils.isNullableType(targetInlineClassType) && !isPrimitive(resultType)) {
|
if (typeMapper.getTypeSystem().isNullableType(targetInlineClassType) && !isPrimitive(resultType)) {
|
||||||
boxOrUnboxWithNullCheck(v, vv -> invokeUnboxMethod(vv, owner, resultType));
|
boxOrUnboxWithNullCheck(v, vv -> invokeUnboxMethod(vv, owner, resultType));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -537,7 +548,7 @@ public abstract class StackValue {
|
|||||||
@Nullable KotlinType toKotlinType,
|
@Nullable KotlinType toKotlinType,
|
||||||
@NotNull InstructionAdapter v
|
@NotNull InstructionAdapter v
|
||||||
) {
|
) {
|
||||||
if (coerceInlineClasses(fromType, fromKotlinType, toType, toKotlinType, v)) return;
|
if (coerceInlineClasses(fromType, fromKotlinType, toType, toKotlinType, v, StaticTypeMapperForOldBackend.INSTANCE)) return;
|
||||||
coerce(fromType, toType, v);
|
coerce(fromType, toType, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +584,8 @@ public abstract class StackValue {
|
|||||||
@Nullable KotlinType fromKotlinType,
|
@Nullable KotlinType fromKotlinType,
|
||||||
@NotNull Type toType,
|
@NotNull Type toType,
|
||||||
@Nullable KotlinType toKotlinType,
|
@Nullable KotlinType toKotlinType,
|
||||||
@NotNull InstructionAdapter v
|
@NotNull InstructionAdapter v,
|
||||||
|
@NotNull KotlinTypeMapperBase typeMapper
|
||||||
) {
|
) {
|
||||||
// NB see also requiresInlineClassBoxingOrUnboxing above
|
// NB see also requiresInlineClassBoxingOrUnboxing above
|
||||||
|
|
||||||
@@ -600,23 +612,23 @@ public abstract class StackValue {
|
|||||||
boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType);
|
boolean isFromTypeUnboxed = isUnboxedInlineClass(fromKotlinType, fromType);
|
||||||
boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType);
|
boolean isToTypeUnboxed = isUnboxedInlineClass(toKotlinType, toType);
|
||||||
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
if (isFromTypeUnboxed && !isToTypeUnboxed) {
|
||||||
boxInlineClass(fromKotlinType, v);
|
boxInlineClass(fromKotlinType, v, typeMapper);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
else if (!isFromTypeUnboxed && isToTypeUnboxed) {
|
||||||
unboxInlineClass(fromType, toKotlinType, v);
|
unboxInlineClass(fromType, toKotlinType, v, typeMapper);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isFromTypeInlineClass) {
|
else if (isFromTypeInlineClass) {
|
||||||
if (isUnboxedInlineClass(fromKotlinType, fromType)) {
|
if (isUnboxedInlineClass(fromKotlinType, fromType)) {
|
||||||
boxInlineClass(fromKotlinType, v);
|
boxInlineClass(fromKotlinType, v, typeMapper);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // isToTypeInlineClass is `true`
|
else { // isToTypeInlineClass is `true`
|
||||||
if (isUnboxedInlineClass(toKotlinType, toType)) {
|
if (isUnboxedInlineClass(toKotlinType, toType)) {
|
||||||
unboxInlineClass(fromType, toKotlinType, v);
|
unboxInlineClass(fromType, toKotlinType, v, typeMapper);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -625,7 +637,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) {
|
public static boolean isUnboxedInlineClass(@NotNull KotlinType kotlinType, @NotNull Type actualType) {
|
||||||
return KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType).equals(actualType);
|
return KotlinTypeMapper.mapUnderlyingTypeOfInlineClassType(kotlinType, StaticTypeMapperForOldBackend.INSTANCE).equals(actualType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v) {
|
public static void coerce(@NotNull Type fromType, @NotNull Type toType, @NotNull InstructionAdapter v) {
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
|||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import org.jetbrains.kotlin.backend.common.SamType
|
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
@@ -451,7 +450,7 @@ class CoroutineCodegenForLambda private constructor(
|
|||||||
if (parameter.type.isInlineClassType()) {
|
if (parameter.type.isInlineClassType()) {
|
||||||
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
||||||
load(index, AsmTypes.OBJECT_TYPE)
|
load(index, AsmTypes.OBJECT_TYPE)
|
||||||
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, this)
|
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, parameter.type, this, typeMapper)
|
||||||
putfield(
|
putfield(
|
||||||
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
||||||
fieldInfoForCoroutineLambdaParameter.fieldName,
|
fieldInfoForCoroutineLambdaParameter.fieldName,
|
||||||
@@ -757,7 +756,7 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
generateCoroutineSuspendedCheck(languageVersionSettings)
|
generateCoroutineSuspendedCheck(languageVersionSettings)
|
||||||
// Now we box the inline class
|
// Now we box the inline class
|
||||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this)
|
StackValue.coerce(AsmTypes.OBJECT_TYPE, typeMapper.mapType(inlineClassToBoxInInvokeSuspend), this)
|
||||||
StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this)
|
StackValue.boxInlineClass(inlineClassToBoxInInvokeSuspend, this, typeMapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,4 +860,4 @@ fun reportSuspensionPointInsideMonitor(element: KtElement, state: GenerationStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FunctionDescriptor.allValueParameterTypes(): List<KotlinType> =
|
private fun FunctionDescriptor.allValueParameterTypes(): List<KotlinType> =
|
||||||
(listOfNotNull(extensionReceiverParameter?.type)) + valueParameters.map { it.type }
|
(listOfNotNull(extensionReceiverParameter?.type)) + valueParameters.map { it.type }
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.codegen.inline
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.ASSERTIONS_DISABLED_FIELD_NAME
|
||||||
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
|
||||||
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
|
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
|
||||||
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||||
@@ -22,6 +25,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -32,9 +36,9 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
@@ -415,13 +419,13 @@ fun addInlineMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
|||||||
internal fun addUnboxInlineClassMarkersIfNeeded(v: InstructionAdapter, descriptor: CallableDescriptor, typeMapper: KotlinTypeMapper) {
|
internal fun addUnboxInlineClassMarkersIfNeeded(v: InstructionAdapter, descriptor: CallableDescriptor, typeMapper: KotlinTypeMapper) {
|
||||||
val inlineClass = (descriptor as? FunctionDescriptor)?.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(typeMapper)
|
val inlineClass = (descriptor as? FunctionDescriptor)?.originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass(typeMapper)
|
||||||
if (inlineClass != null) {
|
if (inlineClass != null) {
|
||||||
generateResumePathUnboxing(v, inlineClass)
|
generateResumePathUnboxing(v, inlineClass, typeMapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateResumePathUnboxing(v: InstructionAdapter, inlineClass: KotlinType) {
|
fun generateResumePathUnboxing(v: InstructionAdapter, inlineClass: KotlinTypeMarker, typeMapper: KotlinTypeMapperBase) {
|
||||||
addBeforeUnboxInlineClassMarker(v)
|
addBeforeUnboxInlineClassMarker(v)
|
||||||
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, inlineClass, v)
|
StackValue.unboxInlineClass(AsmTypes.OBJECT_TYPE, inlineClass, v, typeMapper)
|
||||||
// Suspend functions always returns Any?, but the unboxing disrupts type analysis of the bytecode.
|
// Suspend functions always returns Any?, but the unboxing disrupts type analysis of the bytecode.
|
||||||
// For example, if the underlying type is String, CHECKCAST String is removed.
|
// For example, if the underlying type is String, CHECKCAST String is removed.
|
||||||
// However, the unboxing is moved to the resume path, the direct path still has Any?, but now, without the CHECKCAST.
|
// However, the unboxing is moved to the resume path, the direct path still has Any?, but now, without the CHECKCAST.
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
|||||||
import org.jetbrains.kotlin.types.checker.convertVariance
|
import org.jetbrains.kotlin.types.checker.convertVariance
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.backend.common.SamType
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
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
|
||||||
@@ -101,6 +100,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val typeSystem: TypeSystemCommonBackendContext
|
||||||
|
get() = SimpleClassicTypeSystemContext
|
||||||
|
|
||||||
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 {
|
||||||
return CommonSupertypes.commonSupertype(types)
|
return CommonSupertypes.commonSupertype(types)
|
||||||
@@ -233,6 +235,10 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
return mapType(classifier.defaultType, null, TypeMappingMode.CLASS_DECLARATION)
|
return mapType(classifier.defaultType, null, TypeMappingMode.CLASS_DECLARATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type {
|
||||||
|
return mapType(type as KotlinType, null, mode)
|
||||||
|
}
|
||||||
|
|
||||||
fun mapTypeAsDeclaration(kotlinType: KotlinType): Type {
|
fun mapTypeAsDeclaration(kotlinType: KotlinType): Type {
|
||||||
return mapType(kotlinType, null, TypeMappingMode.CLASS_DECLARATION)
|
return mapType(kotlinType, null, TypeMappingMode.CLASS_DECLARATION)
|
||||||
}
|
}
|
||||||
@@ -1272,29 +1278,6 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val staticTypeMappingConfiguration = object : TypeMappingConfiguration<Type> {
|
|
||||||
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
|
|
||||||
return CommonSupertypes.commonSupertype(types)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): Type? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) {
|
|
||||||
throw IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun preprocessType(kotlinType: KotlinType): KotlinType? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use proper LanguageVersionSettings where possible.
|
* Use proper LanguageVersionSettings where possible.
|
||||||
*/
|
*/
|
||||||
@@ -1412,30 +1395,15 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
|||||||
return ContainingClassesInfo.forPackageMember(facadeName, implClassName)
|
return ContainingClassesInfo.forPackageMember(facadeName, implClassName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure this method is called only from back-end
|
|
||||||
// It uses staticTypeMappingConfiguration that throws exception on error types
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun mapInlineClassTypeAsDeclaration(kotlinType: KotlinType): Type {
|
fun mapUnderlyingTypeOfInlineClassType(kotlinType: KotlinTypeMarker, typeMapper: KotlinTypeMapperBase): Type {
|
||||||
return mapInlineClassType(kotlinType, TypeMappingMode.CLASS_DECLARATION, staticTypeMappingConfiguration)
|
val underlyingType = with(typeMapper.typeSystem) {
|
||||||
|
kotlinType.getUnsubstitutedUnderlyingType()
|
||||||
|
} ?: throw IllegalStateException("There should be underlying type for inline class type: $kotlinType")
|
||||||
|
return typeMapper.mapTypeCommon(underlyingType, TypeMappingMode.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure this method is called only from back-end
|
internal fun generateErrorMessageForErrorType(type: KotlinType, descriptor: DeclarationDescriptor): String {
|
||||||
// It uses staticTypeMappingConfiguration that throws exception on error types
|
|
||||||
@JvmStatic
|
|
||||||
fun mapUnderlyingTypeOfInlineClassType(kotlinType: KotlinType): Type {
|
|
||||||
val underlyingType = kotlinType.unsubstitutedUnderlyingType()
|
|
||||||
?: throw IllegalStateException("There should be underlying type for inline class type: $kotlinType")
|
|
||||||
return mapInlineClassType(underlyingType, TypeMappingMode.DEFAULT, staticTypeMappingConfiguration)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun mapInlineClassType(
|
|
||||||
kotlinType: KotlinType,
|
|
||||||
mode: TypeMappingMode,
|
|
||||||
configuration: TypeMappingConfiguration<Type>
|
|
||||||
): Type =
|
|
||||||
mapType(kotlinType, AsmTypeFactory, mode, configuration, null)
|
|
||||||
|
|
||||||
private fun generateErrorMessageForErrorType(type: KotlinType, descriptor: DeclarationDescriptor): String {
|
|
||||||
val declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
|
val declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
|
||||||
?: return "Error type encountered: $type (${type.javaClass.simpleName})."
|
?: return "Error type encountered: $type (${type.javaClass.simpleName})."
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,18 @@ package org.jetbrains.kotlin.codegen.state
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
abstract class KotlinTypeMapperBase {
|
abstract class KotlinTypeMapperBase {
|
||||||
|
abstract val typeSystem: TypeSystemCommonBackendContext
|
||||||
|
|
||||||
abstract fun mapClass(classifier: ClassifierDescriptor): Type
|
abstract fun mapClass(classifier: ClassifierDescriptor): Type
|
||||||
|
|
||||||
|
abstract fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type
|
||||||
|
|
||||||
fun mapDefaultImpls(descriptor: ClassDescriptor): Type =
|
fun mapDefaultImpls(descriptor: ClassDescriptor): Type =
|
||||||
Type.getObjectType(mapClass(descriptor).internalName + JvmAbi.DEFAULT_IMPLS_SUFFIX)
|
Type.getObjectType(mapClass(descriptor).internalName + JvmAbi.DEFAULT_IMPLS_SUFFIX)
|
||||||
}
|
}
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen.state
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.mapType
|
||||||
|
import org.jetbrains.kotlin.types.CommonSupertypes
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
// This class exists only because it's used to box/unbox inline classes in the static method StackValue.coerce in the old backend, which
|
||||||
|
// has no access to the correct type mapper instance, yet has a lot of call sites across the old backend, refactoring which would be costly.
|
||||||
|
object StaticTypeMapperForOldBackend : KotlinTypeMapperBase() {
|
||||||
|
override val typeSystem: TypeSystemCommonBackendContext
|
||||||
|
get() = SimpleClassicTypeSystemContext
|
||||||
|
|
||||||
|
private val staticTypeMappingConfiguration = object : TypeMappingConfiguration<Type> {
|
||||||
|
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
|
||||||
|
return CommonSupertypes.commonSupertype(types)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): Type? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) {
|
||||||
|
throw IllegalStateException(KotlinTypeMapper.generateErrorMessageForErrorType(kotlinType, descriptor))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessType(kotlinType: KotlinType): KotlinType? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mapClass(classifier: ClassifierDescriptor): Type = TODO("Should not be called")
|
||||||
|
|
||||||
|
override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type {
|
||||||
|
return mapType(type as KotlinType, AsmTypeFactory, mode, staticTypeMappingConfiguration, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-6
@@ -11,10 +11,19 @@ import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByType
|
|||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeTypeContext
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||||
|
|
||||||
fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
|
internal fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession, context: ConeTypeContext): ConeKotlinType? {
|
||||||
|
val unsubstitutedType = unsubstitutedUnderlyingTypeForInlineClass(session) ?: return null
|
||||||
|
val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context)
|
||||||
|
return substitutor.substituteOrNull(unsubstitutedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ConeKotlinType.unsubstitutedUnderlyingTypeForInlineClass(session: FirSession): ConeKotlinType? {
|
||||||
val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType)
|
val symbol = (this.fullyExpandedType(session) as? ConeLookupTagBasedType)
|
||||||
?.lookupTag
|
?.lookupTag
|
||||||
?.toSymbol(session) as? FirRegularClassSymbol
|
?.toSymbol(session) as? FirRegularClassSymbol
|
||||||
@@ -24,8 +33,5 @@ fun ConeKotlinType.substitutedUnderlyingTypeForInlineClass(session: FirSession,
|
|||||||
if (!firClass.status.isInline) return null
|
if (!firClass.status.isInline) return null
|
||||||
val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null
|
val constructor = firClass.declarations.singleOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? ?: return null
|
||||||
val valueParameter = constructor.valueParameters.singleOrNull() ?: return null
|
val valueParameter = constructor.valueParameters.singleOrNull() ?: return null
|
||||||
val unsubstitutedType = valueParameter.returnTypeRef.coneType
|
return valueParameter.returnTypeRef.coneType
|
||||||
|
|
||||||
val substitutor = createTypeSubstitutorByTypeConstructor(mapOf(this.typeConstructor(context) to this), context)
|
|
||||||
return substitutor.substituteOrNull(unsubstitutedType)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,6 +497,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
?: session.builtinTypes.nullableAnyType.type
|
?: session.builtinTypes.nullableAnyType.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
|
require(this is ConeKotlinType)
|
||||||
|
return unsubstitutedUnderlyingTypeForInlineClass(session)
|
||||||
|
}
|
||||||
|
|
||||||
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
require(this is ConeKotlinType)
|
require(this is ConeKotlinType)
|
||||||
return substitutedUnderlyingTypeForInlineClass(session, this@ConeTypeContext)
|
return substitutedUnderlyingTypeForInlineClass(session, this@ConeTypeContext)
|
||||||
|
|||||||
+5
-5
@@ -468,7 +468,7 @@ class ExpressionCodegen(
|
|||||||
if (isSuspensionPoint != SuspensionPointKind.NEVER) {
|
if (isSuspensionPoint != SuspensionPointKind.NEVER) {
|
||||||
addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE)
|
addSuspendMarker(mv, isStartNotEnd = false, isSuspensionPoint == SuspensionPointKind.NOT_INLINE)
|
||||||
if (unboxedInlineClassIrType != null) {
|
if (unboxedInlineClassIrType != null) {
|
||||||
generateResumePathUnboxing(mv, unboxedInlineClassIrType.toIrBasedKotlinType())
|
generateResumePathUnboxing(mv, unboxedInlineClassIrType, typeMapper)
|
||||||
}
|
}
|
||||||
addInlineMarker(mv, isStartNotEnd = false)
|
addInlineMarker(mv, isStartNotEnd = false)
|
||||||
}
|
}
|
||||||
@@ -484,7 +484,7 @@ class ExpressionCodegen(
|
|||||||
mv.checkcast(unboxedInlineClassIrType.asmType)
|
mv.checkcast(unboxedInlineClassIrType.asmType)
|
||||||
}
|
}
|
||||||
if (irFunction.isInvokeSuspendOfContinuation()) {
|
if (irFunction.isInvokeSuspendOfContinuation()) {
|
||||||
StackValue.boxInlineClass(unboxedInlineClassIrType.toIrBasedKotlinType(), mv)
|
StackValue.boxInlineClass(unboxedInlineClassIrType, mv, typeMapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +637,7 @@ class ExpressionCodegen(
|
|||||||
if (!irFunction.isInlineCallableReference) return
|
if (!irFunction.isInlineCallableReference) return
|
||||||
if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return
|
if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return
|
||||||
if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return
|
if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return
|
||||||
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType.toIrBasedKotlinType(), mv)
|
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do not mangle functions if Result is the only parameter of the function,
|
// We do not mangle functions if Result is the only parameter of the function,
|
||||||
@@ -664,7 +664,7 @@ class ExpressionCodegen(
|
|||||||
// Result parameter of SAM-wrapper to Java SAM is already unboxed in visitGetValue, do not unbox it anymore
|
// Result parameter of SAM-wrapper to Java SAM is already unboxed in visitGetValue, do not unbox it anymore
|
||||||
if (irFunction.parentAsClass.superTypes.any { it.getClass()?.isFromJava() == true }) return
|
if (irFunction.parentAsClass.superTypes.any { it.getClass()?.isFromJava() == true }) return
|
||||||
|
|
||||||
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType.toIrBasedKotlinType(), mv)
|
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrClass.isSamAdapter(): Boolean = this.superTypes.any { it.getClass()?.isFun == true }
|
private fun IrClass.isSamAdapter(): Boolean = this.superTypes.any { it.getClass()?.isFun == true }
|
||||||
@@ -920,7 +920,7 @@ class ExpressionCodegen(
|
|||||||
expression.value.accept(this, data).materializeAt(returnType, returnIrType)
|
expression.value.accept(this, data).materializeAt(returnType, returnIrType)
|
||||||
// In case of non-local return from suspend lambda 'materializeAt' does not box return value, box it manually.
|
// In case of non-local return from suspend lambda 'materializeAt' does not box return value, box it manually.
|
||||||
if (isNonLocalReturn && owner.isInvokeSuspendOfLambda() && expression.value.type.isKotlinResult()) {
|
if (isNonLocalReturn && owner.isInvokeSuspendOfLambda() && expression.value.type.isKotlinResult()) {
|
||||||
StackValue.boxInlineClass(expression.value.type.toIrBasedKotlinType(), mv)
|
StackValue.boxInlineClass(expression.value.type, mv, typeMapper)
|
||||||
}
|
}
|
||||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data, null)
|
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data, null)
|
||||||
expression.markLineNumber(startOffset = true)
|
expression.markLineNumber(startOffset = true)
|
||||||
|
|||||||
+4
-1
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.ir.types.isKClass as isKClassImpl
|
|||||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction as isSuspendFunctionImpl
|
import org.jetbrains.kotlin.ir.util.isSuspendFunction as isSuspendFunctionImpl
|
||||||
|
|
||||||
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase(), TypeMappingContext<JvmSignatureWriter> {
|
class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBase(), TypeMappingContext<JvmSignatureWriter> {
|
||||||
internal val typeSystem = IrTypeSystemContextImpl(context.irBuiltIns)
|
override val typeSystem: IrTypeSystemContext = IrTypeSystemContextImpl(context.irBuiltIns)
|
||||||
override val typeContext: TypeSystemCommonBackendContextForTypeMapping = IrTypeCheckerContextForTypeMapping(typeSystem, context)
|
override val typeContext: TypeSystemCommonBackendContextForTypeMapping = IrTypeCheckerContextForTypeMapping(typeSystem, context)
|
||||||
|
|
||||||
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
override fun mapClass(classifier: ClassifierDescriptor): Type =
|
||||||
@@ -53,6 +53,9 @@ class IrTypeMapper(private val context: JvmBackendContext) : KotlinTypeMapperBas
|
|||||||
error("Unknown descriptor: $classifier")
|
error("Unknown descriptor: $classifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mapTypeCommon(type: KotlinTypeMarker, mode: TypeMappingMode): Type =
|
||||||
|
mapType(type as IrType, mode)
|
||||||
|
|
||||||
private fun computeClassInternalName(irClass: IrClass): StringBuilder {
|
private fun computeClassInternalName(irClass: IrClass): StringBuilder {
|
||||||
context.getLocalClassType(irClass)?.internalName?.let {
|
context.getLocalClassType(irClass)?.internalName?.let {
|
||||||
return StringBuilder(it)
|
return StringBuilder(it)
|
||||||
|
|||||||
+2
-7
@@ -12,15 +12,11 @@ import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
|||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.isTypeParameter
|
import org.jetbrains.kotlin.ir.util.isTypeParameter
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.util.substitute
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
|
||||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
@@ -50,12 +46,12 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
isFromTypeUnboxed && !isToTypeUnboxed -> {
|
isFromTypeUnboxed && !isToTypeUnboxed -> {
|
||||||
StackValue.boxInlineClass(erasedSourceType.toIrBasedKotlinType(), mv)
|
StackValue.boxInlineClass(erasedSourceType, mv, typeMapper)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
!isFromTypeUnboxed && isToTypeUnboxed -> {
|
!isFromTypeUnboxed && isToTypeUnboxed -> {
|
||||||
StackValue.unboxInlineClass(type, erasedTargetType.toIrBasedKotlinType(), mv)
|
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +60,6 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
|
|||||||
if (type != target || (castForReified && irType.anyTypeArgument { it.isReified })) {
|
if (type != target || (castForReified && irType.anyTypeArgument { it.isReified })) {
|
||||||
StackValue.coerce(type, target, mv, type == target)
|
StackValue.coerce(type, target, mv, type == target)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun discard()
|
abstract fun discard()
|
||||||
|
|||||||
@@ -431,20 +431,22 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
irClass.kind != ClassKind.INTERFACE && irClass.kind != ClassKind.ANNOTATION_CLASS
|
irClass.kind != ClassKind.INTERFACE && irClass.kind != ClassKind.ANNOTATION_CLASS
|
||||||
} ?: owner.superTypes.first()
|
} ?: owner.superTypes.first()
|
||||||
|
|
||||||
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
// Code in inlineClassesUtils.kt loads the property with the same name from the scope of the substituted type and takes its type.
|
// Code in inlineClassesUtils.kt loads the property with the same name from the scope of the substituted type and takes its type.
|
||||||
// This code below should have the same effect.
|
// This code below should have the same effect.
|
||||||
val irClass = (this as? IrType)?.classOrNull?.owner?.takeIf { it.isInline } ?: return null
|
val irClass = (this as? IrType)?.classOrNull?.owner?.takeIf { it.isInline }
|
||||||
val inlineClassParameter = irClass.primaryConstructor?.valueParameters?.singleOrNull()
|
return irClass?.primaryConstructor?.valueParameters?.singleOrNull()?.type
|
||||||
return inlineClassParameter?.let { parameter ->
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? =
|
||||||
|
getUnsubstitutedUnderlyingType()?.let { type ->
|
||||||
// Taking only the type parameters of the class (and not its outer classes) is OK since inner classes are always top level
|
// Taking only the type parameters of the class (and not its outer classes) is OK since inner classes are always top level
|
||||||
IrTypeSubstitutor(
|
IrTypeSubstitutor(
|
||||||
irClass.typeParameters.map { it.symbol },
|
(this as IrType).getClass()!!.typeParameters.map { it.symbol },
|
||||||
(this as? IrSimpleType)?.arguments.orEmpty(),
|
(this as? IrSimpleType)?.arguments.orEmpty(),
|
||||||
irBuiltIns
|
irBuiltIns
|
||||||
).substitute(parameter.type)
|
).substitute(type as IrType)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun TypeConstructorMarker.getPrimitiveType(): PrimitiveType? {
|
override fun TypeConstructorMarker.getPrimitiveType(): PrimitiveType? {
|
||||||
if (this !is IrClassSymbol) return null
|
if (this !is IrClassSymbol) return null
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
|
|||||||
fun TypeConstructorMarker.isInlineClass(): Boolean
|
fun TypeConstructorMarker.isInlineClass(): Boolean
|
||||||
fun TypeConstructorMarker.isInnerClass(): Boolean
|
fun TypeConstructorMarker.isInnerClass(): Boolean
|
||||||
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
||||||
|
fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker?
|
||||||
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker?
|
||||||
|
|
||||||
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
|
fun KotlinTypeMarker.makeNullable(): KotlinTypeMarker =
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||||
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
||||||
|
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
@@ -645,6 +646,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return representativeUpperBound
|
return representativeUpperBound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
|
require(this is KotlinType, this::errorMessage)
|
||||||
|
return unsubstitutedUnderlyingType()
|
||||||
|
}
|
||||||
|
|
||||||
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
override fun KotlinTypeMarker.getSubstitutedUnderlyingType(): KotlinTypeMarker? {
|
||||||
require(this is KotlinType, this::errorMessage)
|
require(this is KotlinType, this::errorMessage)
|
||||||
return substitutedUnderlyingType()
|
return substitutedUnderlyingType()
|
||||||
|
|||||||
Reference in New Issue
Block a user