X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fanonymous.cs;h=ce83e7674c14d88cc1b6c60145409209a83def58;hb=009d937c1df7d8949b7671c89426e33a11c6d284;hp=0e90b56126ac287d553fa059525a8ec33f94c9d7;hpb=457c9722a4bc7ead4d13d62dd6c4c56dfa24d8c0;p=mono.git diff --git a/mcs/mcs/anonymous.cs b/mcs/mcs/anonymous.cs index 0e90b56126a..ce83e7674c1 100644 --- a/mcs/mcs/anonymous.cs +++ b/mcs/mcs/anonymous.cs @@ -191,15 +191,27 @@ namespace Mono.CSharp { sealed class ThisInitializer : Statement { readonly HoistedThis hoisted_this; + readonly AnonymousMethodStorey parent; - public ThisInitializer (HoistedThis hoisted_this) + public ThisInitializer (HoistedThis hoisted_this, AnonymousMethodStorey parent) { this.hoisted_this = hoisted_this; + this.parent = parent; } protected override void DoEmit (EmitContext ec) { - hoisted_this.EmitAssign (ec, new CompilerGeneratedThis (ec.CurrentType, loc), false, false); + Expression source; + + if (parent == null) + source = new CompilerGeneratedThis (ec.CurrentType, loc); + else { + source = new FieldExpr (parent.HoistedThis.Field, Location.Null) { + InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null) + }; + } + + hoisted_this.EmitAssign (ec, source, false, false); } protected override void CloneTo (CloneContext clonectx, Statement target) @@ -229,6 +241,7 @@ namespace Mono.CSharp { public Expression Instance; bool initialize_hoisted_this; + AnonymousMethodStorey hoisted_this_parent; public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind) : base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation), @@ -238,13 +251,14 @@ namespace Mono.CSharp { ID = parent.Module.CounterAnonymousContainers++; } - public void AddCapturedThisField (EmitContext ec) + public void AddCapturedThisField (EmitContext ec, AnonymousMethodStorey parent) { TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); Field f = AddCompilerGeneratedField ("$this", type_expr); hoisted_this = new HoistedThis (this, f); initialize_hoisted_this = true; + hoisted_this_parent = parent; } public Field AddCapturedVariable (string name, TypeSpec type) @@ -315,8 +329,11 @@ namespace Mono.CSharp { var hoisted = localVariable.HoistedVariant; if (hoisted != null && hoisted.Storey != this && hoisted.Storey is StateMachine) { - // TODO: It's too late the field is defined in HoistedLocalVariable ctor + // + // Variable is already hoisted but we need it in storey which can be shared + // hoisted.Storey.hoisted_locals.Remove (hoisted); + hoisted.Storey.Members.Remove (hoisted.Field); hoisted = null; } @@ -550,7 +567,7 @@ namespace Mono.CSharp { // referenced indirectly // if (initialize_hoisted_this) { - rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); + rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent)); } // @@ -728,6 +745,12 @@ namespace Mono.CSharp { this.field = field; } + public Field Field { + get { + return field; + } + } + public AnonymousMethodStorey Storey { get { return storey; @@ -848,12 +871,6 @@ namespace Mono.CSharp { #region Properties - public Field Field { - get { - return field; - } - } - public bool IsAssigned { get; set; } public ParameterReference Parameter { @@ -893,12 +910,6 @@ namespace Mono.CSharp { : base (storey, field) { } - - public Field Field { - get { - return field; - } - } } // @@ -959,6 +970,12 @@ namespace Mono.CSharp { } } + public override bool IsSideEffectFree { + get { + return true; + } + } + public ParametersCompiled Parameters { get { return Block.Parameters; @@ -1010,9 +1027,9 @@ namespace Mono.CSharp { return null; } - protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters) + protected bool VerifyExplicitParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection parameters) { - if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode)) + if (VerifyParameterCompatibility (ec, tic, delegate_type, parameters, ec.IsInProbingMode)) return true; if (!ec.IsInProbingMode) @@ -1023,7 +1040,7 @@ namespace Mono.CSharp { return false; } - protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) + protected bool VerifyParameterCompatibility (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) { if (Parameters.Count != invoke_pd.Count) { if (ignore_errors) @@ -1044,10 +1061,10 @@ namespace Mono.CSharp { return false; if (p_mod == Parameter.Modifier.NONE) - ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", - (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags)); + ec.Report.Error (1677, Parameters[i].Location, "Parameter `{0}' should not be declared with the `{1}' keyword", + (i + 1).ToString (), Parameter.GetModifierSignature (Parameters [i].ModFlags)); else - ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", + ec.Report.Error (1676, Parameters[i].Location, "Parameter `{0}' must be declared with the `{1}' keyword", (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); error = true; } @@ -1056,19 +1073,15 @@ namespace Mono.CSharp { continue; TypeSpec type = invoke_pd.Types [i]; + + if (tic != null) + type = tic.InflateGenericArgument (ec, type); - // We assume that generic parameters are always inflated - if (TypeManager.IsGenericParameter (type)) - continue; - - if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type))) - continue; - - if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) { + if (!TypeSpecComparer.IsEqual (type, Parameters.Types [i])) { if (ignore_errors) return false; - ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", + ec.Report.Error (1678, Parameters [i].Location, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", (i+1).ToString (), Parameters.Types [i].GetSignatureForError (), invoke_pd.Types [i].GetSignatureForError ()); @@ -1082,7 +1095,7 @@ namespace Mono.CSharp { // // Infers type arguments based on explicit arguments // - public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type) + public bool ExplicitTypeInference (TypeInferenceContext type_inference, TypeSpec delegate_type) { if (!HasExplicitParameters) return false; @@ -1296,7 +1309,7 @@ namespace Mono.CSharp { return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); } - if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { + if (!VerifyExplicitParameters (ec, tic, delegate_type, delegate_parameters)) { return null; } @@ -1661,26 +1674,32 @@ namespace Mono.CSharp { if (src_block.HasCapturedThis) { // // Remove hoisted 'this' request when simple instance method is - // enough (no hoisted variables only 'this') + // enough. No hoisted variables only 'this' and don't need to + // propagate this to value type state machine. // - if (src_block.ParametersBlock.StateMachine == null) + StateMachine sm_parent; + var pb = src_block.ParametersBlock; + do { + sm_parent = pb.StateMachine; + pb = pb.Parent == null ? null : pb.Parent.ParametersBlock; + } while (sm_parent == null && pb != null); + + if (sm_parent == null) { top_block.RemoveThisReferenceFromChildrenBlock (src_block); - - // - // Special case where parent class is used to emit instance method - // because currect storey is of value type (async host). We cannot - // use ldftn on non-boxed instances either to share mutated state - // - if (sm != null && sm.Kind == MemberKind.Struct) { - parent = sm.Parent.PartialContainer; + } else if (sm_parent.Kind == MemberKind.Struct) { + // + // Special case where parent class is used to emit instance method + // because currect storey is of value type (async host) and we cannot + // use ldftn on non-boxed instances either to share mutated state + // + parent = sm_parent.Parent.PartialContainer; + } else if (sm is IteratorStorey) { + // + // For iterators we can host everything in one class + // + parent = storey = sm; } } - - // - // For iterators we can host everything in one class - // - if (sm is IteratorStorey) - parent = storey = sm; } modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; @@ -1803,12 +1822,8 @@ namespace Mono.CSharp { // Special case for value type storey where this is not lifted but // droped off to parent class // - for (var b = Block.Parent; b != null; b = b.Parent) { - if (b.ParametersBlock.StateMachine != null) { - ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec); - break; - } - } + if (ec.CurrentAnonymousMethod != null && ec.AsyncTaskStorey != null) + ec.Emit (OpCodes.Ldfld, ec.AsyncTaskStorey.HoistedThis.Field.Spec); } var delegate_method = method.Spec; @@ -1987,7 +2002,7 @@ namespace Mono.CSharp { Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), - Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); @@ -2096,7 +2111,7 @@ namespace Mono.CSharp { Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), - Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform