2006-02-01 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Wed, 1 Feb 2006 21:46:37 +0000 (21:46 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 1 Feb 2006 21:46:37 +0000 (21:46 -0000)
* anonymous.cs (CaptureContext.EmitInitScope): Do not emit the
scopes for all the roots, the scopes will now be emitted when the
Blocks are entered.

(CaptureContext.EmitScopeInitFromBlock): Simply emit the ScopeInfo
code.  This reduces a lot of existing cruft.

* statement.cs (Block.Emit): Call EmitScopeInitFromBlock here, so
that the ScopeInfo is generated as we enter the scope, not at the
time of use, which is what we used to do before.

* codegen.cs (EmitScopeInitFromBlock): New routine, this is called
every time a Block is about to be emitted if we have a
CaptureContext.

Fixes bug: 77060

svn path=/trunk/mcs/; revision=56424

mcs/gmcs/ChangeLog
mcs/gmcs/anonymous.cs
mcs/gmcs/codegen.cs
mcs/gmcs/statement.cs
mcs/mcs/ChangeLog
mcs/mcs/anonymous.cs
mcs/mcs/codegen.cs
mcs/mcs/statement.cs
mcs/tests/test-anon-34.cs [new file with mode: 0644]

index 0a3eacdc25d9b09ae1609edd61ebc471a3da4045..097704de65949681daf2037ffc5bad4b6e54a890 100644 (file)
@@ -1,3 +1,20 @@
+2006-02-01  Miguel de Icaza  <miguel@novell.com>
+
+       * anonymous.cs (CaptureContext.EmitInitScope): Do not emit the
+       scopes for all the roots, the scopes will now be emitted when the
+       Blocks are entered.
+
+       (CaptureContext.EmitScopeInitFromBlock): Simply emit the ScopeInfo
+       code.  This reduces a lot of existing cruft.
+       
+       * statement.cs (Block.Emit): Call EmitScopeInitFromBlock here, so
+       that the ScopeInfo is generated as we enter the scope, not at the
+       time of use, which is what we used to do before.
+
+       * codegen.cs (EmitScopeInitFromBlock): New routine, this is called
+       every time a Block is about to be emitted if we have a
+       CaptureContext. 
+
 2006-02-01  Raja R Harinath  <rharinath@novell.com>
 
        * codegen.cs (AssemblyClass.Emit): Emit RuntimeCompatibility
index 16f896c5705bdc6749a4707e02c866bd0d0f7e4a..a91481b4c55d2bccdab88e6401b4129ffddf3f34 100644 (file)
@@ -1165,23 +1165,21 @@ namespace Mono.CSharp {
                public void EmitInitScope (EmitContext ec)
                {
                        EmitAnonymousHelperClasses (ec);
-                       if (roots.Count != 0)
-                               foreach (ScopeInfo root in roots)
-                                       root.EmitInitScope (ec);
                }
 
-               ScopeInfo EmitGetScopeFromBlock (EmitContext ec, Block b)
+               //
+               // This is called externally when we start emitting code for a block
+               // if the block has a ScopeInfo associated, emit the init code
+               //
+               public void EmitScopeInitFromBlock (EmitContext ec, Block b)
                {
-                       ScopeInfo si;
-                       
-                       si = (ScopeInfo) scopes [b.ID];
+                       ScopeInfo si = (ScopeInfo) scopes [b.ID];
                        if (si == null)
-                               throw new Exception ("Si is null for block " + b.ID);
-                       si.EmitInitScope (ec);
+                               return;
 
-                       return si;
+                       si.EmitInitScope (ec);
                }
-
+               
                //
                // Emits the opcodes necessary to load the instance of the captured
                // variable in `li'
@@ -1193,7 +1191,7 @@ namespace Mono.CSharp {
                        ScopeInfo si;
 
                        if (li.Block.Toplevel == toplevel_owner){
-                               si = EmitGetScopeFromBlock (ec, li.Block);
+                               si = (ScopeInfo) scopes [li.Block.ID];
                                si.EmitScopeInstance (ig);
                                return;
                        }
@@ -1247,7 +1245,7 @@ namespace Mono.CSharp {
                        ScopeInfo si;
 
                        if (ec.CurrentBlock.Toplevel == toplevel_owner) {
-                               si = EmitGetScopeFromBlock (ec, toplevel_owner);
+                               si = (ScopeInfo) scopes [toplevel_owner.ID];
                                si.EmitScopeInstance (ig);
                        } else {
                                si = ec.CurrentAnonymousMethod.Scope;
index 49537ea0fb0ad3e0e0be2bce2ed60ccf26fd5df0..633c7db6d966804c73454b52b3e524a5fc1c2ad2 100644 (file)
@@ -452,6 +452,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void EmitScopeInitFromBlock (Block b)
+               {
+                       capture_context.EmitScopeInitFromBlock (this, b);
+               }
+
                // <summary>
                //   Starts a new code branching.  This inherits the state of all local
                //   variables and parameters from the current branching.
index 05cf08d2cdbb1cf1f37d8610bcc29373fa46b8d6..60c7e298c8df3756ad4210e83ff233a3a36b601d 100644 (file)
@@ -2027,6 +2027,9 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
+                       if (ec.HaveCaptureInfo){
+                               ec.EmitScopeInitFromBlock (this);
+                       }
 
                        ec.Mark (StartLocation, true);
                        DoEmit (ec);
index f68ced123a272b2a56a8a88ae0c0a3190c021ec2..f5b61eb05ae042c473a5e02fef83b7d6182cd296 100644 (file)
@@ -1,3 +1,20 @@
+2006-02-01  Miguel de Icaza  <miguel@novell.com>
+
+       * anonymous.cs (CaptureContext.EmitInitScope): Do not emit the
+       scopes for all the roots, the scopes will now be emitted when the
+       Blocks are entered.
+
+       (CaptureContext.EmitScopeInitFromBlock): Simply emit the ScopeInfo
+       code.  This reduces a lot of existing cruft.
+       
+       * statement.cs (Block.Emit): Call EmitScopeInitFromBlock here, so
+       that the ScopeInfo is generated as we enter the scope, not at the
+       time of use, which is what we used to do before.
+
+       * codegen.cs (EmitScopeInitFromBlock): New routine, this is called
+       every time a Block is about to be emitted if we have a
+       CaptureContext. 
+
 2006-02-01  Raja R Harinath  <rharinath@novell.com>
 
        * typemanager.cs (NoTypes, NoTypeExprs): Remove.
index 57fb8e98f61c867ff82c45187b35240affc2aec0..daf5399d4242db0e6eed5535a1911c26be922ab4 100644 (file)
@@ -1088,23 +1088,21 @@ namespace Mono.CSharp {
                public void EmitInitScope (EmitContext ec)
                {
                        EmitAnonymousHelperClasses (ec);
-                       if (roots.Count != 0)
-                               foreach (ScopeInfo root in roots)
-                                       root.EmitInitScope (ec);
                }
 
-               ScopeInfo EmitGetScopeFromBlock (EmitContext ec, Block b)
+               //
+               // This is called externally when we start emitting code for a block
+               // if the block has a ScopeInfo associated, emit the init code
+               //
+               public void EmitScopeInitFromBlock (EmitContext ec, Block b)
                {
-                       ScopeInfo si;
-                       
-                       si = (ScopeInfo) scopes [b.ID];
+                       ScopeInfo si = (ScopeInfo) scopes [b.ID];
                        if (si == null)
-                               throw new Exception ("Si is null for block " + b.ID);
-                       si.EmitInitScope (ec);
+                               return;
 
-                       return si;
+                       si.EmitInitScope (ec);
                }
-
+               
                //
                // Emits the opcodes necessary to load the instance of the captured
                // variable in `li'
@@ -1116,7 +1114,7 @@ namespace Mono.CSharp {
                        ScopeInfo si;
 
                        if (li.Block.Toplevel == toplevel_owner){
-                               si = EmitGetScopeFromBlock (ec, li.Block);
+                               si = (ScopeInfo) scopes [li.Block.ID];
                                si.EmitScopeInstance (ig);
                                return;
                        }
@@ -1170,7 +1168,7 @@ namespace Mono.CSharp {
                        ScopeInfo si;
 
                        if (ec.CurrentBlock.Toplevel == toplevel_owner) {
-                               si = EmitGetScopeFromBlock (ec, toplevel_owner);
+                               si = (ScopeInfo) scopes [toplevel_owner.ID];
                                si.EmitScopeInstance (ig);
                        } else {
                                si = ec.CurrentAnonymousMethod.Scope;
index 3eb4d66a640a6e2afcfc5aa3eb148184d46ef8ae..9465acdd29260fc8f7f25821cd8fb08ad55d8714 100644 (file)
@@ -428,6 +428,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void EmitScopeInitFromBlock (Block b)
+               {
+                       capture_context.EmitScopeInitFromBlock (this, b);
+               }
+
                // <summary>
                //   Starts a new code branching.  This inherits the state of all local
                //   variables and parameters from the current branching.
index 2ea4702175e005af8c606de78fe19e0d1658aaed..ad90e58ae24dc685d2d932ca0a91b6655db27086 100644 (file)
@@ -2032,6 +2032,9 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
+                       if (ec.HaveCaptureInfo){
+                               ec.EmitScopeInitFromBlock (this);
+                       }
 
                        ec.Mark (StartLocation, true);
                        DoEmit (ec);
diff --git a/mcs/tests/test-anon-34.cs b/mcs/tests/test-anon-34.cs
new file mode 100644 (file)
index 0000000..3e75f7a
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// This test is from Nigel Perry, Bugzilla #77060
+//
+// The issue here was that in the past we used to emit the
+// Scope initialization on first use, which is wrong as illustrated
+// in this test (the shared scope is not initialized for differnt
+// code paths).
+//
+// This test is a running test, ensuring that it runs
+//
+#region Using directives
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Timers;
+
+#endregion
+
+namespace Delegates
+{ class Space
+  { public int Value;
+
+    public delegate void DoCopy();
+
+    public DoCopy CopyIt;
+
+    public void Leak(bool useArray, int max)
+    { DoCopy one = null;
+
+      if(useArray)
+      { 
+        int[] work;
+        
+        one = delegate 
+              { work = new int[max];
+              };
+      }
+      else
+      { 
+        one = delegate { int xans = (max + 1) * max / 2; };
+      }
+
+       Console.WriteLine("Here goes...");
+       one();
+       Console.WriteLine("... made it");
+    }
+  }
+
+  class Program
+  { static void SpaceLeak()
+    { Space s = new Space();
+
+      Console.WriteLine(s.Value);
+
+      s.Leak(false, 1);
+
+      Console.WriteLine(s.Value);
+    }
+
+    static void Main(string[] args)
+    { SpaceLeak();
+    }
+  }
+}