Merge pull request #1952 from esdrubal/proc_name
[mono.git] / mcs / mcs / flowanalysis.cs
index 4fee5a1f707ac72a1ed102aabc7701f259be7778..267879c043b75ef8dc40f3df4f150503cd69317c 100644 (file)
@@ -17,1055 +17,6 @@ using System.Collections.Generic;
 
 namespace Mono.CSharp
 {
-       // <summary>
-       //   A new instance of this class is created every time a new block is resolved
-       //   and if there's branching in the block's control flow.
-       // </summary>
-       public abstract class FlowBranching
-       {
-               // <summary>
-               //   The type of a FlowBranching.
-               // </summary>
-               public enum BranchingType : byte {
-                       // Normal (conditional or toplevel) block.
-                       Block,
-
-                       // Conditional.
-                       Conditional,
-
-                       // A loop block.
-                       Loop,
-
-                       // The statement embedded inside a loop
-                       Embedded,
-
-                       // part of a block headed by a jump target
-                       Labeled,
-
-                       // TryCatch block.
-                       TryCatch,
-
-                       // TryFinally, Using, Lock, CollectionForeach
-                       Exception,
-
-                       // Switch block.
-                       Switch,
-
-                       // The toplevel block of a function
-                       Toplevel,
-
-                       // An iterator block
-                       Iterator
-               }
-
-               // <summary>
-               //   The type of one sibling of a branching.
-               // </summary>
-               public enum SiblingType : byte {
-                       Block,
-                       Conditional,
-                       SwitchSection,
-                       Try,
-                       Catch,
-                       Finally
-               }
-
-               public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc)
-               {
-                       switch (type) {
-                       case BranchingType.Exception:
-                       case BranchingType.Labeled:
-                       case BranchingType.Toplevel:
-                       case BranchingType.TryCatch:
-                               throw new InvalidOperationException ();
-
-                       case BranchingType.Switch:
-                               return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc);
-
-                       case BranchingType.Block:
-                               return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
-
-                       case BranchingType.Loop:
-                               return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc);
-
-                       case BranchingType.Embedded:
-                               return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc);
-
-                       default:
-                               return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc);
-                       }
-               }
-
-               // <summary>
-               //   The type of this flow branching.
-               // </summary>
-               public readonly BranchingType Type;
-
-               // <summary>
-               //   The block this branching is contained in.  This may be null if it's not
-               //   a top-level block and it doesn't declare any local variables.
-               // </summary>
-               public readonly Block Block;
-
-               // <summary>
-               //   The parent of this branching or null if this is the top-block.
-               // </summary>
-               public readonly FlowBranching Parent;
-
-               // <summary>
-               //   Start-Location of this flow branching.
-               // </summary>
-               public readonly Location Location;
-
-               static int next_id;
-               int id;
-
-               // <summary>
-               //   The vector contains a BitArray with information about which local variables
-               //   and parameters are already initialized at the current code position.
-               // </summary>
-               public class UsageVector {
-                       // <summary>
-                       //   The type of this branching.
-                       // </summary>
-                       public readonly SiblingType Type;
-
-                       // <summary>
-                       //   Start location of this branching.
-                       // </summary>
-                       public Location Location;
-
-                       // <summary>
-                       //   This is only valid for SwitchSection, Try, Catch and Finally.
-                       // </summary>
-                       public readonly Block Block;
-
-                       // <summary>
-                       //   The number of locals in this block.
-                       // </summary>
-                       public readonly int CountLocals;
-
-                       // <summary>
-                       //   If not null, then we inherit our state from this vector and do a
-                       //   copy-on-write.  If null, then we're the first sibling in a top-level
-                       //   block and inherit from the empty vector.
-                       // </summary>
-                       public readonly UsageVector InheritsFrom;
-
-                       // <summary>
-                       //   This is used to construct a list of UsageVector's.
-                       // </summary>
-                       public UsageVector Next;
-
-                       //
-                       // Private.
-                       //
-                       MyBitVector locals;
-                       bool is_unreachable;
-
-                       static int next_id;
-                       int id;
-
-                       //
-                       // Normally, you should not use any of these constructors.
-                       //
-                       public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals)
-                       {
-                               this.Type = type;
-                               this.Block = block;
-                               this.Location = loc;
-                               this.InheritsFrom = parent;
-                               this.CountLocals = num_locals;
-
-                               locals = num_locals == 0 
-                                       ? MyBitVector.Empty
-                                       : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals);
-
-                               if (parent != null)
-                                       is_unreachable = parent.is_unreachable;
-
-                               id = ++next_id;
-
-                       }
-
-                       public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc)
-                               : this (type, parent, block, loc, parent.CountLocals)
-                       { }
-
-                       private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc)
-                       {
-                               this.Type = SiblingType.Block;
-                               this.Location = loc;
-                               this.Block = block;
-
-                               this.is_unreachable = is_unreachable;
-
-                               this.locals = locals;
-
-                               id = ++next_id;
-
-                       }
-
-                       // <summary>
-                       //   This does a deep copy of the usage vector.
-                       // </summary>
-                       public UsageVector Clone ()
-                       {
-                               UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals);
-
-                               retval.locals = locals.Clone ();
-                               retval.is_unreachable = is_unreachable;
-
-                               return retval;
-                       }
-
-                       public bool IsAssigned (VariableInfo var, bool ignoreReachability)
-                       {
-                               if (!ignoreReachability && !var.IsParameter && IsUnreachable)
-                                       return true;
-
-                               return var.IsAssigned (locals);
-                       }
-
-                       public void SetAssigned (VariableInfo var)
-                       {
-                               if (!var.IsParameter && IsUnreachable)
-                                       return;
-
-                               var.SetAssigned (locals);
-                       }
-
-                       public bool IsFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (/*!var.IsParameter &&*/ IsUnreachable)
-                                       return true;
-
-                               return var.IsStructFieldAssigned (locals, name);
-                       }
-
-                       public void SetFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (/*!var.IsParameter &&*/ IsUnreachable)
-                                       return;
-
-                               var.SetStructFieldAssigned (locals, name);
-                       }
-
-                       public bool IsUnreachable {
-                               get {
-                                       return is_unreachable;
-                               }
-                               set {
-                                       is_unreachable = value;
-                               }
-                       }
-
-                       public void ResetBarrier ()
-                       {
-                               is_unreachable = false;
-                       }
-
-                       public void Goto ()
-                       {
-                               is_unreachable = true;
-                       }
-
-                       public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc)
-                       {
-                               if (sibling_list.Next == null)
-                                       return sibling_list;
-
-                               MyBitVector locals = null;
-                               bool is_unreachable = sibling_list.is_unreachable;
-
-                               if (!sibling_list.IsUnreachable)
-                                       locals &= sibling_list.locals;
-
-                               for (UsageVector child = sibling_list.Next; child != null; child = child.Next) {
-                                       is_unreachable &= child.is_unreachable;
-
-                                       if (!child.IsUnreachable)
-                                               locals &= child.locals;
-                               }
-
-                               return new UsageVector (locals, is_unreachable, null, loc);
-                       }
-
-                       // <summary>
-                       //   Merges a child branching.
-                       // </summary>
-                       public UsageVector MergeChild (UsageVector child, bool overwrite)
-                       {
-                               Report.Debug (2, "    MERGING CHILD EFFECTS", this, child, Type);
-
-                               bool new_isunr = child.is_unreachable;
-
-                               //
-                               // We've now either reached the point after the branching or we will
-                               // never get there since we always return or always throw an exception.
-                               //
-                               // If we can reach the point after the branching, mark all locals and
-                               // parameters as initialized which have been initialized in all branches
-                               // we need to look at (see above).
-                               //
-
-                               if ((Type == SiblingType.SwitchSection) && !new_isunr) {
-                                       Report.Error (163, Location,
-                                                     "Control cannot fall through from one " +
-                                                     "case label to another");
-                                       return child;
-                               }
-
-                               locals |= child.locals;
-
-                               // throw away un-necessary information about variables in child blocks
-                               if (locals.Count != CountLocals)
-                                       locals = new MyBitVector (locals, CountLocals);
-
-                               if (overwrite)
-                                       is_unreachable = new_isunr;
-                               else
-                                       is_unreachable |= new_isunr;
-
-                               return child;
-                       }
-
-                       public void MergeOrigins (UsageVector o_vectors)
-                       {
-                               Report.Debug (1, "  MERGING BREAK ORIGINS", this);
-
-                               if (o_vectors == null)
-                                       return;
-
-                               if (IsUnreachable && locals != null)
-                                       locals.SetAll (true);
-
-                               for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) {
-                                       Report.Debug (1, "    MERGING BREAK ORIGIN", vector);
-                                       if (vector.IsUnreachable)
-                                               continue;
-                                       locals &= vector.locals;
-                                       is_unreachable &= vector.is_unreachable;
-                               }
-
-                               Report.Debug (1, "  MERGING BREAK ORIGINS DONE", this);
-                       }
-
-                       //
-                       // Debugging stuff.
-                       //
-
-                       public override string ToString ()
-                       {
-                               return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals);
-                       }
-               }
-
-               // <summary>
-               //   Creates a new flow branching which is contained in `parent'.
-               //   You should only pass non-null for the `block' argument if this block
-               //   introduces any new variables - in this case, we need to create a new
-               //   usage vector with a different size than our parent's one.
-               // </summary>
-               protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype,
-                                        Block block, Location loc)
-               {
-                       Parent = parent;
-                       Block = block;
-                       Location = loc;
-                       Type = type;
-                       id = ++next_id;
-
-                       UsageVector vector;
-                       if (Block != null) {
-                               UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
-                               vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots);
-                       } else {
-                               vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc);
-                       }
-
-                       AddSibling (vector);
-               }
-
-               public abstract UsageVector CurrentUsageVector {
-                       get;
-               }                               
-
-               // <summary>
-               //   Creates a sibling of the current usage vector.
-               // </summary>
-               public void CreateSibling (Block block, SiblingType type)
-               {
-                       UsageVector vector = new UsageVector (
-                               type, Parent.CurrentUsageVector, block, Location);
-                       AddSibling (vector);
-
-                       Report.Debug (1, "  CREATED SIBLING", CurrentUsageVector);
-               }
-
-               public void CreateSibling ()
-               {
-                       CreateSibling (null, SiblingType.Conditional);
-               }
-
-               protected abstract void AddSibling (UsageVector uv);
-
-               protected abstract UsageVector Merge ();
-
-               public UsageVector MergeChild (FlowBranching child)
-               {
-                       return CurrentUsageVector.MergeChild (child.Merge (), true);
-               }
-
-               public virtual bool CheckRethrow (Location loc)
-               {
-                       return Parent.CheckRethrow (loc);
-               }
-
-               public virtual bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       return Parent.AddResumePoint (stmt, current, out pc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       return Parent.AddBreakOrigin (vector, loc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       return Parent.AddContinueOrigin (vector, loc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
-               {
-                       return Parent.AddReturnOrigin (vector, stmt);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       return Parent.AddGotoOrigin (vector, goto_stmt);
-               }
-
-               public bool IsAssigned (VariableInfo vi)
-               {
-                       return CurrentUsageVector.IsAssigned (vi, false);
-               }
-
-               public bool IsStructFieldAssigned (VariableInfo vi, string field_name)
-               {
-                       return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name);
-               }
-
-               protected static Report Report {
-                       get { return RootContext.ToplevelTypes.Compiler.Report; }
-               }
-
-               public void SetAssigned (VariableInfo vi)
-               {
-                       CurrentUsageVector.SetAssigned (vi);
-               }
-
-               public void SetFieldAssigned (VariableInfo vi, string name)
-               {
-                       CurrentUsageVector.SetFieldAssigned (vi, name);
-               }
-
-#if DEBUG
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ();
-                       sb.Append (GetType ());
-                       sb.Append (" (");
-
-                       sb.Append (id);
-                       sb.Append (",");
-                       sb.Append (Type);
-                       if (Block != null) {
-                               sb.Append (" - ");
-                               sb.Append (Block.ID);
-                               sb.Append (" - ");
-                               sb.Append (Block.StartLocation);
-                       }
-                       sb.Append (" - ");
-                       // sb.Append (Siblings.Length);
-                       // sb.Append (" - ");
-                       sb.Append (CurrentUsageVector);
-                       sb.Append (")");
-                       return sb.ToString ();
-               }
-#endif
-
-               public string Name {
-                       get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); }
-               }
-       }
-
-       public class FlowBranchingBlock : FlowBranching
-       {
-               UsageVector sibling_list = null;
-
-               public FlowBranchingBlock (FlowBranching parent, BranchingType type,
-                                          SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override UsageVector CurrentUsageVector {
-                       get { return sibling_list; }
-               }
-
-               protected override void AddSibling (UsageVector sibling)
-               {
-                       if (sibling_list != null && sibling_list.Type == SiblingType.Block)
-                               throw new InternalErrorException ("Blocks don't have sibling flow paths");
-                       sibling.Next = sibling_list;
-                       sibling_list = sibling;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target);
-                       if (stmt == null)
-                               return Parent.AddGotoOrigin (vector, goto_stmt);
-
-                       // forward jump
-                       goto_stmt.SetResolvedTarget (stmt);
-                       stmt.AddUsageVector (vector);
-                       return false;
-               }
-               
-               public static void Error_UnknownLabel (Location loc, string label, Report Report)
-               {
-                       Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
-                               label);
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       Report.Debug (2, "  MERGING SIBLINGS", Name);
-                       UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location);
-                       Report.Debug (2, "  MERGING SIBLINGS DONE", Name, vector);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingBreakable : FlowBranchingBlock
-       {
-               UsageVector break_origins;
-
-               public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       vector = vector.Clone ();
-                       vector.Next = break_origins;
-                       break_origins = vector;
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-                       vector.MergeOrigins (break_origins);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingContinuable : FlowBranchingBlock
-       {
-               UsageVector continue_origins;
-
-               public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       vector = vector.Clone ();
-                       vector.Next = continue_origins;
-                       continue_origins = vector;
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-                       vector.MergeOrigins (continue_origins);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingLabeled : FlowBranchingBlock
-       {
-               LabeledStatement stmt;
-               UsageVector actual;
-
-               public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt)
-                       : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc)
-               {
-                       this.stmt = stmt;
-                       CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
-                       actual = CurrentUsageVector.Clone ();
-
-                       // stand-in for backward jumps
-                       CurrentUsageVector.ResetBarrier ();
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       if (goto_stmt.Target != stmt.Name)
-                               return Parent.AddGotoOrigin (vector, goto_stmt);
-
-                       // backward jump
-                       goto_stmt.SetResolvedTarget (stmt);
-                       actual.MergeOrigins (vector.Clone ());
-
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-
-                       if (actual.IsUnreachable)
-                               Report.Warning (162, 2, stmt.loc, "Unreachable code detected");
-
-                       actual.MergeChild (vector, false);
-                       return actual;
-               }
-       }
-
-       public class FlowBranchingIterator : FlowBranchingBlock
-       {
-               readonly Iterator iterator;
-
-               public FlowBranchingIterator (FlowBranching parent, Iterator iterator)
-                       : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location)
-               {
-                       this.iterator = iterator;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       pc = iterator.AddResumePoint (current);
-                       return false;
-               }
-       }
-
-       public class FlowBranchingToplevel : FlowBranchingBlock
-       {
-               UsageVector return_origins;
-
-               public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt)
-                       : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc)
-               {
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause");
-                       return false;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       throw new InternalErrorException ("A yield in a non-iterator block");
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Report.Error (139, loc, "No enclosing loop out of which to break or continue");
-                       return false;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Report.Error (139, loc, "No enclosing loop out of which to break or continue");
-                       return false;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
-               {
-                       vector = vector.Clone ();
-                       vector.Location = stmt.loc;
-                       vector.Next = return_origins;
-                       return_origins = vector;
-                       return false;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       string name = goto_stmt.Target;
-                       LabeledStatement s = Block.LookupLabel (name);
-                       if (s != null)
-                               throw new InternalErrorException ("Shouldn't get here");
-
-                       if (Parent == null) {
-                               Error_UnknownLabel (goto_stmt.loc, name, Report);
-                               return false;
-                       }
-
-                       int errors = Report.Errors;
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       if (errors == Report.Errors)
-                               Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method");
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       for (UsageVector origin = return_origins; origin != null; origin = origin.Next)
-                               Block.ParametersBlock.CheckOutParameters (origin);
-
-                       UsageVector vector = base.Merge ();
-                       Block.ParametersBlock.CheckOutParameters (vector);
-                       // Note: we _do_not_ merge in the return origins
-                       return vector;
-               }
-
-               public bool End ()
-               {
-                       return Merge ().IsUnreachable;
-               }
-       }
-
-       public class FlowBranchingTryCatch : FlowBranchingBlock
-       {
-               readonly TryCatch tc;
-
-               public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt)
-                       : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc)
-               {
-                       this.tc = stmt;
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       int errors = Report.Errors;
-                       Parent.AddResumePoint (stmt, tc.IsTryCatchFinally ? current : tc, out pc);
-                       if (errors == Report.Errors) {
-                               if (stmt is AwaitStatement) {
-                                       if (CurrentUsageVector.Next != null) {
-                                               Report.Error (1985, stmt.loc, "The `await' operator cannot be used in the body of a catch clause");
-                                       } else {
-                                               this.tc.AddResumePoint (current, pc);
-                                       }
-                               } else {
-                                       if (CurrentUsageVector.Next == null)
-                                               Report.Error (1626, stmt.loc, "Cannot yield a value in the body of a try block with a catch clause");
-                                       else
-                                               Report.Error (1631, stmt.loc, "Cannot yield a value in the body of a catch clause");
-                               }
-                       }
-
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddBreakOrigin (vector, loc);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddContinueOrigin (vector, loc);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       Parent.AddReturnOrigin (vector, exit_stmt);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       return true;
-               }
-       }
-
-       public class FlowBranchingAsync : FlowBranchingBlock
-       {
-               readonly AsyncInitializer async_init;
-
-               public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init)
-                       : base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location)
-               {
-                       this.async_init = async_init;
-               }
-/*
-               public override bool CheckRethrow (Location loc)
-               {
-                       return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
-               }
-*/
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       pc = async_init.AddResumePoint (current);
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddBreakOrigin (vector, loc);
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddContinueOrigin (vector, loc);
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       Parent.AddReturnOrigin (vector, exit_stmt);
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       return true;
-               }
-       }
-
-       public class FlowBranchingTryFinally : FlowBranching
-       {
-               ExceptionStatement stmt;
-               UsageVector current_vector;
-               UsageVector try_vector;
-               UsageVector finally_vector;
-
-               abstract class SavedOrigin {
-                       public readonly SavedOrigin Next;
-                       public readonly UsageVector Vector;
-
-                       protected SavedOrigin (SavedOrigin next, UsageVector vector)
-                       {
-                               Next = next;
-                               Vector = vector.Clone ();
-                       }
-
-                       protected abstract void DoPropagateFinally (FlowBranching parent);
-                       public void PropagateFinally (UsageVector finally_vector, FlowBranching parent)
-                       {
-                               if (finally_vector != null)
-                                       Vector.MergeChild (finally_vector, false);
-                               DoPropagateFinally (parent);
-                       }
-               }
-
-               class BreakOrigin : SavedOrigin {
-                       Location Loc;
-                       public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc)
-                               : base (next, vector)
-                       {
-                               Loc = loc;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddBreakOrigin (Vector, Loc);
-                       }
-               }
-
-               class ContinueOrigin : SavedOrigin {
-                       Location Loc;
-                       public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc)
-                               : base (next, vector)
-                       {
-                               Loc = loc;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddContinueOrigin (Vector, Loc);
-                       }
-               }
-
-               class ReturnOrigin : SavedOrigin {
-                       public ExitStatement Stmt;
-
-                       public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt)
-                               : base (next, vector)
-                       {
-                               Stmt = stmt;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddReturnOrigin (Vector, Stmt);
-                       }
-               }
-
-               class GotoOrigin : SavedOrigin {
-                       public Goto Stmt;
-
-                       public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt)
-                               : base (next, vector)
-                       {
-                               Stmt = stmt;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddGotoOrigin (Vector, Stmt);
-                       }
-               }
-
-               SavedOrigin saved_origins;
-
-               public FlowBranchingTryFinally (FlowBranching parent,
-                                              ExceptionStatement stmt)
-                       : base (parent, BranchingType.Exception, SiblingType.Try,
-                               null, stmt.loc)
-               {
-                       this.stmt = stmt;
-               }
-
-               protected override void AddSibling (UsageVector sibling)
-               {
-                       switch (sibling.Type) {
-                       case SiblingType.Try:
-                               try_vector = sibling;
-                               break;
-                       case SiblingType.Finally:
-                               finally_vector = sibling;
-                               break;
-                       default:
-                               throw new InvalidOperationException ();
-                       }
-                       current_vector = sibling;
-               }
-
-               public override UsageVector CurrentUsageVector {
-                       get { return current_vector; }
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       if (!Parent.CheckRethrow (loc))
-                               return false;
-                       if (finally_vector == null)
-                               return true;
-                       Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause");
-                       return false;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       int errors = Report.Errors;
-                       Parent.AddResumePoint (stmt, this.stmt, out pc);
-                       if (errors == Report.Errors) {
-                               if (finally_vector == null)
-                                       this.stmt.AddResumePoint (current, pc);
-                               else {
-                                       if (stmt is AwaitStatement) {
-                                               Report.Error (1984, stmt.loc, "The `await' operator cannot be used in the body of a finally clause");
-                                       } else {
-                                               Report.Error (1625, stmt.loc, "Cannot yield in the body of a finally clause");
-                                       }
-                               }
-                       }
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddBreakOrigin (vector, loc);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new BreakOrigin (saved_origins, vector, loc);
-                       }
-
-                       // either the loop test or a back jump will follow code
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddContinueOrigin (vector, loc);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new ContinueOrigin (saved_origins, vector, loc);
-                       }
-
-                       // either the loop test or a back jump will follow code
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddReturnOrigin (vector, exit_stmt);
-                               if (errors == Report.Errors)
-                                       exit_stmt.Error_FinallyClause (Report);
-                       } else {
-                               saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt);
-                       }
-
-                       // sets ec.NeedReturnLabel()
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target);
-                       if (s != null)
-                               throw new InternalErrorException ("Shouldn't get here");
-
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddGotoOrigin (vector, goto_stmt);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt);
-                       }
-                       return true;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = try_vector.Clone ();
-
-                       if (finally_vector != null)
-                               vector.MergeChild (finally_vector, false);
-
-                       for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next)
-                               origin.PropagateFinally (finally_vector, Parent);
-
-                       return vector;
-               }
-       }
-
        // <summary>
        //   This is used by the flow analysis code to keep track of the type of local variables.
        //
