Merge pull request #1185 from esdrubal/http-reuse
[mono.git] / mcs / mcs / iterators.cs
index 0d3c19af9a7de9d59a3a7280ef022ff61b73d8f8..5dce0ed1593086082b897df277c32585ca7bd15e 100644 (file)
@@ -74,6 +74,9 @@ namespace Mono.CSharp
 
                public void RegisterResumePoint ()
                {
+                       if (resume_pc != 0)
+                               return;
+
                        if (inside_try_block == null) {
                                resume_pc = machine_initializer.AddResumePoint (this);
                        } else {
@@ -204,10 +207,13 @@ namespace Mono.CSharp
                protected StateMachine (ParametersBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind)
                        : base (block, parent, host, tparams, name, kind)
                {
+                       OriginalTypeParameters = tparams;
                }
 
                #region Properties
 
+               public TypeParameters OriginalTypeParameters { get; private set; }
+
                public StateMachineMethod StateMachineMethod {
                        get {
                                return method;
@@ -720,8 +726,7 @@ namespace Mono.CSharp
                //
                // The state as we generate the machine
                //
-               Label move_next_ok;
-               Label iterator_body_end;
+               protected Label move_next_ok;
                protected Label move_next_error;
                LocalBuilder skip_finally;
                protected LocalBuilder current_pc;
@@ -735,11 +740,7 @@ namespace Mono.CSharp
 
                #region Properties
 
-               public Label BodyEnd {
-                       get {
-                               return iterator_body_end;
-                       }
-               }
+               public Label BodyEnd { get; set; }
 
                public LocalBuilder CurrentPC
                {
@@ -827,11 +828,18 @@ namespace Mono.CSharp
                        // We only care if the PC is zero (start executing) or non-zero (don't do anything)
                        ec.Emit (OpCodes.Brtrue, move_next_error);
 
-                       iterator_body_end = ec.DefineLabel ();
+                       BodyEnd = ec.DefineLabel ();
+
+                       var async_init = this as AsyncInitializer;
+                       if (async_init != null)
+                               ec.BeginExceptionBlock ();
 
                        block.EmitEmbedded (ec);
 
-                       ec.MarkLabel (iterator_body_end);
+                       if (async_init != null)
+                               async_init.EmitCatchBlock (ec);
+
+                       ec.MarkLabel (BodyEnd);
 
                        EmitMoveNextEpilogue (ec);
 
@@ -841,6 +849,8 @@ namespace Mono.CSharp
                                ec.EmitInt (0);
                                ec.Emit (OpCodes.Ret);
                        }
+
+                       ec.MarkLabel (move_next_ok);
                }
 
                void EmitMoveNext (EmitContext ec)
@@ -890,26 +900,14 @@ namespace Mono.CSharp
 
                        ec.MarkLabel (labels[0]);
 
-                       iterator_body_end = ec.DefineLabel ();
+                       BodyEnd = ec.DefineLabel ();
 
                        block.EmitEmbedded (ec);
 
-                       ec.MarkLabel (iterator_body_end);
+                       ec.MarkLabel (BodyEnd);
 
                        if (async_init != null) {
-                               var catch_value = LocalVariable.CreateCompilerGenerated (ec.Module.Compiler.BuiltinTypes.Exception, block, Location);
-
-                               ec.BeginCatchBlock (catch_value.Type);
-                               catch_value.EmitAssign (ec);
-
-                               ec.EmitThis ();
-                               ec.EmitInt ((int) IteratorStorey.State.After);
-                               ec.Emit (OpCodes.Stfld, storey.PC.Spec);
-
-                               ((AsyncTaskStorey) async_init.Storey).EmitSetException (ec, new LocalVariableReference (catch_value, Location));
-
-                               ec.Emit (OpCodes.Leave, move_next_ok);
-                               ec.EndExceptionBlock ();
+                               async_init.EmitCatchBlock (ec);
                        }
 
                        ec.Mark (Block.Original.EndLocation);