JVM IR: reuse JVM code for reified type parameter mappings instead of copy-paste

This commit is contained in:
Alexander Udalov
2019-09-04 16:19:14 +02:00
parent d1df453edc
commit d16bdded7f
10 changed files with 83 additions and 168 deletions
@@ -17,8 +17,13 @@
package org.jetbrains.kotlin.codegen
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.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
interface BaseExpressionCodegen {
@@ -29,6 +34,8 @@ interface BaseExpressionCodegen {
val inlineNameGenerator: NameGenerator
val typeSystem: TypeSystemCommonBackendContext
val lastLineNumber: Int
fun propagateChildReifiedTypeParametersUsages(reifiedTypeParametersUsages: ReifiedTypeParametersUsages)
@@ -41,4 +48,17 @@ interface BaseExpressionCodegen {
)
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.checker.ClassicTypeSystemContextImpl;
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.util.OperatorNameConventions;
import org.jetbrains.org.objectweb.asm.Label;
@@ -123,7 +124,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private final TailRecursionCodegen tailRecursionCodegen;
public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this);
private final SwitchCodegenProvider switchCodegenProvider;
public final TypeSystemCommonBackendContext typeSystem;
private final TypeSystemCommonBackendContext typeSystem;
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());
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
Pair<TypeParameterMarker, ReificationArgument> typeParameterAndReificationArgument =
extractReificationArgument(typeSystem, type);
if (typeParameterAndReificationArgument == null) {
KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper();
// 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
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(
@@ -5077,10 +5066,18 @@ The "returned" value of try expression with no finally is either the last expres
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()) {
parentCodegen.getReifiedTypeParametersUsages().
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
parentCodegen.getReifiedTypeParametersUsages().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.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.TypeUtils
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.org.objectweb.asm.Label
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 arrayDepth = 0
val isNullable = type.isMarkedNullable
while (KotlinBuiltIns.isArray(type)) {
val isNullable = type.isMarkedNullable()
while (type.isArrayOrNullableArray()) {
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 =