Example #1
0
        internal static void LoadFrameOrClearStack(JavaStackMap stackMap,
                                                   Mono.Cecil.Cil.Instruction inst)
        {
            // following any instruction that breaks the normal flow of execution,
            // we need to load an stack frame already recorded for some following
            // instruction, if any (e.g. as part of a conditional branch sequence).
            // if there isn't such a frame, just clear and reset the stack frame.

            for (;;)
            {
                inst = inst.Next;
                if (inst == null)
                {
                    break;
                }
                if (stackMap.LoadFrame((ushort)inst.Offset, true, null))
                {
                    return;
                }
                var flowControl = inst.OpCode.FlowControl;
                if (flowControl == Mono.Cecil.Cil.FlowControl.Branch ||
                    flowControl == Mono.Cecil.Cil.FlowControl.Break ||
                    flowControl == Mono.Cecil.Cil.FlowControl.Cond_Branch ||
                    flowControl == Mono.Cecil.Cil.FlowControl.Return ||
                    flowControl == Mono.Cecil.Cil.FlowControl.Throw)
                {
                    break;
                }
            }

            stackMap.ClearStack();
        }
Example #2
0
        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);
        }