[runtime] Add support for jagged array ctors which create an array of arrays. Fixes...
authorZoltan Varga <vargaz@gmail.com>
Wed, 26 Feb 2014 21:16:34 +0000 (16:16 -0500)
committerZoltan Varga <vargaz@gmail.com>
Wed, 26 Feb 2014 21:16:45 +0000 (16:16 -0500)
mcs/class/corlib/Test/System/ArrayTest.cs
mono/metadata/class.c
mono/metadata/icall.c

index eab4c40e1434ad47d8c4fb335497cb760a647a24..b0aea630b10e5788e1bde8ade615309f5ac5fd95 100644 (file)
@@ -3636,5 +3636,22 @@ public class ArrayTest
 
 #endif
 
+       [Test]
+       public void JaggedArrayCtor ()
+       {
+        var type = Type.GetType ("System.Object[][]");
+
+               ConstructorInfo ctor = null;
+        foreach (var c in type.GetConstructors ()) {
+                       if (c.GetParameters ().Length == 2)
+                               ctor = c;
+               }
+               Assert.IsNotNull (ctor);
+               var arr = (object[])ctor.Invoke (new object [] { 4, 10 });
+               for (int i = 0; i < 4; ++i) {
+                       Assert.IsNotNull (arr [i]);
+                       Assert.AreEqual (10, ((object[])arr [i]).Length);
+               }
+       }
 }
 }
index 36a86794e77bf55a723c6e26bebff446b1fdb4ce..6ba180402dd95a9e459c0b020e4bfc02e3e62eb3 100644 (file)
@@ -2084,12 +2084,18 @@ mono_class_setup_methods (MonoClass *class)
                MonoMethodSignature *sig;
                int count_generic = 0, first_generic = 0;
                int method_num = 0;
+               gboolean jagged_ctor = FALSE;
 
                class->method.count = 3 + (class->rank > 1? 2: 1);
 
                mono_class_setup_interfaces (class, &error);
                g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
 
+               if (class->rank == 1 && class->element_class->rank) {
+                       jagged_ctor = TRUE;
+                       class->method.count ++;
+               }
+
                if (class->interface_count) {
                        count_generic = generic_array_methods (class);
                        first_generic = class->method.count;
@@ -2118,6 +2124,19 @@ mono_class_setup_methods (MonoClass *class)
                        amethod = create_array_method (class, ".ctor", sig);
                        methods [method_num++] = amethod;
                }
+
+               if (jagged_ctor) {
+                       /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
+                       sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
+                       sig->ret = &mono_defaults.void_class->byval_arg;
+                       sig->pinvoke = TRUE;
+                       sig->hasthis = TRUE;
+                       for (i = 0; i < class->rank + 1; ++i)
+                               sig->params [i] = &mono_defaults.int32_class->byval_arg;
+                       amethod = create_array_method (class, ".ctor", sig);
+                       methods [method_num++] = amethod;
+               }
+
                /* element Get (idx11, [idx2, ...]) */
                sig = mono_metadata_signature_alloc (class->image, class->rank);
                sig->ret = &class->element_class->byval_arg;
index 40cac17433a0d11355545385e113f893baaf7b44..7e1563168ed5c3c680d920271e8d3a0fd969ecf5 100644 (file)
@@ -2830,6 +2830,18 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoAr
                for (i = 0; i < pcount; ++i)
                        lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
 
+               if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
+                       /* This is a ctor for jagged arrays. MS creates an array of arrays. */
+                       MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
+
+                       for (i = 0; i < mono_array_length (arr); ++i) {
+                               MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
+
+                               mono_array_setref_fast (arr, i, subarray);
+                       }
+                       return (MonoObject*)arr;
+               }
+
                if (m->klass->rank == pcount) {
                        /* Only lengths provided. */
                        lower_bounds = NULL;