[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>
Mon, 1 Dec 2014 09:26:51 +0000 (10:26 +0100)
mcs/class/corlib/Test/System/ArrayTest.cs
mono/metadata/class.c
mono/metadata/icall.c

index fbea6549dc9041e1a42486dc3ea3444f42719e81..a1cc1a008cbec9353c146b199a7d85475a671282 100644 (file)
@@ -3618,5 +3618,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 9ae7c6e3325ce9c2daef6cd44419ec3851ed5e97..93853e594c1860a881bb3fabfbf4c485565b33eb 100644 (file)
@@ -2148,12 +2148,18 @@ mono_class_setup_methods (MonoClass *class)
                MonoMethodSignature *sig;
                int count_generic = 0, first_generic = 0;
                int method_num = 0;
+               gboolean jagged_ctor = FALSE;
 
                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 = count;
@@ -2182,6 +2188,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 e3241865924fdf0a556d48d22c0d07aed1920b10..e91e9e99d2625170e122505c043bfd5226ec5c4d 100644 (file)
@@ -2843,6 +2843,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;