Optimize little bit cloning operations.
authorMarek Safar <marek.safar@gmail.com>
Thu, 12 Aug 2010 14:31:33 +0000 (15:31 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 12 Aug 2010 14:33:24 +0000 (15:33 +0100)
mcs/errors/cs1706-4.cs [new file with mode: 0644]
mcs/mcs/anonymous.cs
mcs/mcs/constant.cs
mcs/mcs/context.cs
mcs/mcs/ecore.cs
mcs/mcs/generic.cs
mcs/mcs/import.cs
mcs/mcs/lambda.cs
mcs/mcs/method.cs
mcs/mcs/statement.cs

diff --git a/mcs/errors/cs1706-4.cs b/mcs/errors/cs1706-4.cs
new file mode 100644 (file)
index 0000000..887684b
--- /dev/null
@@ -0,0 +1,17 @@
+// CS1706: Anonymous methods and lambda expressions cannot be used in the current context
+// Line: 13
+
+using System;
+
+delegate int TestDelegate();
+
+class MyAttr : Attribute
+{
+       public MyAttr (TestDelegate d) { }
+}
+
+[MyAttr (() => 1)]
+class C
+{
+}
+
index 609c2092534e4d5e74958e3e9b979a8506a2666c..93661a903fe49ae10b46d127edf7c5fbfe0b84ab 100644 (file)
@@ -958,16 +958,24 @@ namespace Mono.CSharp {
 
                public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type)
                {
+                       Expression expr;
                        AnonymousExpression am;
+
+                       if (compatibles.TryGetValue (delegate_type, out expr)) {
+                               am = expr as AnonymousExpression;
+                               return am == null ? null : am.ReturnType;
+                       }
+
                        using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
                                am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
                                if (am != null)
                                        am = am.Compatible (ec);
                        }
-                       
+
                        if (am == null)
                                return null;
 
+//                     compatibles.Add (delegate_type, am);
                        return am.ReturnType;
                }
 
@@ -1042,9 +1050,10 @@ namespace Mono.CSharp {
                        } catch (Exception e) {
                                throw new InternalErrorException (e, loc);
                        }
-                       
-                       if (!ec.IsInProbingMode)
-                               compatibles.Add (type, am == null ? EmptyExpression.Null : am);
+
+                       if (!ec.IsInProbingMode) {
+                               compatibles.Add (type, am ?? EmptyExpression.Null);
+                       }
 
                        return am;
                }
