X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdelegate.cs;h=a73c9f68c75cb81a94973da5046804f9d6c7163e;hb=04403c39d29635436db8fb677ea6a6423cf6c72b;hp=9492103f782c952a34b28bdac6acdf681951e259;hpb=694ab7d8477ba306f75ee1cb71ec8acd87788f67;p=mono.git diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 9492103f782..a73c9f68c75 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -28,7 +28,7 @@ namespace Mono.CSharp { // // Delegate container implementation // - public class Delegate : TypeContainer, IParametersMember + public class Delegate : TypeDefinition, IParametersMember { FullNamedExpression ReturnType; readonly ParametersCompiled parameters; @@ -55,10 +55,9 @@ namespace Mono.CSharp { Modifiers.UNSAFE | Modifiers.PRIVATE; - public Delegate (NamespaceContainer ns, DeclSpace parent, FullNamedExpression type, - Modifiers mod_flags, MemberName name, ParametersCompiled param_list, + public Delegate (TypeContainer parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, ParametersCompiled param_list, Attributes attrs) - : base (ns, parent, name, attrs, MemberKind.Delegate) + : base (parent, name, attrs, MemberKind.Delegate) { this.ReturnType = type; @@ -130,7 +129,7 @@ namespace Mono.CSharp { ); Constructor = new Constructor (this, Constructor.ConstructorName, - Modifiers.PUBLIC, null, ctor_parameters, null, Location); + Modifiers.PUBLIC, null, ctor_parameters, Location); Constructor.Define (); // @@ -185,7 +184,7 @@ namespace Mono.CSharp { TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); var resolved_rt = new TypeExpression (ret_type, Location); - InvokeBuilder = new Method (this, null, resolved_rt, MethodModifiers, new MemberName (InvokeMethodName), p, null); + InvokeBuilder = new Method (this, resolved_rt, MethodModifiers, new MemberName (InvokeMethodName), p, null); InvokeBuilder.Define (); // @@ -221,7 +220,7 @@ namespace Mono.CSharp { var p = parameters[i]; compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location), p.Name, - p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.ModFlags & Parameter.Modifier.RefOutMask, p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); } @@ -239,7 +238,7 @@ namespace Mono.CSharp { } ); - BeginInvokeBuilder = new Method (this, null, + BeginInvokeBuilder = new Method (this, new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers, new MemberName ("BeginInvoke"), async_parameters, null); BeginInvokeBuilder.Define (); @@ -256,7 +255,7 @@ namespace Mono.CSharp { int out_params = 0; foreach (Parameter p in Parameters.FixedParameters) { - if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) + if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0) ++out_params; } @@ -266,12 +265,12 @@ namespace Mono.CSharp { int param = 0; for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { Parameter p = parameters [i]; - if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) + if ((p.ModFlags & Parameter.Modifier.RefOutMask) == 0) continue; end_params [param++] = new Parameter (new TypeExpression (p.Type, Location), p.Name, - p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.ModFlags & Parameter.Modifier.RefOutMask, p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); } @@ -289,19 +288,21 @@ namespace Mono.CSharp { // // Create method, define parameters, register parameters with type system // - EndInvokeBuilder = new Method (this, null, returnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null); + EndInvokeBuilder = new Method (this, returnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null); EndInvokeBuilder.Define (); } - public override void DefineConstants () + public override void PrepareEmit () { if (!Parameters.IsEmpty) { parameters.ResolveDefaultValues (this); } } - public override void EmitType () + public override void Emit () { + base.Emit (); + if (ReturnType.Type != null) { if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); @@ -328,12 +329,6 @@ namespace Mono.CSharp { BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); } - - if (OptAttributes != null) { - OptAttributes.Emit (); - } - - base.Emit (); } protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) @@ -345,9 +340,7 @@ namespace Mono.CSharp { protected override TypeAttributes TypeAttr { get { - return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | - TypeAttributes.Class | TypeAttributes.Sealed | - base.TypeAttr; + return base.TypeAttr | TypeAttributes.Class | TypeAttributes.Sealed; } } @@ -443,12 +436,14 @@ namespace Mono.CSharp { protected MethodSpec constructor_method; protected MethodGroupExpr method_group; + public bool AllowSpecialMethodsInvocation { get; set; } + public override bool ContainsEmitWithAwait () { return false; } - public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc) + public static Arguments CreateDelegateMethodArguments (ResolveContext rc, AParametersCollection pd, TypeSpec[] types, Location loc) { Arguments delegate_arguments = new Arguments (pd.Count); for (int i = 0; i < pd.Count; ++i) { @@ -465,7 +460,11 @@ namespace Mono.CSharp { break; } - delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier)); + var ptype = types[i]; + if (ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + ptype = rc.BuiltinTypes.Object; + + delegate_arguments.Add (new Argument (new TypeExpression (ptype, loc), atype_modifier)); } return delegate_arguments; @@ -501,7 +500,7 @@ namespace Mono.CSharp { var invoke_method = Delegate.GetInvokeMethod (type); - Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc); + Arguments arguments = CreateDelegateMethodArguments (ec, invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); if (method_group == null) return null; @@ -514,7 +513,8 @@ namespace Mono.CSharp { return null; } - Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); + if (!AllowSpecialMethodsInvocation) + Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { @@ -527,12 +527,15 @@ namespace Mono.CSharp { } TypeSpec rt = delegate_method.ReturnType; + if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + rt = ec.BuiltinTypes.Object; + if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) { - Expression ret_expr = new TypeExpression (rt, loc); + Expression ret_expr = new TypeExpression (delegate_method.ReturnType, loc); Error_ConversionFailed (ec, delegate_method, ret_expr); } - if (delegate_method.IsConditionallyExcluded (ec.Module.Compiler, loc)) { + if (delegate_method.IsConditionallyExcluded (ec, loc)) { ec.Report.SymbolRelatedToPreviousError (delegate_method); MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { @@ -606,7 +609,7 @@ namespace Mono.CSharp { var invoke = Delegate.GetInvokeMethod (target_type); - Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location); + Arguments arguments = CreateDelegateMethodArguments (ec, invoke.Parameters, invoke.Parameters.Types, mg.Location); return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null; } @@ -642,18 +645,92 @@ namespace Mono.CSharp { // public class ImplicitDelegateCreation : DelegateCreation { - ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l) + Field mg_cache; + + public ImplicitDelegateCreation (TypeSpec delegateType, MethodGroupExpr mg, Location loc) { - type = t; + type = delegateType; this.method_group = mg; - loc = l; + this.loc = loc; + } + + // + // Returns true when type is MVAR or has MVAR reference + // + static bool ContainsMethodTypeParameter (TypeSpec type) + { + var tps = type as TypeParameterSpec; + if (tps != null) + return tps.IsMethodOwned; + + var ec = type as ElementTypeSpec; + if (ec != null) + return ContainsMethodTypeParameter (ec.Element); + + foreach (var t in type.TypeArguments) { + if (ContainsMethodTypeParameter (t)) { + return true; + } + } + + return false; + } + + protected override Expression DoResolve (ResolveContext ec) + { + var expr = base.DoResolve (ec); + if (expr == null) + return null; + + if (ec.IsInProbingMode) + return expr; + + // + // Cache any static delegate creation + // + if (method_group.InstanceExpression != null) + return expr; + + // + // Cannot easily cache types with MVAR + // + if (ContainsMethodTypeParameter (type)) + return expr; + + if (ContainsMethodTypeParameter (method_group.BestCandidate.DeclaringType)) + return expr; + + // + // Create type level cache for a delegate instance + // + var parent = ec.CurrentMemberDefinition.Parent.PartialContainer; + int id = parent.MethodGroupsCounter++; + + mg_cache = new Field (parent, new TypeExpression (type, loc), + Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, + new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "mg$cache", id), loc), null); + mg_cache.Define (); + parent.AddField (mg_cache); + + return expr; } - static public Expression Create (ResolveContext ec, MethodGroupExpr mge, - TypeSpec target_type, Location loc) + public override void Emit (EmitContext ec) { - ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc); - return d.DoResolve (ec); + Label l_initialized = ec.DefineLabel (); + + if (mg_cache != null) { + ec.Emit (OpCodes.Ldsfld, mg_cache.Spec); + ec.Emit (OpCodes.Brtrue_S, l_initialized); + } + + base.Emit (ec); + + if (mg_cache != null) { + ec.Emit (OpCodes.Stsfld, mg_cache.Spec); + ec.MarkLabel (l_initialized); + ec.Emit (OpCodes.Ldsfld, mg_cache.Spec); + } } }