Implement MethodMirror.MakeGenericMethod ().
authorZoltan Varga <vargaz@gmail.com>
Tue, 4 Jun 2013 06:01:22 +0000 (08:01 +0200)
committerZoltan Varga <vargaz@gmail.com>
Tue, 4 Jun 2013 06:01:32 +0000 (08:01 +0200)
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mcs/class/System.Core/Test/System.Linq/EnumerableMoreTest.cs
mcs/class/corlib/System/Array.cs
mono/mini/debugger-agent.c

index c7c1c02dde183c0651c178a948b1612b88c0caa0..105ff4fb67dbe949566a7949661634af7f4d3164 100644 (file)
@@ -395,7 +395,7 @@ namespace Mono.Debugger.Soft
                 * with newer runtimes, and vice versa.
                 */
                internal const int MAJOR_VERSION = 2;
-               internal const int MINOR_VERSION = 23;
+               internal const int MINOR_VERSION = 24;
 
                enum WPSuspendPolicy {
                        NONE = 0,
@@ -519,7 +519,8 @@ namespace Mono.Debugger.Soft
                        GET_INFO = 6,
                        GET_BODY = 7,
                        RESOLVE_TOKEN = 8,
-                       GET_CATTRS = 9
+                       GET_CATTRS = 9,
+                       MAKE_GENERIC_METHOD = 10
                }
 
                enum CmdType {
@@ -1875,6 +1876,11 @@ namespace Mono.Debugger.Soft
                        return ReadCattrs (r);
                }
 
+               internal long Method_MakeGenericMethod (long id, long[] args) {
+                       PacketReader r = SendReceive (CommandSet.METHOD, (int)CmdMethod.MAKE_GENERIC_METHOD, new PacketWriter ().WriteId (id).WriteInt (args.Length).WriteIds (args));
+                       return r.ReadId ();
+               }
+
                /*
                 * THREAD
                 */
index ac97cb02fb43742c806aedec74020c48f04d6e00..04717c61062dbc191a2f8c662782b326a74eb8d6 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
 using System.Reflection;
 using C = Mono.Cecil;
@@ -306,6 +307,30 @@ namespace Mono.Debugger.Soft
                        return type_args;
                }
 
+               // Since protocol version 2.24
+               public MethodMirror MakeGenericMethod (TypeMirror[] args) {
+                       if (args == null)
+                               throw new ArgumentNullException ("args");
+                       foreach (var a in args)
+                               if (a == null)
+                                       throw new ArgumentNullException ("args");
+
+                       if (!IsGenericMethodDefinition)
+                               throw new InvalidOperationException ("not a generic method definition");
+
+                       if (GetGenericArguments ().Length != args.Length)
+                               throw new ArgumentException ("Incorrect length");
+
+                       vm.CheckProtocolVersion (2, 24);
+                       long id = -1;
+                       try {
+                               id = vm.conn.Method_MakeGenericMethod (Id, args.Select (t => t.Id).ToArray ());
+                       } catch (CommandException) {
+                               throw new InvalidOperationException ();
+                       }
+                       return vm.GetMethod (id);
+               }
+
                public IList<int> ILOffsets {
                        get {
                                if (debug_info == null)
index 7d475e7dd0bb49d8db51b02508d14996699ffe16..29091d2dd832d269a487c799e18171664ac1b8d1 100644 (file)
@@ -1151,6 +1151,10 @@ public class Tests : TestsBase
                set_gc_suspend_field ();
                gc_suspend_1 ();
        }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void generic_method<T> () where T : class {
+       }
 }
 
 class TypeLoadClass {
index d998b4c021e430a64ed67f3318c594c3a9829fae..71c9ba7feacd580be6fbf0a14a3ff50c9fba44ea 100644 (file)
@@ -3174,6 +3174,36 @@ public class DebuggerTests
                var o2 = entry_point.DeclaringType.GetValue (entry_point.DeclaringType.GetField ("gc_suspend_field")) as ObjectMirror;
                Assert.IsNull (o2);
        }
+
+       [Test]
+       public void MakeGenericMethod () {
+               Event e = run_until ("bp1");
+
+               var intm = vm.RootDomain.GetCorrespondingType (typeof (int));
+               var stringm = vm.RootDomain.GetCorrespondingType (typeof (string));
+               var gm = entry_point.DeclaringType.GetMethod ("generic_method");
+               var res = gm.MakeGenericMethod (new TypeMirror [] { stringm });
+               var args = res.GetGenericArguments ();
+               Assert.AreEqual (1, args.Length);
+               Assert.AreEqual (stringm, args [0]);
+
+               // Error checking
+               AssertThrows<ArgumentNullException> (delegate {
+                               gm.MakeGenericMethod (null);
+                       });
+               AssertThrows<ArgumentNullException> (delegate {
+                               gm.MakeGenericMethod (new TypeMirror [] { null });
+                       });
+               AssertThrows<ArgumentException> (delegate {
+                               gm.MakeGenericMethod (new TypeMirror [] { stringm, stringm });
+                       });
+               AssertThrows<InvalidOperationException> (delegate {
+                               gm.MakeGenericMethod (new TypeMirror [] { intm });
+                       });
+               AssertThrows<InvalidOperationException> (delegate {
+                               entry_point.DeclaringType.GetMethod ("Main").MakeGenericMethod (new TypeMirror [] { intm });
+                       });
+       }
 }
 
 }
