+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
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'
ScopeInfo si;
if (li.Block.Toplevel == toplevel_owner){
- si = EmitGetScopeFromBlock (ec, li.Block);
+ si = (ScopeInfo) scopes [li.Block.ID];
si.EmitScopeInstance (ig);
return;
}
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;
}
}
+ 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.
}
}
}
+ if (ec.HaveCaptureInfo){
+ ec.EmitScopeInitFromBlock (this);
+ }
ec.Mark (StartLocation, true);
DoEmit (ec);
+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.
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'
ScopeInfo si;
if (li.Block.Toplevel == toplevel_owner){
- si = EmitGetScopeFromBlock (ec, li.Block);
+ si = (ScopeInfo) scopes [li.Block.ID];
si.EmitScopeInstance (ig);
return;
}
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;
}
}
+ 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.
}
}
}
+ if (ec.HaveCaptureInfo){
+ ec.EmitScopeInitFromBlock (this);
+ }
ec.Mark (StartLocation, true);
DoEmit (ec);
--- /dev/null
+//
+// 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();
+ }
+ }
+}