[runtime] Use coop handles for System.Array.SetValue
authorAleksey Kliger <aleksey@xamarin.com>
Tue, 20 Jun 2017 00:11:15 +0000 (20:11 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Tue, 20 Jun 2017 19:00:04 +0000 (15:00 -0400)
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/object-internals.h

index 65a0ac454c350e40e1f228df347ea412a41e1875..a6a68bde499bd28025b7d763c991735509efc26a 100644 (file)
@@ -158,7 +158,7 @@ ICALL(ARRAY_8, "GetRank",          ves_icall_System_Array_GetRank)
 ICALL(ARRAY_9, "GetValue",         ves_icall_System_Array_GetValue)
 ICALL(ARRAY_10, "GetValueImpl",     ves_icall_System_Array_GetValueImpl)
 ICALL(ARRAY_11, "SetGenericValueImpl", ves_icall_System_Array_SetGenericValueImpl)
-ICALL(ARRAY_12, "SetValue",         ves_icall_System_Array_SetValue)
+HANDLES(ICALL(ARRAY_12, "SetValue",         ves_icall_System_Array_SetValue))
 HANDLES(ICALL(ARRAY_13, "SetValueImpl",     ves_icall_System_Array_SetValueImpl))
 
 ICALL_TYPE(BUFFER, "System.Buffer", BUFFER_1)
index 1da38eec40534673c6e20eb905deca830bccd9cb..cdbab7561d41be8e8e2cd0ddb13502f302925a37 100644 (file)
@@ -229,17 +229,6 @@ ves_icall_System_Array_SetValueImpl (MonoArrayHandle arr, MonoObjectHandle value
        array_set_value_impl (arr, value, pos, error);
 }
 
-static void
-array_set_value_impl_raw (MonoArray *arr_raw, MonoObject *value_raw, guint32 pos, MonoError *error)
-{
-       HANDLE_FUNCTION_ENTER ();
-       MONO_HANDLE_DCL (MonoArray, arr);
-       MONO_HANDLE_DCL (MonoObject, value);
-       error_init (error);
-       array_set_value_impl (arr, value, pos, error);
-       HANDLE_FUNCTION_RETURN ();
-}
-
 static void
 array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
 {
@@ -269,7 +258,7 @@ array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos,
        ea = mono_array_handle_pin_with_size (arr, esize, pos, &arr_gchandle);
 
        if (mono_class_is_nullable (ec)) {
-               mono_nullable_init ((guint8*)ea, MONO_HANDLE_RAW (value), ec); /* FIXME: use coop handles for mono_nullable_init */
+               mono_nullable_init_from_handle ((guint8*)ea, value, ec);
                goto leave;
        }
 
@@ -541,53 +530,62 @@ leave:
 }
 
 ICALL_EXPORT void 
-ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
-                                MonoArray *idxs)
+ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value,
+                                MonoArrayHandle idxs, MonoError *error)
 {
-       MonoError error;
+       MonoArrayBounds dim;
        MonoClass *ac, *ic;
-       gint32 i, pos, *ind;
+       gint32 idx;
+       gint32 i, pos;
 
-       MONO_CHECK_ARG_NULL (idxs,);
+       error_init (error);
 
-       error_init (&error);
+       if (MONO_HANDLE_IS_NULL (idxs)) {
+               mono_error_set_argument_null (error, "idxs", "");
+               return;
+       }
 
-       ic = idxs->obj.vtable->klass;
-       ac = arr->obj.vtable->klass;
+       ic = mono_handle_class (idxs);
+       ac = mono_handle_class (arr);
 
        g_assert (ic->rank == 1);
-       if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
-               mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
+       if (mono_handle_array_has_bounds (idxs) || MONO_HANDLE_GETVAL (idxs, max_length) != ac->rank) {
+               mono_error_set_argument (error, "idxs", "");
                return;
        }
 
-       ind = (gint32 *)idxs->vector;
-
-       if (arr->bounds == NULL) {
-               if (*ind < 0 || *ind >= arr->max_length) {
-                       mono_set_pending_exception (mono_get_exception_index_out_of_range ());
+       if (!mono_handle_array_has_bounds (arr)) {
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
+               if (idx < 0 || idx >= MONO_HANDLE_GETVAL (arr, max_length)) {
+                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
                        return;
                }
 
-               array_set_value_impl_raw (arr, value, *ind, &error);
-               mono_error_set_pending_exception (&error);
+               array_set_value_impl (arr, value, idx, error);
                return;
        }
        
-       for (i = 0; i < ac->rank; i++)
-               if ((ind [i] < arr->bounds [i].lower_bound) ||
-                   (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
-                       mono_set_pending_exception (mono_get_exception_index_out_of_range ());
+       for (i = 0; i < ac->rank; i++) {
+               mono_handle_array_get_bounds_dim (arr, i, &dim);
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
+               if ((idx < dim.lower_bound) ||
+                   (idx >= (mono_array_lower_bound_t)dim.length + dim.lower_bound)) {
+                       mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
                        return;
                }
+       }
 
-       pos = ind [0] - arr->bounds [0].lower_bound;
-       for (i = 1; i < ac->rank; i++)
-               pos = pos * arr->bounds [i].length + ind [i] - 
-                       arr->bounds [i].lower_bound;
 
-       array_set_value_impl_raw (arr, value, pos, &error);
-       mono_error_set_pending_exception (&error);
+       MONO_HANDLE_ARRAY_GETVAL  (idx, idxs, gint32, 0);
+       mono_handle_array_get_bounds_dim (arr, 0, &dim);
+       pos = idx - dim.lower_bound;
+       for (i = 1; i < ac->rank; i++) {
+               mono_handle_array_get_bounds_dim (arr, i, &dim);
+               MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
+               pos = pos * dim.length + idx - dim.lower_bound;
+       }
+
+       array_set_value_impl (arr, value, pos, error);
 }
 
 ICALL_EXPORT MonoArray *
index af0eda302e52b2f6a5dd051789224bc00d6b473d..391e1cd994b314899300b48c87e4c525d8bf0cec 100644 (file)
@@ -160,6 +160,19 @@ struct _MonoString {
                mono_gc_wbarrier_arrayref_copy (__p, __s, (count));     \
        } while (0)
 
+static inline gboolean
+mono_handle_array_has_bounds (MonoArrayHandle arr)
+{
+       return MONO_HANDLE_GETVAL (arr, bounds) != NULL;
+}
+
+static inline void
+mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBounds *bounds)
+{
+       MonoArrayBounds *src = MONO_HANDLE_GETVAL (arr, bounds);
+       memcpy (bounds, &src[dim], sizeof (MonoArrayBounds));
+}
+
 
 typedef struct {
        MonoObject obj;