@@ -1108,10 +59,9 @@ namespace Mono.CSharp
                public TypeInfo[] SubStructInfo;
 
                readonly StructInfo struct_info;
-               private static Dictionary<TypeSpec, TypeInfo> type_hash;
 
                static readonly TypeInfo simple_type = new TypeInfo (1);
-               
+
                static TypeInfo ()
                {
                        Reset ();
@@ -1119,7 +69,6 @@ namespace Mono.CSharp
                
                public static void Reset ()
                {
-                       type_hash = new Dictionary<TypeSpec, TypeInfo> ();
                        StructInfo.field_type_hash = new Dictionary<TypeSpec, StructInfo> ();
                }
 
@@ -1154,23 +103,34 @@ namespace Mono.CSharp
                        return struct_info.GetStructField (name);
                }
 
-               public static TypeInfo GetTypeInfo (TypeSpec type)
+               public static TypeInfo GetTypeInfo (TypeSpec type, IMemberContext context)
                {
                        if (!type.IsStruct)
                                return simple_type;
 
                        TypeInfo info;
-                       if (type_hash.TryGetValue (type, out info))
-                               return info;
+                       Dictionary<TypeSpec, TypeInfo> type_hash;
+                       if (type.BuiltinType > 0) {
+                               // Don't cache built-in types, they are null in most cases except for
+                               // corlib compilation when we need to distinguish between declaration
+                               // and referencing
+                               type_hash = null;
+                       } else {
+                               type_hash = context.Module.TypeInfoCache;
+                               if (type_hash.TryGetValue (type, out info))
+                                       return info;
+                       }
 
-                       var struct_info = StructInfo.GetStructInfo (type);
+                       var struct_info = StructInfo.GetStructInfo (type, context);
                        if (struct_info != null) {
                                info = new TypeInfo (struct_info, 0);
                        } else {
                                info = simple_type;
                        }
 
-                       type_hash.Add (type, info);
+                       if (type_hash != null)
+                               type_hash.Add (type, info);
+
                        return info;
                }
 
