void InitLocalsRefs2(CilType plainType, BoxedType boxedType, bool arg, int index) { if (arg) { code.NewInstruction(plainType.LoadOpcode, null, index); } else { code.NewInstruction(plainType.InitOpcode, null, null); } stackMap.PushStack(plainType); if (boxedType != null) { boxedType.BoxValue(code); } else if (plainType.IsGenericParameter) { GenericUtil.ValueClone(code); } else { CilMethod.ValueMethod(CilMethod.ValueClone, code); code.NewInstruction(0xC0 /* checkcast */, plainType, null); } code.NewInstruction(0x3A /* astore */, null, index); stackMap.PopStack(CilMain.Where); }
public void Length() { var stackTop = (CilType)stackMap.PopStack(CilMain.Where); if (object.ReferenceEquals(stackTop, GenericArrayType)) { // length of a generic array T[] code.NewInstruction(0xB8 /* invokestatic */, new JavaType(0, 0, "java.lang.reflect.Array"), new JavaMethodRef("getLength", JavaType.IntegerType, JavaType.ObjectType)); } else if (stackTop.IsArray) { code.NewInstruction(0xBE /* arraylength */, null, null); } else { throw new InvalidProgramException(); } stackMap.PushStack(CilType.From(JavaType.IntegerType)); }
void ExceptionClauseSetup(ushort instOffset, CatchClause catchClause) { // if this is the first exception for the try block: // // the offset is recorded in the exception attribute, so we need // to generate a stack frame for it, which matches the stack frame // on entry to the try block, with a pushed java.lang.Throwable. var tryClause = catchClause.tryClause; if (catchClause == tryClause.catchClauses[0]) { stackMap.LoadFrame((ushort)tryClause.tryStart, false, CilMain.Where); stackMap.PushStack(ThrowableType); stackMap.SaveFrame((ushort)instOffset, true, CilMain.Where); if (!catchClause.finallyClause) { code.NewInstruction(0xB8 /* invokestatic */, CilType.SystemUtilType, new JavaMethodRef("TranslateException", ThrowableType, ThrowableType)); } } // if this is a finally clause, we have nothing further to do. // but if this is a filter clause, do some additional set up. if (catchClause.finallyClause) { if (catchClause.hasNestedTry) { // see also: ScanCatchClauseForNestedTry SaveExceptionObject(tryClause, false); } if (catchClause.faultClause) { // the 'fault' clause should start with a check whether // an exception was thrown, which is very similar to what // 'endfinally' does at the end of a normal 'finally' block, // so we can reuse the same code. Translate_Endfinally(instOffset, true); } return; } // // if this is a filter clause, we just need to initialize loals // if (catchClause.filterCondStart != 0) { // should the filter test pass, we need push the exception // object. we don't know which local the filter test uses // to store the exception, so we make our own copy. this // will be loaded by the 'endfilter' instruction, see there. SaveExceptionObject(tryClause); return; } // // for a non-filter catch clause that catches any kind of // exception, we don't need to test the exception type at all // if (catchClause.catchType.Equals(ThrowableType)) { if (catchClause.includesRethrow) { SaveExceptionObject(tryClause); } } // // otherwise, we do need to test the exception type, and // possibly branch to a secondary catch clause in the chain. // if (catchClause.catchFromType == null) { // exception type is plain type. we will use follow up // instructions 'ifeq == zero' and 'ifne != zero', // see ExceptionClauseCommon if (catchClause.catchType.Equals(ThrowableType)) { code.NewInstruction(0x04 /* iconst_1 */, null, null); stackMap.PushStack(JavaType.IntegerType); } else { code.NewInstruction(0x59 /* dup */, null, null); stackMap.PushStack(ThrowableType); code.NewInstruction(0xC1 /* instanceof */, catchClause.catchType, null); } } else { // exception type is a generic type. we will use follow up // instructions 'ifnull' and 'ifnonnnull'. // see also below in ExceptionClauseCommon code.NewInstruction(0x59 /* dup */, null, null); stackMap.PushStack(ThrowableType); GenericUtil.CastToGenericType(catchClause.catchFromType, 0, code); } stackMap.PopStack(CilMain.Where); ExceptionClauseCommon(catchClause); }