public static void Instance(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst) { if (cilInst.Operand is TypeReference cilType && cilInst.Next != null) { var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where); if (!stackTop.IsReference) { throw new InvalidProgramException(); // top of stack is a primitive type } var castType = (CilType)CilType.From(cilType); JavaType castClass = CilType.From(cilType).AsWritableClass; if (GenericUtil.ShouldCallGenericCast(stackTop, castType) || castType.IsGenericParameter) { code.StackMap.PushStack(stackTop); // casting to a generic type is done via GenericType.TestCast GenericUtil.CastToGenericType(cilType, 0, code); code.StackMap.PopStack(CilMain.Where); // stackTop if (!castType.IsGenericParameter) { code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } else if (CodeArrays.CheckCast(castType, false, code)) { // if casting to Object[], ValueType[], to an array of // interface type, or to an array of a generic parameter, // then CodeArrays.CheckCast already generated a call to // system.Array.CheckCast in baselib, and we are done here if (!castType.IsGenericParameter) { // avoid cast since T[] might be a primitive array code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } // // the cil 'isinst' casts the operand to the requested class, // but the jvm 'instanceof' only returns zero or one. so we // also use 'checkcast' to get the jvm to acknowledge the cast // // however, if the cil 'isinst' is immediately followed by // 'brtrue' or 'brfalse' then we don't have to actually cast // else if (!TestForBranch(code, castClass, cilInst.Next)) { ushort nextLabel = (ushort)cilInst.Next.Offset; int localIndex = locals.GetTempIndex(stackTop); TestAndCast(code, castClass, stackTop, nextLabel, localIndex); locals.FreeTempIndex(localIndex); } }
void CastToClass(object data) { var srcType = (CilType)code.StackMap.PopStack(CilMain.Where); if (!(srcType.IsReference && data is TypeReference)) { throw new InvalidProgramException(); } byte op; var dstType = (CilType)CilType.From((TypeReference)data); if (GenericUtil.ShouldCallGenericCast(srcType, dstType)) { code.StackMap.PushStack(srcType); // casting to a generic type is done via GenericType.TestCast GenericUtil.CastToGenericType((TypeReference)data, 1, code); code.StackMap.PopStack(CilMain.Where); // srcType op = 0xC0; // checkcast } else { // cast to a non-generic type if (dstType.Equals(srcType) || dstType.Equals(JavaType.ObjectType)) { op = 0x00; // nop } else if (dstType.IsReference) { CodeArrays.CheckCast(dstType, true, code); if (srcType.ArrayRank != 0 && srcType.ArrayRank == dstType.ArrayRank && srcType.PrimitiveType != 0 && dstType.PrimitiveType != 0 && srcType.AdjustRank(-srcType.ArrayRank).NewArrayType == dstType.AdjustRank(-dstType.ArrayRank).NewArrayType) { // casting to same java array type, e.g. byte[] to sbyte[] op = 0x00; // nop } else if (dstType.IsGenericParameter) { op = 0x00; // nop } else { op = 0xC0; // checkcast } } else { throw new InvalidProgramException(); } } code.NewInstruction(op, dstType, null); code.StackMap.PushStack(dstType); }
public static bool MaybeGetProxy(CilType fromType, CilType intoType, JavaCode code) { if (fromType.IsArray || object.ReferenceEquals(fromType, GenericArrayType) || fromType.Equals(JavaType.StringType)) { if (GenericUtil.ShouldCallGenericCast(fromType, intoType)) { code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, GetProxyMethod); return(true); } } return(false); }
void CastToClass(object data) { var srcType = (CilType)code.StackMap.PopStack(CilMain.Where); if (!(srcType.IsReference && data is TypeReference)) { throw new InvalidProgramException(); } byte op; var dstType = (CilType)CilType.From((TypeReference)data); if (GenericUtil.ShouldCallGenericCast(srcType, dstType)) { code.StackMap.PushStack(srcType); // casting to a generic type is done via GenericType.TestCast GenericUtil.CastToGenericType((TypeReference)data, 1, code); code.StackMap.PopStack(CilMain.Where); // srcType op = 0xC0; // checkcast } else { // cast to a non-generic type if (dstType.Equals(srcType) || dstType.Equals(JavaType.ObjectType)) { op = 0x00; // nop } else if (dstType.IsReference) { CodeArrays.CheckCast(dstType, true, code); op = 0xC0; // checkcast } else { throw new InvalidProgramException(); } } code.NewInstruction(op, dstType, null); code.StackMap.PushStack(dstType); }