Merge pull request #4967 from kumpera/profiler-arg-cleanup
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / CADMessages.cs
index 0f19f0249d1dec7d077f19057f1616b52cba56ad..4d20d6a67879155c1e8b32c91548f97ef55cede0 100644 (file)
@@ -51,14 +51,16 @@ namespace System.Runtime.Remoting.Messaging {
        }
        
        internal class CADObjRef {
-               ObjRef objref;
-               public int SourceDomain;
+               internal ObjRef objref;
+               internal int SourceDomain;
+               internal byte[] TypeInfo;
 
                public CADObjRef (ObjRef o, int sourceDomain) {
                        objref = o;
+                       TypeInfo = o.SerializeType ();
                        SourceDomain = sourceDomain;
                }
-               
+
                public string TypeName {
                        get { return objref.TypeInfo.TypeName; }
                }
@@ -68,78 +70,83 @@ namespace System.Runtime.Remoting.Messaging {
                }
        }
 
+       [Serializable]
+       internal class CADMethodRef
+       {
+               Type[] GetTypes (string[] typeArray)
+               {
+                       Type[] res = new Type [typeArray.Length];
+                       for (int i = 0; i < typeArray.Length; ++i)
+                               res [i] = Type.GetType (typeArray [i], true);
+                       return res;
+               }
+
+               bool ctor;
+               string typeName;
+               string methodName;
+               string[] param_names;
+               string[] generic_arg_names;
+
+               public MethodBase Resolve ()
+               {
+                       Type type = Type.GetType (typeName, true);
+                       MethodBase sig_cand = null;
+                       Type[] param_types = GetTypes (param_names);
+                       if (ctor)
+                               sig_cand = type.GetConstructor (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+                       else
+                               sig_cand = type.GetMethod (methodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+
+                       if (sig_cand != null && generic_arg_names != null)
+                               sig_cand = ((MethodInfo)sig_cand).MakeGenericMethod (GetTypes (generic_arg_names));
+
+                       if (sig_cand == null)
+                               throw new RemotingException ($"Method '{methodName}' not found in type '{typeName}'");
+
+                       return sig_cand;
+               }
+
+               public CADMethodRef (IMethodMessage msg)
+               {
+                       MethodBase method = msg.MethodBase;
+                       typeName = method.DeclaringType.AssemblyQualifiedName;
+                       ctor = method.IsConstructor;
+                       methodName = method.Name;
+
+                       if (!ctor && method.IsGenericMethod) {
+                               var ga = method.GetGenericArguments ();
+                               generic_arg_names = new string [ga.Length];
+                               for (int i = 0; i < ga.Length; ++i)
+                                       generic_arg_names [i] = ga [i].AssemblyQualifiedName;
+
+                               method = ((MethodInfo)method).GetGenericMethodDefinition ();
+                       }
+
+                       var param_types = method.GetParameters ();
+                       param_names = new string [param_types.Length];
+                       for (int i = 0; i < param_types.Length; ++i)
+                               param_names [i] = param_types [i].ParameterType.AssemblyQualifiedName;
+               }
+       }
+
        internal class CADMessageBase {
 
                protected object [] _args;
                protected byte [] _serializedArgs = null;
                protected int _propertyCount = 0;
                protected CADArgHolder _callContext;
-               internal RuntimeMethodHandle MethodHandle;
-               internal string FullTypeName;
-               internal MethodBase _method;
+               internal byte[] serializedMethod;
 
                public CADMessageBase (IMethodMessage msg) {
-                       MethodHandle = msg.MethodBase.MethodHandle;
-                       FullTypeName = msg.MethodBase.DeclaringType.AssemblyQualifiedName;
-               }
-
-               internal MethodBase method {
-                       get {
-                               if (_method == null) {
-                                       _method = GetMethod();
-                               }
-                               return _method;
-                       }
+                       CADMethodRef methodRef = new CADMethodRef (msg);
+                       serializedMethod = CADSerializer.SerializeObject (methodRef).GetBuffer ();
                }
 
                internal MethodBase GetMethod ()
                {
-                       Type tt = Type.GetType (FullTypeName, true);
-                       if (tt.IsGenericType || tt.IsGenericTypeDefinition) {
-                               _method = MethodBase.GetMethodFromHandleNoGenericCheck (MethodHandle);
-                       } else {
-                               _method = MethodBase.GetMethodFromHandle (MethodHandle);
-                       }
+                       CADMethodRef methRef = (CADMethodRef)CADSerializer.DeserializeObjectSafe (serializedMethod);
 
-                       if (tt != _method.DeclaringType) {
-                               // The target domain has loaded the type from a different assembly.
-                               // We need to locate the correct type and get the method from it
-                               Type [] signature = GetSignature (_method, true);
-                               if (_method.IsGenericMethod) {
-                                       MethodBase [] methods = tt.GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
-                                       Type [] base_args = _method.GetGenericArguments ();
-                                       foreach (MethodBase method in methods) {
-                                               if (!method.IsGenericMethod || method.Name != _method.Name)
-                                                       continue;
-                                               Type [] method_args = method.GetGenericArguments ();
-                                               if (base_args.Length != method_args.Length)
-                                                       continue;
-
-                                               MethodInfo method_instance = ((MethodInfo) method).MakeGenericMethod (base_args);
-                                               Type [] base_sig = GetSignature (method_instance, false);
-                                               if (base_sig.Length != signature.Length) {
-                                                       continue;
-                                               }
-                                               bool dont = false;
-                                               for (int i = base_sig.Length - 1; i >= 0; i--) {
-                                                       if (base_sig [i] != signature [i]) {
-                                                               dont = true;
-                                                               break;
-                                                       }
-                                               }
-                                               if (dont)
-                                                       continue;
-                                               return method_instance;
-                                       }
-                                       return _method;
-                               }
-
-                               MethodBase mb = tt.GetMethod (_method.Name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, signature, null);
-                               if (mb == null)
-                                       throw new RemotingException ("Method '" + _method.Name + "' not found in type '" + tt + "'");
-                               return mb;
-                       }
-                       return _method;
+                       return methRef.Resolve ();
                }
 
                static protected Type [] GetSignature (MethodBase methodBase, bool load)
@@ -156,6 +163,7 @@ namespace System.Runtime.Remoting.Messaging {
                        }
                        return signature;
                }
+
                // Helper to marshal properties
                internal static int MarshalProperties (IDictionary dict, ref ArrayList args) {
                        IDictionary serDict = dict;
@@ -241,7 +249,7 @@ namespace System.Runtime.Remoting.Messaging {
                        return new CADArgHolder(args.Count - 1);
                }
 
-               protected object UnmarshalArgument (object arg, ArrayList args, Type argType) {
+               protected object UnmarshalArgument (object arg, ArrayList args) {
                        if (arg == null) return null;
                        
                        // Check if argument is an holder (then we know that it's a serialized argument)
@@ -252,19 +260,7 @@ namespace System.Runtime.Remoting.Messaging {
 
                        CADObjRef objref = arg as CADObjRef;
                        if (null != objref) {
-                               string typeName;
-
-                               if (argType != null) {
-                                       typeName = string.Copy (argType.AssemblyQualifiedName);
-                               } else {
-                                       typeName = string.Copy (objref.TypeName);
-                               }
-
-                               string uri = string.Copy (objref.URI);
-                               int domid = objref.SourceDomain;
-                               
-                               ChannelInfo cinfo = new ChannelInfo (new CrossAppDomainData (domid));
-                               ObjRef localRef = new ObjRef (typeName, uri, cinfo);
+                               ObjRef localRef = objref.objref.DeserializeInTheCurrentDomain (objref.SourceDomain, objref.TypeInfo);
                                return RemotingServices.Unmarshal (localRef);
                        }
                        
@@ -334,12 +330,12 @@ namespace System.Runtime.Remoting.Messaging {
                        return marshalledArgs;
                }
 
-               internal object [] UnmarshalArguments (object [] arguments, ArrayList args, Type [] sig) {
+               internal object [] UnmarshalArguments (object [] arguments, ArrayList args) {
                        object [] unmarshalledArgs = new object [arguments.Length];
 
                        int total = arguments.Length;
                        for (int i = 0; i < total; i++)
-                               unmarshalledArgs [i] = UnmarshalArgument (arguments [i], args, sig [i]);
+                               unmarshalledArgs [i] = UnmarshalArgument (arguments [i], args);
 
                        return unmarshalledArgs;
                }
@@ -416,8 +412,7 @@ namespace System.Runtime.Remoting.Messaging {
                }
 
                internal object [] GetArgs (ArrayList args) {
-                       Type [] sigs = GetSignature (method, true);
-                       return UnmarshalArguments (_args, args, sigs);
+                       return UnmarshalArguments (_args, args);
                }
 
                internal int PropertiesCount {
@@ -432,7 +427,9 @@ namespace System.Runtime.Remoting.Messaging {
        internal class CADMethodReturnMessage : CADMessageBase {
                object _returnValue;
                CADArgHolder _exception = null;
+#pragma warning disable 414
                Type [] _sig;
+#pragma warning restore
 
                static internal CADMethodReturnMessage Create (IMessage callMsg) {
                        IMethodReturnMessage msg = callMsg as IMethodReturnMessage;
@@ -450,7 +447,7 @@ namespace System.Runtime.Remoting.Messaging {
                        _returnValue = MarshalArgument ( retMsg.ReturnValue, ref serializeList);
                        _args = MarshalArguments ( retMsg.Args, ref serializeList);
 
-                       _sig = GetSignature (method, true);
+                       _sig = GetSignature (GetMethod (), true);
 
                        if (null != retMsg.Exception) {
                                if (null == serializeList)
@@ -482,17 +479,11 @@ namespace System.Runtime.Remoting.Messaging {
                }
 
                internal object [] GetArgs (ArrayList args) {
-                       return UnmarshalArguments (_args, args, _sig);
+                       return UnmarshalArguments (_args, args);
                }
 
                internal object GetReturnValue (ArrayList args) {
-                       MethodInfo minfo = method as MethodInfo;
-
-                       Type returnType = null;
-                       if (minfo != null)
-                               returnType = minfo.ReturnType;
-
-                       return UnmarshalArgument (_returnValue, args, returnType);
+                       return UnmarshalArgument (_returnValue, args);
                }
 
                internal Exception GetException(ArrayList args) {