index 30b6738d4474aaa837dc2f242582b00c6800cd67..f5559ae00ea98c4d6b1ced3571c68675e2efaf60 100644 (file)
@@ -608,15 +608,27 @@ namespace MonoTests.System.Linq {
                        AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).Contains ("2", (IEqualityComparer<string>) EqualityComparer<string>.Default); });
                }
 
+               static void IsFalse(bool b, int[] data) {
+                       if (b) {
+                               Console.WriteLine (data.Contains (0));
+                               object o = null;
+                               o.ToString ();
+                               Assert.IsFalse (true);
+                       }
+                       //Console.WriteLine ("HIT!");
+               }
+
                [Test]
                public void ContainsTest ()
                {
                        int [] data = { 5, 2, 3, 1, 6 };
-
+                       ICollection<int> icoll = data;
 
                        // Contains<TSource> (TSource)
                        Assert.IsTrue (data.Contains (2));
-                       Assert.IsFalse (data.Contains (0));
+                       for (int i = 0; i < 50; ++i)
+                               Console.WriteLine (icoll.Contains (0));//Console.WriteLine (data.Contains (0));
+                       IsFalse (data.Contains (0), data);
 
                        // Contains<TSource> (TSource, IEqualityComparer<TSource>)
                        Assert.IsTrue (data.Contains (2, EqualityComparer<int>.Default));
index 2f90fbd131be5a982ef04f7d984020f5b257d767..91654019f146e6f8dde8272b6ca8848ad29a540c 100644 (file)
@@ -105,14 +105,16 @@ namespace System
                                T value;
                                GetGenericValueImpl (i, out value);
                                if (item == null){
-                                       if (value == null)
+                                       if (value == null) {
                                                return true;
+                                       }
 
                                        continue;
                                }
-                               
-                               if (item.Equals (value))
+
+                               if (item.Equals (value)) {
                                        return true;
+                               }
                        }
 
                        return false;
index fb913485e0cacfe5fcb6a2556b9f87ca116dab13..05c20169ed29f8e398904b53dc30a110f47ca9ca 100644 (file)
@@ -74,6 +74,7 @@ int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/runtime.h>
 #include <mono/metadata/threadpool.h>
+#include <mono/metadata/verify-internals.h>
 #include <mono/utils/mono-semaphore.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-stack-unwinding.h>
@@ -282,7 +283,7 @@ typedef struct {
 #define HEADER_LENGTH 11
 
 #define MAJOR_VERSION 2
-#define MINOR_VERSION 23
+#define MINOR_VERSION 24
 
 typedef enum {
        CMD_SET_VM = 1,
@@ -464,6 +465,7 @@ typedef enum {
        CMD_METHOD_GET_BODY = 7,
        CMD_METHOD_RESOLVE_TOKEN = 8,
        CMD_METHOD_GET_CATTRS = 9,
+       CMD_METHOD_MAKE_GENERIC_METHOD = 10
 } CmdMethod;
 
 typedef enum {
@@ -8096,6 +8098,40 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
                buffer_add_cattrs (buf, domain, method->klass->image, attr_klass, cinfo);
                break;
        }
+       case CMD_METHOD_MAKE_GENERIC_METHOD: {
+               MonoType **type_argv;
+               int i, type_argc;
+               MonoDomain *d;
+               MonoClass *klass;
+               MonoGenericInst *ginst;
+               MonoGenericContext tmp_context;
+               MonoMethod *inflated;
+
+               type_argc = decode_int (p, &p, end);
+               type_argv = g_new0 (MonoType*, type_argc);
+               for (i = 0; i < type_argc; ++i) {
+                       klass = decode_typeid (p, &p, end, &d, &err);
+                       if (err) {
+                               g_free (type_argv);
+                               return err;
+                       }
+                       if (domain != d) {
+                               g_free (type_argv);
+                               return ERR_INVALID_ARGUMENT;
+                       }
+                       type_argv [i] = &klass->byval_arg;
+               }
+               ginst = mono_metadata_get_generic_inst (type_argc, type_argv);
+               g_free (type_argv);
+               tmp_context.class_inst = method->klass->generic_class ? method->klass->generic_class->context.class_inst : NULL;
+               tmp_context.method_inst = ginst;
+
+               inflated = mono_class_inflate_generic_method (method, &tmp_context);
+               if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
+                       return ERR_INVALID_ARGUMENT;
+               buffer_add_methodid (buf, domain, inflated);
+               break;
+       }
        default:
                return ERR_NOT_IMPLEMENTED;
        }