[interp] intrinsify System.Array.UnsafeLoad
authorBernhard Urban <bernhard.urban@xamarin.com>
Wed, 17 May 2017 11:40:58 +0000 (13:40 +0200)
committerBernhard Urban <bernhard.urban@xamarin.com>
Wed, 17 May 2017 15:36:43 +0000 (17:36 +0200)
mono/mini/interp/interp.c
mono/mini/interp/transform.c

index 9000d63448ba999d71638a60ab9f0f8209b8556e..87d1781d6abb280338506f8b3a357d9550c88a49 100644 (file)
@@ -564,7 +564,7 @@ ves_array_create (MonoInvocation *frame, MonoDomain *domain, MonoClass *klass, M
 }
 
 static gint32
-ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame)
+ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame, gboolean safe)
 {
        g_assert (!frame->ex);
        MonoClass *ac = ((MonoObject *) ao)->vtable->klass;
@@ -575,7 +575,7 @@ ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame)
                        guint32 idx = sp [i].data.i;
                        guint32 lower = ao->bounds [i].lower_bound;
                        guint32 len = ao->bounds [i].length;
-                       if (idx < lower || (idx - lower) >= len) {
+                       if (safe && (idx < lower || (idx - lower) >= len)) {
                                frame->ex = mono_get_exception_index_out_of_range ();
                                FILL_IN_TRACE (frame->ex, frame);
                                return -1;
@@ -584,7 +584,7 @@ ves_array_calculate_index (MonoArray *ao, stackval *sp, MonoInvocation *frame)
                }
        } else {
                pos = sp [0].data.i;
-               if (pos >= ao->max_length) {
+               if (safe && pos >= ao->max_length) {
                        frame->ex = mono_get_exception_index_out_of_range ();
                        FILL_IN_TRACE (frame->ex, frame);
                        return -1;
@@ -604,7 +604,7 @@ ves_array_set (MonoInvocation *frame)
 
        g_assert (ac->rank >= 1);
 
-       gint32 pos = ves_array_calculate_index (ao, sp, frame);
+       gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
        if (frame->ex)
                return;
 
@@ -627,7 +627,7 @@ ves_array_set (MonoInvocation *frame)
 }
 
 static void
-ves_array_get (MonoInvocation *frame)
+ves_array_get (MonoInvocation *frame, gboolean safe)
 {
        stackval *sp = frame->stack_args + 1;
 
@@ -637,7 +637,7 @@ ves_array_get (MonoInvocation *frame)
 
        g_assert (ac->rank >= 1);
 
-       gint32 pos = ves_array_calculate_index (ao, sp, frame);
+       gint32 pos = ves_array_calculate_index (ao, sp, frame, safe);
        if (frame->ex)
                return;
 
@@ -655,7 +655,7 @@ ves_array_element_address (MonoInvocation *frame, MonoClass *required_type, Mono
 
        g_assert (ac->rank >= 1);
 
-       gint32 pos = ves_array_calculate_index (ao, sp, frame);
+       gint32 pos = ves_array_calculate_index (ao, sp, frame, TRUE);
        if (frame->ex)
                return NULL;
 
@@ -982,6 +982,10 @@ ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
                        stackval_from_data (mt, frame->retval, (char *) frame->stack_args, FALSE);
                        return;
                }
+               if (!strcmp (method->name, "UnsafeLoad")) {
+                       ves_array_get (frame, FALSE);
+                       return;
+               }
        }
 
        isinst_obj = mono_object_isinst_checked (obj, mono_defaults.array_class, &error);
@@ -992,7 +996,7 @@ ves_runtime_method (MonoInvocation *frame, ThreadContext *context)
                        return;
                }
                if (*name == 'G' && (strcmp (name, "Get") == 0)) {
-                       ves_array_get (frame);
+                       ves_array_get (frame, TRUE);
                        return;
                }
        }
index 69ef2c13fb66d4d1096bd1342531cf1b54fafef2..9354aa8737c61109ddc52c4e8e9744d18e05b506 100644 (file)
@@ -3523,7 +3523,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                header = mono_method_get_header (nm);
                mono_os_mutex_unlock(&calc_section);
        } else if (method->klass == mono_defaults.array_class) {
-               if (!strcmp (method->name, "UnsafeMov")) {
+               if (!strcmp (method->name, "UnsafeMov") || !strcmp (method->name, "UnsafeLoad")) {
                        mono_os_mutex_lock (&calc_section);
                        if (!runtime_method->transformed) {
                                runtime_method->code = g_malloc (sizeof (short));
@@ -3535,9 +3535,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                        mono_os_mutex_unlock(&calc_section);
                        mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
                        return NULL;
-               } else if (!strcmp (method->name, "UnsafeStore)")) {
-                       g_error ("TODO");
-               } else if (!strcmp (method->name, "UnsafeLoad)")) {
+               } else if (!strcmp (method->name, "UnsafeStore")) {
                        g_error ("TODO");
                }
        }