public override int Run(InterpretedFrame frame)
{
Debug.Assert(_tryHandler != null, "the tryHandler must be set already");
// Push fault.
frame.PushContinuation(_labelIndex);
int prevInstrIndex = frame.InstructionIndex;
frame.InstructionIndex++;
// Start to run the try/fault blocks
Instruction[] instructions = frame.Interpreter.Instructions.Instructions;
// C# 6 has no direct support for fault blocks, but they can be faked or coerced out of the compiler
// in several ways. Catch-and-rethrow can work in specific cases, but not generally as the double-pass
// will not work correctly with filters higher up the call stack. Iterators can be used to produce real
// fault blocks, but it depends on an implementation detail rather than a guarantee, and is rather
// indirect. This leaves using a finally block and not doing anything in it if the body ran to
// completion, which is the approach used here.
bool ranWithoutFault = false;
try
{
// run the try block
int index = frame.InstructionIndex;
while (index >= _tryHandler.TryStartIndex && index < _tryHandler.TryEndIndex)
{
index += instructions[index].Run(frame);
frame.InstructionIndex = index;
}
// run the 'Goto' that jumps out of the try/fault blocks
Debug.Assert(instructions[index] is GotoInstruction, "should be the 'Goto' instruction that jumps out the try/fault");
// if we've arrived here there was no exception thrown. As the fault block won't run, we need to
// pop the continuation for it here, before Gotoing the end of the try/fault.
ranWithoutFault = true;
frame.RemoveContinuation();
frame.InstructionIndex += instructions[index].Run(frame);
}
finally
{
if (!ranWithoutFault)
{
// run the fault block
// we cannot jump out of the finally block, and we cannot have an immediate rethrow in it
int index = frame.InstructionIndex = _tryHandler.FinallyStartIndex;
while (index >= _tryHandler.FinallyStartIndex && index < _tryHandler.FinallyEndIndex)
{
index += instructions[index].Run(frame);
frame.InstructionIndex = index;
}
}
}
return(frame.InstructionIndex - prevInstrIndex);
}