/// <summary> /// Produces a Try/Finally if frame has a handler (otherwise a regular block). /// Handler goes into the Finally. /// If there are nested frames, they are emitted into the try block. /// This way the handler for the current frame is guaranteed to run even if /// nested handlers throw exceptions. /// /// { /// switch(state) /// { /// case state1: /// case state2: /// case state3: /// case state4: /// try /// { /// switch(state) /// { /// case state3: /// case state4: /// try /// { /// ... more nested state dispatches if any .... /// } /// finally /// { /// // handler for a try where state3 and state4 can be observed /// handler_3_4() /// } /// break; /// } /// } /// finally /// { /// // handler for a try where state1 and state2 can be observed /// handler_1_2() /// } /// break; /// /// case state5: /// ... another dispatch of nested states to their finally blocks ... /// break; /// } /// } /// /// </summary> private BoundStatement EmitFinallyFrame(IteratorFinallyFrame frame, BoundLocal state) { BoundStatement body = null; if (frame.knownStates != null) { var breakLabel = F.GenerateLabel("break"); var sections = from ft in frame.knownStates group ft.Key by ft.Value into g select F.SwitchSection( new List <int>(g), EmitFinallyFrame(g.Key, state), F.Goto(breakLabel)); body = F.Block( F.Switch(state, sections.ToImmutableArray()), F.Label(breakLabel)); } if (!frame.IsRoot()) { var tryBlock = body != null?F.Block(body) : F.Block(); body = F.Try( tryBlock, ImmutableArray <BoundCatchBlock> .Empty, F.Block(F.ExpressionStatement(F.Call(F.This(), frame.handler)))); } Debug.Assert(body != null, "we should have either sub-dispatch or a handler"); return(body); }
private IteratorFinallyFrame PushFrame(BoundTryStatement statement) { var state = _nextFinalizeState--; var finallyMethod = MakeSynthesizedFinally(state); var newFrame = new IteratorFinallyFrame(_currentFinallyFrame, state, finallyMethod, _yieldsInTryAnalysis.Labels(statement)); newFrame.AddState(state); _currentFinallyFrame = newFrame; return(newFrame); }
public IteratorFinallyFrame( IteratorFinallyFrame parent, int finalizeState, IteratorFinallyMethodSymbol handler, HashSet<LabelSymbol> labels) { Debug.Assert(parent != null, "non root frame must have a parent"); Debug.Assert((object)handler != null, "non root frame must have a handler"); this.parent = parent; this.finalizeState = finalizeState; this.handler = handler; this.labels = labels; }
public IteratorFinallyFrame( IteratorFinallyFrame parent, int finalizeState, IteratorFinallyMethodSymbol handler, HashSet <LabelSymbol> labels) { Debug.Assert(parent != null, "non root frame must have a parent"); Debug.Assert((object)handler != null, "non root frame must have a handler"); this.parent = parent; this.finalizeState = finalizeState; this.handler = handler; this.labels = labels; }
// Notifies all parents about the state recursively. // All parents need to know states they recursively contain and what // immediate child can handle every particular state. private void AddState(int state, IteratorFinallyFrame innerHandler) { var knownStates = this.knownStates; if (knownStates == null) { this.knownStates = knownStates = new Dictionary<int, IteratorFinallyFrame>(); } knownStates.Add(state, innerHandler); if (parent != null) { // Present ourselves to the parent as responsible for a handling a state. parent.AddState(state, this); } }
// Notifies all parents about the state recursively. // All parents need to know states they recursively contain and what // immediate child can handle every particular state. private void AddState(int state, IteratorFinallyFrame innerHandler) { var knownStates = this.knownStates; if (knownStates == null) { this.knownStates = knownStates = new Dictionary <int, IteratorFinallyFrame>(); } knownStates.Add(state, innerHandler); if (parent != null) { // Present ourselves to the parent as responsible for a handling a state. parent.AddState(state, this); } }
private IteratorFinallyFrame PushFrame(BoundTryStatement statement) { var syntax = statement.Syntax; if (slotAllocatorOpt?.TryGetPreviousStateMachineState(syntax, out var finalizeState) != true) { finalizeState = _nextFinalizeState--; } AddStateDebugInfo(syntax, finalizeState); var finallyMethod = MakeSynthesizedFinally(finalizeState); var newFrame = new IteratorFinallyFrame(_currentFinallyFrame, finalizeState, finallyMethod, _yieldsInTryAnalysis.Labels(statement)); newFrame.AddState(finalizeState); _currentFinallyFrame = newFrame; return(newFrame); }
private void PopFrame() { var result = _currentFinallyFrame; _currentFinallyFrame = result.parent; }
private IteratorFinallyFrame PushFrame(BoundTryStatement statement) { var state = _nextFinalizeState--; var finallyMethod = MakeSynthesizedFinally(state); var newFrame = new IteratorFinallyFrame(_currentFinallyFrame, state, finallyMethod, _yieldsInTryAnalysis.Labels(statement)); newFrame.AddState(state); _currentFinallyFrame = newFrame; return newFrame; }
/// <summary> /// Produces a Try/Finally if frame has a handler (otherwise a regular block). /// Handler goes into the Finally. /// If there are nested frames, they are emitted into the try block. /// This way the handler for the current frame is guaranteed to run even if /// nested handlers throw exceptions. /// /// { /// switch(state) /// { /// case state1: /// case state2: /// case state3: /// case state4: /// try /// { /// switch(state) /// { /// case state3: /// case state4: /// try /// { /// ... more nested state dispatches if any .... /// } /// finally /// { /// // handler for a try where state3 and state4 can be observed /// handler_3_4() /// } /// break; /// } /// } /// finally /// { /// // handler for a try where state1 and state2 can be observed /// handler_1_2() /// } /// break; /// /// case state5: /// ... another dispatch of nested states to their finally blocks ... /// break; /// } /// } /// /// </summary> private BoundStatement EmitFinallyFrame(IteratorFinallyFrame frame, BoundLocal state) { BoundStatement body = null; if (frame.knownStates != null) { var breakLabel = F.GenerateLabel("break"); var sections = from ft in frame.knownStates group ft.Key by ft.Value into g select F.SwitchSection( new List<int>(g), EmitFinallyFrame(g.Key, state), F.Goto(breakLabel)); body = F.Block( F.Switch(state, sections), F.Label(breakLabel)); } if (!frame.IsRoot()) { var tryBlock = body != null ? F.Block(body) : F.Block(); body = F.Try( tryBlock, ImmutableArray<BoundCatchBlock>.Empty, F.Block(F.ExpressionStatement(F.Call(F.This(), frame.handler)))); } Debug.Assert(body != null, "we should have either sub-dispatch or a handler"); return body; }