Typecheck instructions are supported for reified T
This commit is contained in:
committed by
Andrey Breslav
parent
416ac7917b
commit
f3c49c605f
@@ -3401,16 +3401,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
if (isArray) {
|
||||
gen(args.get(0), Type.INT_TYPE);
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(
|
||||
arrayType.getArguments().get(0).getType()
|
||||
putReifierMarkerIfTypeIsReifiedParameter(
|
||||
arrayType.getArguments().get(0).getType(),
|
||||
ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME
|
||||
);
|
||||
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
|
||||
v.iconst(parameterDescriptor.getIndex());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false
|
||||
);
|
||||
}
|
||||
v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType())));
|
||||
}
|
||||
else {
|
||||
@@ -3702,7 +3696,6 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
JetTypeReference typeReference = expression.getRight();
|
||||
JetType rightType = bindingContext.get(TYPE, typeReference);
|
||||
assert rightType != null;
|
||||
Type rightTypeAsm = boxType(asmType(rightType));
|
||||
JetExpression left = expression.getLeft();
|
||||
DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||
@@ -3724,7 +3717,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
v.instanceOf(rightTypeAsm);
|
||||
generateInstanceOfInstruction(rightType);
|
||||
Label ok = new Label();
|
||||
v.ifne(ok);
|
||||
v.pop();
|
||||
@@ -3732,8 +3725,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
v.mark(ok);
|
||||
}
|
||||
|
||||
v.checkcast(rightTypeAsm);
|
||||
return StackValue.onStack(rightTypeAsm);
|
||||
return generateCheckCastInstruction(rightType);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor);
|
||||
@@ -3786,14 +3778,13 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
Type type = boxType(asmType(jetType));
|
||||
if (jetType.isNullable()) {
|
||||
Label nope = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
v.dup();
|
||||
v.ifnull(nope);
|
||||
v.instanceOf(type);
|
||||
generateInstanceOfInstruction(jetType);
|
||||
v.goTo(end);
|
||||
v.mark(nope);
|
||||
v.pop();
|
||||
@@ -3801,7 +3792,32 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
v.mark(end);
|
||||
}
|
||||
else {
|
||||
v.instanceOf(type);
|
||||
generateInstanceOfInstruction(jetType);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInstanceOfInstruction(@NotNull JetType jetType) {
|
||||
Type type = boxType(asmType(jetType));
|
||||
putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.INSTANCEOF_MARKER_METHOD_NAME);
|
||||
v.instanceOf(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue generateCheckCastInstruction(@NotNull JetType jetType) {
|
||||
Type type = boxType(asmType(jetType));
|
||||
putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.CHECKCAST_MARKER_METHOD_NAME);
|
||||
v.checkcast(type);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
private void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
||||
if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) {
|
||||
v.iconst(typeParameterDescriptor.getIndex());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
|
||||
class object {
|
||||
public val NEW_ARRAY_MARKER_METHOD_NAME: String = "reifyNewArray"
|
||||
public val CHECKCAST_MARKER_METHOD_NAME: String = "reifyCheckcast"
|
||||
public val INSTANCEOF_MARKER_METHOD_NAME: String = "reifyInstanceof"
|
||||
}
|
||||
|
||||
public fun reifyInstructions(instructions: InsnList) {
|
||||
@@ -54,9 +56,12 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList) {
|
||||
val mapping = getTypeParameterMapping(insn) ?: return
|
||||
|
||||
if (mapping.asmType != null) {
|
||||
val asmType = mapping.asmType
|
||||
if (asmType != null) {
|
||||
if (!when (insn.name) {
|
||||
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, mapping.asmType)
|
||||
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
|
||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType)
|
||||
else -> false
|
||||
}) {
|
||||
return
|
||||
@@ -68,10 +73,18 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
}
|
||||
}
|
||||
|
||||
private fun processNewArray(insn: MethodInsnNode, parameter: Type): Boolean {
|
||||
if (insn.getNext()?.getOpcode() != Opcodes.ANEWARRAY) return false
|
||||
val next = insn.getNext() as TypeInsnNode
|
||||
next.desc = parameter.getInternalName()
|
||||
private fun processNewArray(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
|
||||
|
||||
private fun processCheckcast(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.CHECKCAST)
|
||||
|
||||
private fun processInstanceof(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.INSTANCEOF)
|
||||
|
||||
private fun processNextTypeInsn(insn: MethodInsnNode, parameter: Type, expectedNextOpcode: Int): Boolean {
|
||||
if (insn.getNext()?.getOpcode() != expectedNextOpcode) return false
|
||||
(insn.getNext() as TypeInsnNode).desc = parameter.getInternalName()
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user