@@ -1178,26 +138,32 @@ namespace Mono.CSharp
                //   A struct's constructor must always assign all fields.
                //   This method checks whether it actually does so.
                // </summary>
-               public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc)
+               public bool IsFullyInitialized (FlowAnalysisContext fc, VariableInfo vi, Location loc)
                {
                        if (struct_info == null)
                                return true;
 
                        bool ok = true;
-                       FlowBranching branching = ec.CurrentBranching;
                        for (int i = 0; i < struct_info.Count; i++) {
-                               var field = struct_info.Fields [i];
+                               var field = struct_info.Fields[i];
 
-                               if (!branching.IsStructFieldAssigned (vi, field.Name)) {
-                                       if (field.MemberDefinition is Property.BackingField) {
-                                               ec.Report.Error (843, loc,
+                               if (!fc.IsStructFieldDefinitelyAssigned (vi, field.Name)) {
+                                       var bf = field.MemberDefinition as Property.BackingFieldDeclaration;
+                                       if (bf != null) {
+                                               if (bf.Initializer != null)
+                                                       continue;
+
+                                               fc.Report.Error (843, loc,
                                                        "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer",
                                                        field.GetSignatureForError ());
-                                       } else {
-                                               ec.Report.Error (171, loc,
-                                                       "Field `{0}' must be fully assigned before control leaves the constructor",
-                                                       field.GetSignatureForError ());
+
+                                               ok = false;
+                                               continue;
                                        }
+
+                                       fc.Report.Error (171, loc,
+                                               "Field `{0}' must be fully assigned before control leaves the constructor",
+                                               field.GetSignatureForError ());
                                        ok = false;
                                }
                        }
@@ -1227,11 +193,11 @@ namespace Mono.CSharp
                        //
                        // We only need one instance per type
                        //
-                       StructInfo (TypeSpec type)
+                       StructInfo (TypeSpec type, IMemberContext context)
                        {
                                field_type_hash.Add (type, this);
 
-                               fields = MemberCache.GetAllFieldsForDefiniteAssignment (type);
+                               fields = MemberCache.GetAllFieldsForDefiniteAssignment (type, context);
 
                                struct_field_hash = new Dictionary<string, TypeInfo> ();
                                field_hash = new Dictionary<string, int> (fields.Count);
@@ -1245,7 +211,7 @@ namespace Mono.CSharp
                                        var field = fields [i];
 
                                        if (field.MemberType.IsStruct)
-                                               sinfo [i] = GetStructInfo (field.MemberType);
+                                               sinfo [i] = GetStructInfo (field.MemberType, context);
 
                                        if (sinfo [i] == null)
                                                field_hash.Add (field.Name, ++Length);
@@ -1303,28 +269,30 @@ namespace Mono.CSharp
                                return null;
                        }
 
-                       public static StructInfo GetStructInfo (TypeSpec type)
+                       public static StructInfo GetStructInfo (TypeSpec type, IMemberContext context)
                        {
-                               if (type.BuiltinType > 0)
+                               if (type.BuiltinType > 0 && type != context.CurrentType)
                                        return null;
 
                                StructInfo info;
                                if (field_type_hash.TryGetValue (type, out info))
                                        return info;
 
-                               return new StructInfo (type);
+                               return new StructInfo (type, context);
                        }
                }
        }
 
-       // <summary>
-       //   This is used by the flow analysis code to store information about a single local variable
-       //   or parameter.  Depending on the variable's type, we need to allocate one or more elements
-       //   in the BitVector - if it's a fundamental or reference type, we just need to know whether
-       //   it has been assigned or not, but for structs, we need this information for each of its fields.
-       // </summary>
-       public class VariableInfo {
+       //
+       // This is used by definite assignment analysis code to store information about a local variable
+       // or parameter.  Depending on the variable's type, we need to allocate one or more elements
+       // in the BitVector - if it's a fundamental or reference type, we just need to know whether
+       // it has been assigned or not, but for structs, we need this information for each of its fields.
+       //
+       public class VariableInfo
+       {
                readonly string Name;
+
                readonly TypeInfo TypeInfo;
 
                // <summary>
@@ -1337,20 +305,20 @@ namespace Mono.CSharp
                //   The first bit always specifies whether the variable as such has been assigned while
                //   the remaining bits contain this information for each of a struct's fields.
                // </summary>
-               public readonly int Length;
+               readonly int Length;
 
                // <summary>
                //   If this is a parameter of local variable.
                // </summary>
-               public readonly bool IsParameter;
+               public bool IsParameter;
 
                VariableInfo[] sub_info;
 
-               VariableInfo (string name, TypeSpec type, int offset)
+               VariableInfo (string name, TypeSpec type, int offset, IMemberContext context)
                {
                        this.Name = name;
                        this.Offset = offset;
-                       this.TypeInfo = TypeInfo.GetTypeInfo (type);
+                       this.TypeInfo = TypeInfo.GetTypeInfo (type, context);
 
                        Length = TypeInfo.TotalLength;
 
@@ -1369,7 +337,7 @@ namespace Mono.CSharp
                        Initialize ();
                }
 
-               protected void Initialize ()
+               void Initialize ()
                {
                        TypeInfo[] sub_fields = TypeInfo.SubStructInfo;
                        if (sub_fields != null) {
@@ -1382,24 +350,24 @@ namespace Mono.CSharp
                                sub_info = new VariableInfo [0];
                }
 
-               public VariableInfo (LocalVariable local_info, int offset)
-                       : this (local_info.Name, local_info.Type, offset)
+               public static VariableInfo Create (BlockContext bc, LocalVariable variable)
                {
-                       this.IsParameter = false;
+                       var info = new VariableInfo (variable.Name, variable.Type, bc.AssignmentInfoOffset, bc);
+                       bc.AssignmentInfoOffset += info.Length;
+                       return info;
                }
 
-               public VariableInfo (ParametersCompiled ip, int i, int offset)
-                       : this (ip.FixedParameters [i].Name, ip.Types [i], offset)
+               public static VariableInfo Create (BlockContext bc, Parameter parameter)
                {
-                       this.IsParameter = true;
-               }
+                       var info = new VariableInfo (parameter.Name, parameter.Type, bc.AssignmentInfoOffset, bc) {
+                               IsParameter = true
+                       };
 
-               public bool IsAssigned (ResolveContext ec)
-               {
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
+                       bc.AssignmentInfoOffset += info.Length;
+                       return info;
                }
 
-               public bool IsAssigned (MyBitVector vector)
+               public bool IsAssigned (DefiniteAssignmentBitSet vector)
                {
                        if (vector == null)
                                return true;
@@ -1438,23 +406,18 @@ namespace Mono.CSharp
                                        return false;
                        }
                        
-                       vector [Offset] = true;
+                       vector.Set (Offset);
                        return true;
                }
 
                public bool IsEverAssigned { get; set; }
 
-               public bool IsStructFieldAssigned (ResolveContext ec, string name)
-               {
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsStructFieldAssigned (this, name);
-               }
-
-               public bool IsFullyInitialized (BlockContext bc, Location loc)
+               public bool IsFullyInitialized (FlowAnalysisContext fc, Location loc)
                {
-                       return TypeInfo.IsFullyInitialized (bc, this, loc);
+                       return TypeInfo.IsFullyInitialized (fc, this, loc);
                }
 
-               public bool IsStructFieldAssigned (MyBitVector vector, string field_name)
+               public bool IsStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
                {
                        int field_idx = TypeInfo.GetFieldIndex (field_name);
 
@@ -1464,31 +427,20 @@ namespace Mono.CSharp
                        return vector [Offset + field_idx];
                }
 
-               public void SetStructFieldAssigned (ResolveContext ec, string name)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetFieldAssigned (this, name);
-               }
-
-               public void SetAssigned (ResolveContext ec)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetAssigned (this);
-               }
-
-               public void SetAssigned (MyBitVector vector)
+               public void SetAssigned (DefiniteAssignmentBitSet vector, bool generatedAssignment)
                {
                        if (Length == 1)
-                               vector[Offset] = true;
+                               vector.Set (Offset);
                        else
-                               vector.SetRange (Offset, Length);
+                               vector.Set (Offset, Length);
 
-                       IsEverAssigned = true;
+                       if (!generatedAssignment)
+                               IsEverAssigned = true;
                }
 
-               public void SetStructFieldAssigned (MyBitVector vector, string field_name)
+               public void SetStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
                {
-                       if (vector[Offset])
+                       if (vector [Offset])
                                return;
 
                        int field_idx = TypeInfo.GetFieldIndex (field_name);
@@ -1498,15 +450,15 @@ namespace Mono.CSharp
 
                        var complex_field = TypeInfo.GetStructField (field_name);
                        if (complex_field != null) {
-                               vector.SetRange (Offset + complex_field.Offset, complex_field.TotalLength);
+                               vector.Set (Offset + complex_field.Offset, complex_field.TotalLength);
                        } else {
-                               vector[Offset + field_idx] = true;
+                               vector.Set (Offset + field_idx);
                        }
 
                        IsEverAssigned = true;
 
                        //
-                       // Each field must be assigned
+                       // Each field must be assigned before setting master bit
                        //
                        for (int i = Offset + 1; i < TypeInfo.TotalLength + Offset; i++) {
                                if (!vector[i])
@@ -1517,7 +469,7 @@ namespace Mono.CSharp
                        // Set master struct flag to assigned when all tested struct
                        // fields have been assigned
                        //
-                       vector[Offset] = true;
+                       vector.Set (Offset);
                }
 
                public VariableInfo GetStructFieldInfo (string fieldName)
@@ -1532,274 +484,226 @@ namespace Mono.CSharp
 
                public override string ToString ()
                {
-                       return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
-                                             Name, TypeInfo, Offset, Length, IsParameter);
+                       return String.Format ("Name={0} Offset={1} Length={2} {3})", Name, Offset, Length, TypeInfo);
                }
        }
 
-       // <summary>
-       //   This is a special bit vector which can inherit from another bit vector doing a
-       //   copy-on-write strategy.  The inherited vector may have a smaller size than the
-       //   current one.
-       // </summary>
-       public class MyBitVector {
-               public readonly int Count;
-               public static readonly MyBitVector Empty = new MyBitVector ();
-
-               // Invariant: vector != null => vector.Count == Count
-               // Invariant: vector == null || shared == null
-               //            i.e., at most one of 'vector' and 'shared' can be non-null.  They can both be null -- that means all-ones
-               // The object in 'shared' cannot be modified, while 'vector' can be freely modified
-               System.Collections.BitArray vector, shared;
+       public struct Reachability
+       {
+               readonly bool unreachable;
 
-               MyBitVector ()
+               Reachability (bool unreachable)
                {
-                       shared = new System.Collections.BitArray (0, false);
+                       this.unreachable = unreachable;
+               }
+
+               public bool IsUnreachable {
+                       get {
+                               return unreachable;
+                       }
                }
 
-               public MyBitVector (MyBitVector InheritsFrom, int Count)
+               public static Reachability CreateUnreachable ()
                {
-                       if (InheritsFrom != null)
-                               shared = InheritsFrom.MakeShared (Count);
+                       return new Reachability (true);
+               }
 
-                       this.Count = Count;
+               public static Reachability operator & (Reachability a, Reachability b)
+               {
+                   return new Reachability (a.unreachable && b.unreachable);
                }
 
-               System.Collections.BitArray MakeShared (int new_count)
+               public static Reachability operator | (Reachability a, Reachability b)
                {
-                       // Post-condition: vector == null
+                       return new Reachability (a.unreachable | b.unreachable);
+               }
+       }
 
-                       // ensure we don't leak out dirty bits from the BitVector we inherited from
-                       if (new_count > Count &&
-                           ((shared != null && shared.Count > Count) ||
-                            (shared == null && vector == null)))
-                               initialize_vector ();
+       //
+       // Special version of bit array. Many operations can be simplified because
+       // we are always dealing with arrays of same sizes
+       //
+       public class DefiniteAssignmentBitSet
+       {
+               const uint copy_on_write_flag = 1u << 31;
 
-                       if (vector != null) {
-                               shared = vector;
-                               vector = null;
-                       }
+               uint bits;
 
-                       return shared;
-               }
+               // Used when bits overflows
+               int[] large_bits;
 
-               // <summary>
-               //   Get/set bit `index' in the bit vector.
-               // </summary>
-               public bool this [int index] {
-                       get {
-                               if (index >= Count)
-                                       // FIXME: Disabled due to missing anonymous method flow analysis
-                                       // throw new ArgumentOutOfRangeException ();
-                                       return true; 
-
-                               if (vector != null)
-                                       return vector [index];
-                               if (shared == null)
-                                       return true;
-                               if (index < shared.Count)
-                                       return shared [index];
-                               return false;
-                       }
+               public static readonly DefiniteAssignmentBitSet Empty = new DefiniteAssignmentBitSet (0);
 
-                       set {
-                               // Only copy the vector if we're actually modifying it.
-                               if (this [index] != value) {
-                                       if (vector == null)
-                                               initialize_vector ();
-                                       vector [index] = value;
-                               }
-                       }
+               public DefiniteAssignmentBitSet (int length)
+               {
+                       if (length > 31)
+                               large_bits = new int[(length + 31) / 32];
                }
 
-               // <summary>
-               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
-               //   different size than the current one.
-               // </summary>
-               private MyBitVector Or (MyBitVector new_vector)
+               public DefiniteAssignmentBitSet (DefiniteAssignmentBitSet source)
                {
-                       if (Count == 0 || new_vector.Count == 0)
-                               return this;
-
-                       var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
-
-                       if (o == null) {
-                               int n = new_vector.Count;
-                               if (n < Count) {
-                                       for (int i = 0; i < n; ++i)
-                                               this [i] = true;
-                               } else {
-                                       SetAll (true);
-                               }
-                               return this;
+                       if (source.large_bits != null) {
+                               large_bits = source.large_bits;
+                               bits = source.bits | copy_on_write_flag;
+                       } else {
+                               bits = source.bits & ~copy_on_write_flag;
                        }
+               }
 
-                       if (Count == o.Count) {
-                               if (vector == null) {
-                                       if (shared == null)
-                                               return this;
-                                       initialize_vector ();
-                               }
-                               vector.Or (o);
-                               return this;
-                       }
+               public static DefiniteAssignmentBitSet operator & (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
+               {
+                       if (IsEqual (a, b))
+                               return a;
 
-                       int min = o.Count;
-                       if (Count < min)
-                               min = Count;
+                       DefiniteAssignmentBitSet res;
+                       if (a.large_bits == null) {
+                               res = new DefiniteAssignmentBitSet (a);
+                               res.bits &= (b.bits & ~copy_on_write_flag);
+                               return res;
+                       }
 
-                       for (int i = 0; i < min; i++) {
-                               if (o [i])
-                                       this [i] = true;
+                       res = new DefiniteAssignmentBitSet (a);
+                       res.Clone ();
+                       var dest = res.large_bits;
+                       var src = b.large_bits;
+                       for (int i = 0; i < dest.Length; ++i) {
+                               dest[i] &= src[i];
                        }
 
-                       return this;
+                       return res;
                }
 
-               // <summary>
-               //   Performs an `and' operation on the bit vector.  The `new_vector' may have
-               //   a different size than the current one.
-               // </summary>
-               private MyBitVector And (MyBitVector new_vector)
+               public static DefiniteAssignmentBitSet operator | (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       if (Count == 0)
-                               return this;
-
-                       var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
+                       if (IsEqual (a, b))
+                               return a;
 
-                       if (o == null) {
-                               for (int i = new_vector.Count; i < Count; ++i)
-                                       this [i] = false;
-                               return this;
+                       DefiniteAssignmentBitSet res;
+                       if (a.large_bits == null) {
+                               res = new DefiniteAssignmentBitSet (a);
+                               res.bits |= b.bits;
+                               res.bits &= ~copy_on_write_flag;
+                               return res;
                        }
 
-                       if (o.Count == 0) {
-                               SetAll (false);
-                               return this;
-                       }
+                       res = new DefiniteAssignmentBitSet (a);
+                       res.Clone ();
+                       var dest = res.large_bits;
+                       var src = b.large_bits;
 
-                       if (Count == o.Count) {
-                               if (vector == null) {
-                                       if (shared == null) {
-                                               shared = new_vector.MakeShared (Count);
-                                               return this;
-                                       }
-                                       initialize_vector ();
-                               }
-                               vector.And (o);
-                               return this;
+                       for (int i = 0; i < dest.Length; ++i) {
+                               dest[i] |= src[i];
                        }
 
-                       int min = o.Count;
-                       if (Count < min)
-                               min = Count;
+                       return res;
+               }
 
-                       for (int i = 0; i < min; i++) {
-                               if (! o [i])
-                                       this [i] = false;
-                       }
+               public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
+               {
+                       if (das.Count == 0)
+                               throw new ArgumentException ("Empty das");
 
-                       for (int i = min; i < Count; i++)
-                               this [i] = false;
+                       DefiniteAssignmentBitSet res = das[0];
+                       for (int i = 1; i < das.Count; ++i) {
+                               res &= das[i];
+                       }
 
-                       return this;
+                       return res;
                }
 
-               public static MyBitVector operator & (MyBitVector a, MyBitVector b)
-               {
-                       if (a == b)
-                               return a;
-                       if (a == null)
-                               return b.Clone ();
-                       if (b == null)
-                               return a.Clone ();
-                       if (a.Count > b.Count)
-                               return a.Clone ().And (b);
-                       else
-                               return b.Clone ().And (a);                                      
+               bool CopyOnWrite {
+                       get {
+                               return (bits & copy_on_write_flag) != 0;
+                       }
                }
 
-               public static MyBitVector operator | (MyBitVector a, MyBitVector b)
-               {
-                       if (a == b)
-                               return a;
-                       if (a == null)
-                               return new MyBitVector (null, b.Count);
-                       if (b == null)
-                               return new MyBitVector (null, a.Count);
-                       if (a.Count > b.Count)
-                               return a.Clone ().Or (b);
-                       else
-                               return b.Clone ().Or (a);
+               int Length {
+                       get {
+                               return large_bits == null ? 31 : large_bits.Length * 32;
+                       }
                }
 
-               public MyBitVector Clone ()
+               public void Set (int index)
                {
-                       return Count == 0 ? Empty : new MyBitVector (this, Count);
+                       if (CopyOnWrite && !this[index])
+                               Clone ();
+
+                       SetBit (index);
                }
 
-               public void SetRange (int offset, int length)
+               public void Set (int index, int length)
                {
-                       if (offset > Count || offset + length > Count)
-                               throw new ArgumentOutOfRangeException ("flow-analysis");
+                       for (int i = 0; i < length; ++i) {
+                               if (CopyOnWrite && !this[index + i])
+                                       Clone ();
 
-                       if (shared == null && vector == null)
-                               return;
+                               SetBit (index + i);
+                       }
+               }
 
-                       int i = 0;
-                       if (shared != null) {
-                               if (offset + length <= shared.Count) {
-                                       for (; i < length; ++i)
-                                               if (!shared [i+offset])
-                                                   break;
-                                       if (i == length)
-                                               return;
-                               }
-                               initialize_vector ();
+               public bool this[int index] {
+                       get {
+                               return GetBit (index);
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       var length = Length;
+                       StringBuilder sb = new StringBuilder (length);
+                       for (int i = 0; i < length; ++i) {
+                               sb.Append (this[i] ? '1' : '0');
                        }
-                       for (; i < length; ++i)
-                               vector [i+offset] = true;
 
+                       return sb.ToString ();
                }
 
-               public void SetAll (bool value)
+               void Clone ()
                {
-                       // Don't clobber Empty
-                       if (Count == 0)
-                               return;
-                       shared = value ? null : Empty.MakeShared (Count);
-                       vector = null;
+                       large_bits = (int[]) large_bits.Clone ();
                }
 
-               void initialize_vector ()
+               bool GetBit (int index)
                {
-                       // Post-condition: vector != null
-                       if (shared == null) {
-                               vector = new System.Collections.BitArray (Count, true);
-                               return;
-                       }
+                       return large_bits == null ?
+                               (bits & (1 << index)) != 0 :
+                               (large_bits[index >> 5] & (1 << (index & 31))) != 0;
+               }
 
-                       vector = new System.Collections.BitArray (shared);
-                       if (Count != vector.Count)
-                               vector.Length = Count;
-                       shared = null;
+               void SetBit (int index)
+               {
+                       if (large_bits == null)
+                               bits = (uint) ((int) bits | (1 << index));
+                       else
+                               large_bits[index >> 5] |= (1 << (index & 31));
                }
 
-               StringBuilder Dump (StringBuilder sb)
+               static bool IsEqual (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       var dump = vector == null ? shared : vector;
-                       if (dump == null)
-                               return sb.Append ("/");
-                       if (dump == shared)
-                               sb.Append ("=");
-                       for (int i = 0; i < dump.Count; i++)
-                               sb.Append (dump [i] ? "1" : "0");
-                       return sb;
+                       if (a.large_bits == null)
+                               return (a.bits & ~copy_on_write_flag) == (b.bits & ~copy_on_write_flag);
+
+                       for (int i = 0; i < a.large_bits.Length; ++i) {
+                               if (a.large_bits[i] != b.large_bits[i])
+                                       return false;
+                       }
+
+                       return true;
                }
 
-               public override string ToString ()
+               public static bool IsIncluded (DefiniteAssignmentBitSet set, DefiniteAssignmentBitSet test)
                {
-                       return Dump (new StringBuilder ("{")).Append ("}").ToString ();
+                       var set_bits = set.large_bits;
+                       if (set_bits == null)
+                               return (set.bits & test.bits & ~copy_on_write_flag) == (set.bits & ~copy_on_write_flag);
+
+                       var test_bits = test.large_bits;
+                       for (int i = 0; i < set_bits.Length; ++i) {
+                               if ((set_bits[i] & test_bits[i]) != set_bits[i])
+                                       return false;
+                       }
+
+                       return true;
                }
        }
 }