@@ -1116,7 +1125,7 @@ namespace Mono.CSharp {
                        // 
                        type = InternalType.AnonymousMethod;
 
-                       if ((Parameters != null) && !Parameters.Resolve (ec))
+                       if (!DoResolveParameters (ec))
                                return null;
 
                        // FIXME: The emitted code isn't very careful about reachability
@@ -1128,6 +1137,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               protected virtual bool DoResolveParameters (ResolveContext rc)
+               {
+                       return Parameters.Resolve (rc);
+               }
+
                public override void Emit (EmitContext ec)
                {
                        // nothing, as we only exist to not do anything.
@@ -1270,11 +1284,14 @@ namespace Mono.CSharp {
 
                public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
                {
+                       if (block.Resolved)
+                               return this;
+
                        // TODO: Implement clone
                        BlockContext aec = new BlockContext (ec.MemberContext, Block, ReturnType);
                        aec.CurrentAnonymousMethod = ae;
 
-                       IDisposable aec_dispose = null;
+                       ResolveContext.FlagsHandle? aec_dispose = null;
                        ResolveContext.Options flags = 0;
                        if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
                                flags |= ResolveContext.Options.InferReturnType;
@@ -1313,7 +1330,7 @@ namespace Mono.CSharp {
                        }
 
                        if (aec_dispose != null) {
-                               aec_dispose.Dispose ();
+                               aec_dispose.Value.Dispose ();
                        }
 
                        if (res && errors != ec.Report.Errors)
index bf5062e741a0c66df1e229da36e3f18d6d45d320..f6c34b0499c3c00a8ff720e73ccad4e0841586bf 100644 (file)
@@ -249,9 +249,15 @@ namespace Mono.CSharp {
                        // do nothing
                }
 
+               public sealed override Expression Clone (CloneContext clonectx)
+               {
+                       // No cloning is not needed for constants
+                       return this;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
-                       // CloneTo: Nothing, we do not keep any state on this expression
+                       throw new NotSupportedException ("should not be reached");
                }
 
                public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
@@ -281,7 +287,8 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class IntegralConstant : Constant {
+       public abstract class IntegralConstant : Constant
+       {
                protected IntegralConstant (Location loc) :
                        base (loc)
                {
index 5823391e1d2d79f3e7a0b628e8289795cd361b17..2a86fd637c919a6facb9ce5dcdd7d37bfea5412d 100644 (file)
@@ -457,7 +457,7 @@ namespace Mono.CSharp
                public bool IsObsolete {
                        get {
                                // Disables obsolete checks when probing is on
-                               return IsInProbingMode || MemberContext.IsObsolete;
+                               return MemberContext.IsObsolete;
                        }
                }
 
@@ -502,9 +502,7 @@ namespace Mono.CSharp
 
                public void AddBlockMap (Block from, Block to)
                {
-                       if (block_map.ContainsKey (from))
-                               return;
-                       block_map[from] = to;
+                       block_map.Add (from, to);
                }
 
                public Block LookupBlock (Block from)
@@ -512,7 +510,6 @@ namespace Mono.CSharp
                        Block result;
                        if (!block_map.TryGetValue (from, out result)) {
                                result = (Block) from.Clone (this);
-                               block_map [from] = result;
                        }
 
                        return result;
index 83d0081113ce3f669c22ad4255366eb96cd28a95..00ae02eb128d277a888ac26744176e05b02626d1 100644 (file)
@@ -894,7 +894,7 @@ namespace Mono.CSharp {
                // compile the same code using different type values for the same
                // arguments to find the correct overload
                //
-               public Expression Clone (CloneContext clonectx)
+               public virtual Expression Clone (CloneContext clonectx)
                {
                        Expression cloned = (Expression) MemberwiseClone ();
                        CloneTo (clonectx, cloned);
index 33e403c8913d342a0d625fe99ad267bb2cdf0ace..08eab290dbc0c59c7a8289c398c2c3934fb93496 100644 (file)
@@ -2409,23 +2409,15 @@ namespace Mono.CSharp {
 
                        var a = bounds [index];
                        if (a == null) {
-                               a = new List<BoundInfo> ();
+                               a = new List<BoundInfo> (2);
+                               a.Add (bound);
                                bounds [index] = a;
-                       } else {
-                               if (a.Contains (bound))
-                                       return;
+                               return;
                        }
 
-                       //
-                       // SPEC: does not cover type inference using constraints
-                       //
-                       //if (TypeManager.IsGenericParameter (t)) {
-                       //    GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
-                       //    if (constraints != null) {
-                       //        //if (constraints.EffectiveBaseClass != null)
-                       //        //    t = constraints.EffectiveBaseClass;
-                       //    }
-                       //}
+                       if (a.Contains (bound))
+                               return;
+
                        a.Add (bound);
                }
                
index 234429676cc2497334d7fc40cac5074e3cd853c8..2412f64a1c0754d9a03f88026e24af0710d08533 100644 (file)
@@ -723,7 +723,9 @@ namespace Mono.CSharp
                                AttributesBag bag = null;
                                List<string> conditionals = null;
 
-                               var attrs = CustomAttributeData.GetCustomAttributes (mi);
+                               // It should not throw any loading exception
+                               IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes (mi);
+
                                foreach (var a in attrs) {
                                        var type = a.Constructor.DeclaringType;
                                        if (type == typeof (ObsoleteAttribute)) {
index eb4907b1816bd663a7df3120411ff50119a3f3ca..9ed980a925ffaeedee8172b1b43b5dcf0aa9eca1 100644 (file)
@@ -100,24 +100,21 @@ namespace Mono.CSharp {
                        return Parameters;
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ToplevelBlock b)
+               {
+                       return new LambdaMethod (p, b, returnType, delegateType, loc);
+               }
+
+               protected override bool DoResolveParameters (ResolveContext rc)
                {
                        //
                        // Only explicit parameters can be resolved at this point
                        //
                        if (HasExplicitParameters) {
-                               if (!Parameters.Resolve (ec))
-                                       return null;
+                               return Parameters.Resolve (rc);
                        }
 
-                       eclass = ExprClass.Value;
-                       type = InternalType.AnonymousMethod;
-                       return this;
-               }
-
-               protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ToplevelBlock b)
-               {
-                       return new LambdaMethod (p, b, returnType, delegateType, loc);
+                       return true;
                }
 
                public override string GetSignatureForError ()
@@ -126,7 +123,7 @@ namespace Mono.CSharp {
                }
        }
 
-       public class LambdaMethod : AnonymousMethodBody
+       class LambdaMethod : AnonymousMethodBody
        {
                public LambdaMethod (ParametersCompiled parameters,
                                        ToplevelBlock block, TypeSpec return_type, TypeSpec delegate_type,
index a99debb8065d2c96ff2730e8c1857b77998c89f9..ff095a4172e36dfdc68a7e17f4cc4e17329c8827 100644 (file)
@@ -808,6 +808,7 @@ namespace Mono.CSharp {
 
                public TypeParameterSpec[] TypeParameters {
                        get {
+                               // TODO: Cache this
                                return CurrentTypeParameters.Select (l => l.Type).ToArray ();
                        }
                }
index 9d2a1032c106e4d8151a59f2529422ba5b621536..4de8d7ab2c72b7a59ee5b4d2f63bc7fad52c1b19 100644 (file)
@@ -2249,8 +2249,9 @@ namespace Mono.CSharp {
 
                        clonectx.AddBlockMap (this, target);
 
-                       target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
-                       target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
+                       target.Toplevel = (ToplevelBlock) (Toplevel == this ? target : clonectx.LookupBlock (Toplevel));
+                       target.Explicit = (ExplicitBlock) (Explicit == this ? target : clonectx.LookupBlock (Explicit));
+
                        if (Parent != null)
                                target.Parent = clonectx.RemapBlockCopy (Parent);
 
@@ -2608,10 +2609,11 @@ namespace Mono.CSharp {
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
-                       ToplevelBlock target = (ToplevelBlock) t;
                        base.CloneTo (clonectx, t);
 
                        if (parameters.Count != 0) {
+                               ToplevelBlock target = (ToplevelBlock) t;
+
                                target.parameter_info = new ToplevelParameterInfo[parameters.Count];
                                for (int i = 0; i < parameters.Count; ++i)
                                        target.parameter_info[i] = new ToplevelParameterInfo (target, i);