JVM IR: reuse JVM code for reified type parameter mappings instead of copy-paste
This commit is contained in:
@@ -17,8 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.inline.NameGenerator
|
import org.jetbrains.kotlin.codegen.inline.NameGenerator
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putReifiedOperationMarker
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
interface BaseExpressionCodegen {
|
interface BaseExpressionCodegen {
|
||||||
@@ -29,6 +34,8 @@ interface BaseExpressionCodegen {
|
|||||||
|
|
||||||
val inlineNameGenerator: NameGenerator
|
val inlineNameGenerator: NameGenerator
|
||||||
|
|
||||||
|
val typeSystem: TypeSystemCommonBackendContext
|
||||||
|
|
||||||
val lastLineNumber: Int
|
val lastLineNumber: Int
|
||||||
|
|
||||||
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
|
||||||
@@ -41,4 +48,17 @@ interface BaseExpressionCodegen {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun markLineNumberAfterInlineIfNeeded()
|
fun markLineNumberAfterInlineIfNeeded()
|
||||||
|
|
||||||
|
fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker)
|
||||||
|
|
||||||
|
@JvmDefault
|
||||||
|
fun putReifiedOperationMarkerIfTypeIsReifiedParameter(type: KotlinTypeMarker, operationKind: OperationKind) {
|
||||||
|
with(typeSystem) {
|
||||||
|
val (typeParameter, second) = extractReificationArgument(type) ?: return
|
||||||
|
if (typeParameter.isReified()) {
|
||||||
|
consumeReifiedOperationMarker(typeParameter)
|
||||||
|
putReifiedOperationMarker(operationKind, second, visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
|||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.*;
|
||||||
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContextImpl;
|
import org.jetbrains.kotlin.types.checker.ClassicTypeSystemContextImpl;
|
||||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
|
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker;
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||||
import org.jetbrains.org.objectweb.asm.Label;
|
import org.jetbrains.org.objectweb.asm.Label;
|
||||||
@@ -123,7 +124,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
private final TailRecursionCodegen tailRecursionCodegen;
|
private final TailRecursionCodegen tailRecursionCodegen;
|
||||||
public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this);
|
public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this);
|
||||||
private final SwitchCodegenProvider switchCodegenProvider;
|
private final SwitchCodegenProvider switchCodegenProvider;
|
||||||
public final TypeSystemCommonBackendContext typeSystem;
|
private final TypeSystemCommonBackendContext typeSystem;
|
||||||
|
|
||||||
private final Stack<BlockStackElement> blockStackElements = new Stack<>();
|
private final Stack<BlockStackElement> blockStackElements = new Stack<>();
|
||||||
|
|
||||||
@@ -2679,7 +2680,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
||||||
|
|
||||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
Pair<TypeParameterMarker, ReificationArgument> typeParameterAndReificationArgument =
|
||||||
|
extractReificationArgument(typeSystem, type);
|
||||||
if (typeParameterAndReificationArgument == null) {
|
if (typeParameterAndReificationArgument == null) {
|
||||||
KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper();
|
KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper();
|
||||||
// type is not generic
|
// type is not generic
|
||||||
@@ -4841,19 +4843,6 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
|
||||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
|
||||||
) {
|
|
||||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
|
||||||
if (typeParameterAndReificationArgument == null) return;
|
|
||||||
|
|
||||||
TypeParameterDescriptor typeParameter = typeParameterAndReificationArgument.getFirst();
|
|
||||||
if (typeParameter.isReified()) {
|
|
||||||
consumeReifiedOperationMarker(typeParameter);
|
|
||||||
ReifiedTypeInliner.putReifiedOperationMarker(operationKind, typeParameterAndReificationArgument.getSecond(), v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
|
||||||
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(
|
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(
|
||||||
@@ -5077,10 +5066,18 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void consumeReifiedOperationMarker(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeSystemCommonBackendContext getTypeSystem() {
|
||||||
|
return typeSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consumeReifiedOperationMarker(@NotNull TypeParameterMarker typeParameter) {
|
||||||
|
assert typeParameter instanceof TypeParameterDescriptor : "Type parameter should be a descriptor: " + typeParameter;
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) typeParameter;
|
||||||
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||||
parentCodegen.getReifiedTypeParametersUsages().
|
parentCodegen.getReifiedTypeParametersUsages().addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||||
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,11 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor.CoroutinesCompatibilityMode
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
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.*
|
||||||
@@ -381,18 +384,21 @@ fun InstructionAdapter.generateNewInstanceDupAndPlaceBeforeStackTop(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractReificationArgument(initialType: KotlinType): Pair<TypeParameterDescriptor, ReificationArgument>? {
|
fun TypeSystemCommonBackendContext.extractReificationArgument(initialType: KotlinTypeMarker): Pair<TypeParameterMarker, ReificationArgument>? {
|
||||||
var type = initialType
|
var type = initialType
|
||||||
var arrayDepth = 0
|
var arrayDepth = 0
|
||||||
val isNullable = type.isMarkedNullable
|
val isNullable = type.isMarkedNullable()
|
||||||
while (KotlinBuiltIns.isArray(type)) {
|
while (type.isArrayOrNullableArray()) {
|
||||||
arrayDepth++
|
arrayDepth++
|
||||||
type = type.arguments[0].type
|
val argument = type.getArgument(0)
|
||||||
|
type =
|
||||||
|
if (argument.isStarProjection()) nullableAnyType()
|
||||||
|
else argument.getType()
|
||||||
}
|
}
|
||||||
|
|
||||||
val parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type) ?: return null
|
val typeParameter = type.typeConstructor().getTypeParameterClassifier() ?: return null
|
||||||
|
|
||||||
return Pair(parameterDescriptor, ReificationArgument(parameterDescriptor.name.asString(), isNullable, arrayDepth))
|
return Pair(typeParameter, ReificationArgument(typeParameter.getName().asString(), isNullable, arrayDepth))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ import org.jetbrains.kotlin.fir.symbols.*
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl
|
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
@@ -435,6 +433,8 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
|
|
||||||
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker = TODO("not implemented")
|
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker = TODO("not implemented")
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean = TODO("not implemented")
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
||||||
val firRegularClass = toFirRegularClass() ?: return false
|
val firRegularClass = toFirRegularClass() ?: return false
|
||||||
|
|
||||||
|
|||||||
+23
-138
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.codegen.CallGenerator
|
|||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME
|
||||||
|
import org.jetbrains.kotlin.codegen.extractReificationArgument
|
||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
||||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
||||||
@@ -45,6 +46,8 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
@@ -116,6 +119,9 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
override val inlineNameGenerator: NameGenerator = NameGenerator("${classCodegen.type.internalName}\$todo") // TODO
|
override val inlineNameGenerator: NameGenerator = NameGenerator("${classCodegen.type.internalName}\$todo") // TODO
|
||||||
|
|
||||||
|
override val typeSystem: TypeSystemCommonBackendContext
|
||||||
|
get() = typeMapper.typeSystem
|
||||||
|
|
||||||
override var lastLineNumber: Int = -1
|
override var lastLineNumber: Int = -1
|
||||||
|
|
||||||
private val closureReifiedMarkers = hashMapOf<IrClass, ReifiedTypeParametersUsages>()
|
private val closureReifiedMarkers = hashMapOf<IrClass, ReifiedTypeParametersUsages>()
|
||||||
@@ -319,8 +325,9 @@ class ExpressionCodegen(
|
|||||||
mv.load(0, OBJECT_TYPE)
|
mv.load(0, OBJECT_TYPE)
|
||||||
|
|
||||||
for (argumentIndex in 0 until expression.typeArgumentsCount) {
|
for (argumentIndex in 0 until expression.typeArgumentsCount) {
|
||||||
expression.getTypeArgument(argumentIndex)?.getTypeParameterOrNull()?.takeIf { it.isReified }?.let {
|
val classifier = expression.getTypeArgument(argumentIndex)?.classifierOrNull
|
||||||
consumeReifiedOperationMarker(it)
|
if (classifier is IrTypeParameterSymbol && classifier.owner.isReified) {
|
||||||
|
consumeReifiedOperationMarker(classifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,7 +612,7 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
if (typeOperand.isReifiedTypeParameter) {
|
if (typeOperand.isReifiedTypeParameter) {
|
||||||
val operationKind = if (expression.operator == IrTypeOperator.CAST) AS else SAFE_AS
|
val operationKind = if (expression.operator == IrTypeOperator.CAST) AS else SAFE_AS
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, operationKind, mv, this)
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, operationKind)
|
||||||
v.checkcast(boxedRightType)
|
v.checkcast(boxedRightType)
|
||||||
} else {
|
} else {
|
||||||
assert(expression.operator == IrTypeOperator.CAST) { "IrTypeOperator.SAFE_CAST should have been lowered." }
|
assert(expression.operator == IrTypeOperator.CAST) { "IrTypeOperator.SAFE_CAST should have been lowered." }
|
||||||
@@ -618,7 +625,7 @@ class ExpressionCodegen(
|
|||||||
expression.argument.accept(this, data).coerce(context.irBuiltIns.anyNType).materialize()
|
expression.argument.accept(this, data).coerce(context.irBuiltIns.anyNType).materialize()
|
||||||
val type = typeMapper.boxType(typeOperand)
|
val type = typeMapper.boxType(typeOperand)
|
||||||
if (typeOperand.isReifiedTypeParameter) {
|
if (typeOperand.isReifiedTypeParameter) {
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS, mv, this)
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS)
|
||||||
v.instanceOf(type)
|
v.instanceOf(type)
|
||||||
} else {
|
} else {
|
||||||
TypeIntrinsics.instanceOf(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
|
TypeIntrinsics.instanceOf(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
|
||||||
@@ -906,7 +913,7 @@ class ExpressionCodegen(
|
|||||||
assert(classifier.owner.isReified) {
|
assert(classifier.owner.isReified) {
|
||||||
"Non-reified type parameter under ::class should be rejected by type checker: ${classifier.owner.dump()}"
|
"Non-reified type parameter under ::class should be rejected by type checker: ${classifier.owner.dump()}"
|
||||||
}
|
}
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(classType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(classType, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
|
||||||
}
|
}
|
||||||
|
|
||||||
generateClassInstance(mv, classType)
|
generateClassInstance(mv, classType)
|
||||||
@@ -948,9 +955,9 @@ class ExpressionCodegen(
|
|||||||
element.getTypeArgumentOrDefault(it)
|
element.getTypeArgumentOrDefault(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mappings = IrTypeParameterMappings()
|
val mappings = TypeParameterMappings<IrType>()
|
||||||
for ((key, type) in typeArguments.entries) {
|
for ((key, type) in typeArguments.entries) {
|
||||||
val reificationArgument = extractReificationArgument(type)
|
val reificationArgument = typeMapper.typeSystem.extractReificationArgument(type)
|
||||||
if (reificationArgument == null) {
|
if (reificationArgument == null) {
|
||||||
// type is not generic
|
// type is not generic
|
||||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||||
@@ -961,7 +968,7 @@ class ExpressionCodegen(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
mappings.addParameterMappingForFurtherReification(
|
mappings.addParameterMappingForFurtherReification(
|
||||||
key.name.identifier, type, reificationArgument, key.isReified
|
key.name.identifier, type, reificationArgument.second, key.isReified
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -969,9 +976,8 @@ class ExpressionCodegen(
|
|||||||
val original = (callee as? IrSimpleFunction)?.resolveFakeOverride() ?: irFunction
|
val original = (callee as? IrSimpleFunction)?.resolveFakeOverride() ?: irFunction
|
||||||
val methodOwner = callee.parent.safeAs<IrClass>()?.let(typeMapper::mapClass) ?: MethodSignatureMapper.FAKE_OWNER_TYPE
|
val methodOwner = callee.parent.safeAs<IrClass>()?.let(typeMapper::mapClass) ?: MethodSignatureMapper.FAKE_OWNER_TYPE
|
||||||
val sourceCompiler = IrSourceCompilerForInline(state, element, this, data)
|
val sourceCompiler = IrSourceCompilerForInline(state, element, this, data)
|
||||||
val typeParameterMappings = mappings.toTypeParameterMappings()
|
|
||||||
|
|
||||||
val reifiedTypeInliner = ReifiedTypeInliner(typeParameterMappings, object : ReifiedTypeInliner.IntrinsicsSupport<IrType> {
|
val reifiedTypeInliner = ReifiedTypeInliner(mappings, object : ReifiedTypeInliner.IntrinsicsSupport<IrType> {
|
||||||
override fun putClassInstance(v: InstructionAdapter, type: IrType) {
|
override fun putClassInstance(v: InstructionAdapter, type: IrType) {
|
||||||
generateClassInstance(v, type)
|
generateClassInstance(v, type)
|
||||||
}
|
}
|
||||||
@@ -980,13 +986,14 @@ class ExpressionCodegen(
|
|||||||
}, IrTypeCheckerContext(context.irBuiltIns), state.languageVersionSettings)
|
}, IrTypeCheckerContext(context.irBuiltIns), state.languageVersionSettings)
|
||||||
|
|
||||||
return IrInlineCodegen(
|
return IrInlineCodegen(
|
||||||
this, state, original.descriptor, methodOwner, signature, typeParameterMappings, sourceCompiler, reifiedTypeInliner
|
this, state, original.descriptor, methodOwner, signature, mappings, sourceCompiler, reifiedTypeInliner
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeReifiedOperationMarker(typeParameter: IrTypeParameter) {
|
override fun consumeReifiedOperationMarker(typeParameter: TypeParameterMarker) {
|
||||||
if (typeParameter.parent != irFunction) {
|
require(typeParameter is IrTypeParameterSymbol)
|
||||||
classCodegen.reifiedTypeParametersUsages.addUsedReifiedParameter(typeParameter.name.asString())
|
if (typeParameter.owner.parent != irFunction) {
|
||||||
|
classCodegen.reifiedTypeParametersUsages.addUsedReifiedParameter(typeParameter.owner.name.asString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,128 +1022,6 @@ class ExpressionCodegen(
|
|||||||
return irFunction.isInline || isInlineLambda
|
return irFunction.isInline || isInlineLambda
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Borrowed and modified from compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt */
|
private val IrType.isReifiedTypeParameter: Boolean
|
||||||
|
get() = this.classifierOrNull?.safeAs<IrTypeParameterSymbol>()?.owner?.isReified == true
|
||||||
private fun extractReificationArgumentWithParameter(initialType: IrType): Pair<IrTypeParameter, IrReificationArgument>? {
|
|
||||||
var type = initialType
|
|
||||||
var arrayDepth = 0
|
|
||||||
val isNullable = type.isMarkedNullable()
|
|
||||||
while (type.isArray() || type.isNullableArray()) {
|
|
||||||
arrayDepth++
|
|
||||||
type = (type as IrSimpleType).arguments[0].safeAs<IrTypeProjection>()?.type ?: classCodegen.context.irBuiltIns.anyNType
|
|
||||||
}
|
|
||||||
|
|
||||||
val parameter = type.getTypeParameterOrNull() ?: return null
|
|
||||||
|
|
||||||
return Pair(parameter, IrReificationArgument(parameter.name.asString(), isNullable, arrayDepth))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractReificationArgument(initialType: IrType): IrReificationArgument? = extractReificationArgumentWithParameter(initialType)?.second
|
|
||||||
|
|
||||||
/* From ReifiedTypeInliner.kt */
|
|
||||||
inner class IrReificationArgument(
|
|
||||||
val parameterName: String, val nullable: Boolean, private val arrayDepth: Int
|
|
||||||
) {
|
|
||||||
fun asString() = "[".repeat(arrayDepth) + parameterName + (if (nullable) "?" else "")
|
|
||||||
fun combine(replacement: IrReificationArgument) =
|
|
||||||
IrReificationArgument(
|
|
||||||
replacement.parameterName,
|
|
||||||
this.nullable || (replacement.nullable && this.arrayDepth == 0),
|
|
||||||
this.arrayDepth + replacement.arrayDepth
|
|
||||||
)
|
|
||||||
|
|
||||||
fun reify(replacementAsmType: Type, irType: IrType) =
|
|
||||||
Pair(
|
|
||||||
Type.getType("[".repeat(arrayDepth) + replacementAsmType),
|
|
||||||
irType.arrayOf(arrayDepth).withHasQuestionMark(nullable)
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun IrType.arrayOf(arrayDepth: Int): IrType {
|
|
||||||
val builtins = classCodegen.context.irBuiltIns
|
|
||||||
var currentType = this
|
|
||||||
|
|
||||||
repeat(arrayDepth) {
|
|
||||||
currentType = builtins.arrayClass.typeWith(currentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentType
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toReificationArgument() = ReificationArgument(parameterName, nullable, arrayDepth)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* From ExpressionCodegen.java */
|
|
||||||
fun putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
|
||||||
type: IrType, operationKind: ReifiedTypeInliner.OperationKind, v: InstructionAdapter,
|
|
||||||
codegen: ExpressionCodegen?
|
|
||||||
) {
|
|
||||||
val typeParameterAndReificationArgument = extractReificationArgumentWithParameter(type)
|
|
||||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.first.isReified) {
|
|
||||||
val irTypeParameter = typeParameterAndReificationArgument.first
|
|
||||||
codegen?.consumeReifiedOperationMarker(irTypeParameter)
|
|
||||||
ReifiedTypeInliner.putReifiedOperationMarker(
|
|
||||||
operationKind, typeParameterAndReificationArgument.second.toReificationArgument(), v
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val IrType.isReifiedTypeParameter: Boolean
|
|
||||||
get() = this.classifierOrNull?.safeAs<IrTypeParameterSymbol>()?.owner?.isReified == true
|
|
||||||
|
|
||||||
/* From typeUtil.java */
|
|
||||||
fun IrType.getTypeParameterOrNull() = classifierOrNull?.owner?.safeAs<IrTypeParameter>()
|
|
||||||
|
|
||||||
/* From ReifiedTypeInliner.kt */
|
|
||||||
class IrTypeParameterMappings {
|
|
||||||
private val mappingsByName = hashMapOf<String, IrTypeParameterMapping>()
|
|
||||||
|
|
||||||
fun addParameterMappingToType(name: String, type: IrType, asmType: Type, signature: String, isReified: Boolean) {
|
|
||||||
mappingsByName[name] = IrTypeParameterMapping(
|
|
||||||
name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addParameterMappingForFurtherReification(
|
|
||||||
name: String,
|
|
||||||
type: IrType,
|
|
||||||
reificationArgument: ExpressionCodegen.IrReificationArgument,
|
|
||||||
isReified: Boolean
|
|
||||||
) {
|
|
||||||
mappingsByName[name] = IrTypeParameterMapping(
|
|
||||||
name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun get(name: String): IrTypeParameterMapping? = mappingsByName[name]
|
|
||||||
|
|
||||||
fun hasReifiedParameters() = mappingsByName.values.any { it.isReified }
|
|
||||||
|
|
||||||
internal inline fun forEach(l: (IrTypeParameterMapping) -> Unit) {
|
|
||||||
mappingsByName.values.forEach(l)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toTypeParameterMappings() = TypeParameterMappings<IrType>().also { result ->
|
|
||||||
mappingsByName.forEach { (_, value) ->
|
|
||||||
if (value.asmType == null) {
|
|
||||||
result.addParameterMappingForFurtherReification(
|
|
||||||
value.name,
|
|
||||||
value.type,
|
|
||||||
value.reificationArgument!!.toReificationArgument(),
|
|
||||||
value.isReified
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
result.addParameterMappingToType(value.name, value.type, value.asmType, value.signature!!, value.isReified)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IrTypeParameterMapping(
|
|
||||||
val name: String,
|
|
||||||
val type: IrType,
|
|
||||||
val asmType: Type?,
|
|
||||||
val reificationArgument: ExpressionCodegen.IrReificationArgument?,
|
|
||||||
val signature: String?,
|
|
||||||
val isReified: Boolean
|
|
||||||
)
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
class IrTypeMapper(private val context: JvmBackendContext) {
|
class IrTypeMapper(private val context: JvmBackendContext) {
|
||||||
private val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
internal val typeSystem = IrTypeCheckerContext(context.irBuiltIns)
|
||||||
|
|
||||||
fun classInternalName(irClass: IrClass): String =
|
fun classInternalName(irClass: IrClass): String =
|
||||||
context.getLocalClassInfo(irClass)?.internalName
|
context.getLocalClassInfo(irClass)?.internalName
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ object NewArray : IntrinsicMethod() {
|
|||||||
return with(codegen) {
|
return with(codegen) {
|
||||||
val elementIrType = expression.type.getArrayElementType(context.irBuiltIns)
|
val elementIrType = expression.type.getArrayElementType(context.irBuiltIns)
|
||||||
if (expression.type.isArray()) {
|
if (expression.type.isArray()) {
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY)
|
||||||
elementIrType, ReifiedTypeInliner.OperationKind.NEW_ARRAY, mv, this
|
|
||||||
)
|
|
||||||
mv.newarray(typeMapper.boxType(elementIrType))
|
mv.newarray(typeMapper.boxType(elementIrType))
|
||||||
} else {
|
} else {
|
||||||
mv.newarray(typeMapper.mapType(elementIrType))
|
mv.newarray(typeMapper.mapType(elementIrType))
|
||||||
|
|||||||
@@ -273,6 +273,9 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker =
|
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker =
|
||||||
irBuiltIns.arrayClass.typeWith(componentType as IrType)
|
irBuiltIns.arrayClass.typeWith(componentType as IrType)
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean =
|
||||||
|
(this as IrType).isArray() || isNullableArray()
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
override fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean {
|
||||||
val symbol = this as IrClassifierSymbol
|
val symbol = this as IrClassifierSymbol
|
||||||
return symbol is IrClassSymbol && symbol.owner.let {
|
return symbol is IrClassSymbol && symbol.owner.let {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.types.model.*
|
|||||||
interface TypeSystemCommonBackendContext : TypeSystemContext {
|
interface TypeSystemCommonBackendContext : TypeSystemContext {
|
||||||
fun nullableAnyType(): SimpleTypeMarker
|
fun nullableAnyType(): SimpleTypeMarker
|
||||||
fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker
|
fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker
|
||||||
|
fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean
|
||||||
|
|
||||||
fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean
|
fun TypeConstructorMarker.isFinalClassOrEnumEntryOrAnnotationClassConstructor(): Boolean
|
||||||
|
|
||||||
|
|||||||
@@ -508,6 +508,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return builtIns.getArrayType(Variance.INVARIANT, componentType)
|
return builtIns.getArrayType(Variance.INVARIANT, componentType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.isArrayOrNullableArray(): Boolean {
|
||||||
|
require(this is KotlinType, this::errorMessage)
|
||||||
|
return KotlinBuiltIns.isArray(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean {
|
override fun KotlinTypeMarker.hasAnnotation(fqName: FqName): Boolean {
|
||||||
require(this is KotlinType, this::errorMessage)
|
require(this is KotlinType, this::errorMessage)
|
||||||
return annotations.hasAnnotation(fqName)
|
return annotations.hasAnnotation(fqName)
|
||||||
|
|||||||
Reference in New Issue
Block a user