This instruction implements a goto expression that can jump out of any expression. It pops values (arguments) from the evaluation stack that the expression tree nodes in between the goto expression and the target label node pushed and not consumed yet. A goto expression can jump into a node that evaluates arguments only if it carries a value and jumps right after the first argument (the carried value will be used as the first argument). Goto can jump into an arbitrary child of a BlockExpression since the block doesn’t accumulate values on evaluation stack as its child expressions are being evaluated. Goto needs to execute any finally blocks on the way to the target label. { f(1, 2, try { g(3, 4, try { goto L } finally { ... }, 6) } finally { ... }, 7, 8) L: ... } The goto expression here jumps to label L while having 4 items on evaluation stack (1, 2, 3 and 4). The jump needs to execute both finally blocks, the first one on stack level 4 the second one on stack level 2. So, it needs to jump the first finally block, pop 2 items from the stack, run second finally block and pop another 2 items from the stack and set instruction pointer to label L. Goto also needs to rethrow ThreadAbortException iff it jumps out of a catch handler and the current thread is in "abort requested" state.
Inheritance: IndexedBranchInstruction
Esempio n. 1
0
 internal static GotoInstruction Create(int labelIndex, bool hasResult, bool hasValue) {
     if (labelIndex < CacheSize) {
         var index = Variants * labelIndex | (hasResult ? 2 : 0) | (hasValue ? 1 : 0);
         return Cache[index] ?? (Cache[index] = new GotoInstruction(labelIndex, hasResult, hasValue));
     }
     return new GotoInstruction(labelIndex, hasResult, hasValue);
 }
Esempio n. 2
0
 public void EmitGoto(BranchLabel label, bool hasResult, bool hasValue)
 {
     Emit(GotoInstruction.Create(EnsureLabelIndex(label), hasResult, hasValue));
 }