2009-07-27 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Mon, 27 Jul 2009 11:28:11 +0000 (11:28 -0000)
committerMark Probst <mark.probst@gmail.com>
Mon, 27 Jul 2009 11:28:11 +0000 (11:28 -0000)
        * icall-def.h, thread-types.h, threads.c: New separate icalls for
        Interlocked.(Compare)Exchange with object arguments, which invoke
        write barriers.

2009-07-27  Mark Probst  <mark.probst@gmail.com>

        * method-to-ir.c: Invoke write barriers for the
        Interlocked.(Compare)Exchange JIT intrinsics.

svn path=/trunk/mono/; revision=138722

mono/metadata/ChangeLog
mono/metadata/icall-def.h
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/mini/ChangeLog
mono/mini/method-to-ir.c

index d6d3c3a1f6880b972e28b8c8cb9c693f685954a6..70dde5036af69741ac9d9bfeaabe3d18e18b522a 100644 (file)
@@ -1,3 +1,9 @@
+2009-07-27  Mark Probst  <mark.probst@gmail.com>
+
+       * icall-def.h, thread-types.h, threads.c: New separate icalls for
+       Interlocked.(Compare)Exchange with object arguments, which invoke
+       write barriers.
+
 2009-07-26  Miguel de Icaza  <miguel@novell.com>
 
        * icall.c (ves_icall_Type_GetNestedType): Throw an exception when
index 56908ae0e79e8e15e864459fd08ff034c92b4a71..4341a5a52f8e40c9fc4b648e2e1f327b501c16a3 100644 (file)
@@ -815,7 +815,7 @@ ICALL(ILOCK_2, "Add(long&,long)", ves_icall_System_Threading_Interlocked_Add_Lon
 ICALL(ILOCK_3, "CompareExchange(T&,T,T)", ves_icall_System_Threading_Interlocked_CompareExchange_T)
 ICALL(ILOCK_4, "CompareExchange(double&,double,double)", ves_icall_System_Threading_Interlocked_CompareExchange_Double)
 ICALL(ILOCK_5, "CompareExchange(int&,int,int)", ves_icall_System_Threading_Interlocked_CompareExchange_Int)
-ICALL(ILOCK_6, "CompareExchange(intptr&,intptr,intptr)", ves_icall_System_Threading_Interlocked_CompareExchange_Object)
+ICALL(ILOCK_6, "CompareExchange(intptr&,intptr,intptr)", ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr)
 ICALL(ILOCK_7, "CompareExchange(long&,long,long)", ves_icall_System_Threading_Interlocked_CompareExchange_Long)
 ICALL(ILOCK_8, "CompareExchange(object&,object,object)", ves_icall_System_Threading_Interlocked_CompareExchange_Object)
 ICALL(ILOCK_9, "CompareExchange(single&,single,single)", ves_icall_System_Threading_Interlocked_CompareExchange_Single)
@@ -824,7 +824,7 @@ ICALL(ILOCK_11, "Decrement(long&)", ves_icall_System_Threading_Interlocked_Decre
 ICALL(ILOCK_12, "Exchange(T&,T)", ves_icall_System_Threading_Interlocked_Exchange_T)
 ICALL(ILOCK_13, "Exchange(double&,double)", ves_icall_System_Threading_Interlocked_Exchange_Double)
 ICALL(ILOCK_14, "Exchange(int&,int)", ves_icall_System_Threading_Interlocked_Exchange_Int)
-ICALL(ILOCK_15, "Exchange(intptr&,intptr)", ves_icall_System_Threading_Interlocked_Exchange_Object)
+ICALL(ILOCK_15, "Exchange(intptr&,intptr)", ves_icall_System_Threading_Interlocked_Exchange_IntPtr)
 ICALL(ILOCK_16, "Exchange(long&,long)", ves_icall_System_Threading_Interlocked_Exchange_Long)
 ICALL(ILOCK_17, "Exchange(object&,object)", ves_icall_System_Threading_Interlocked_Exchange_Object)
 ICALL(ILOCK_18, "Exchange(single&,single)", ves_icall_System_Threading_Interlocked_Exchange_Single)
index d1c8346fbf50a5a5306f020337df7c91f783eca2..7e83c51f9cf3ee73f193369f4b2aca988a3e7582 100644 (file)
@@ -96,12 +96,14 @@ gint64 ves_icall_System_Threading_Interlocked_Decrement_Long(gint64 * location)
 gint32 ves_icall_System_Threading_Interlocked_Exchange_Int(gint32 *location, gint32 value) MONO_INTERNAL;
 gint64 ves_icall_System_Threading_Interlocked_Exchange_Long(gint64 *location, gint64 value) MONO_INTERNAL;
 MonoObject *ves_icall_System_Threading_Interlocked_Exchange_Object(MonoObject **location, MonoObject *value) MONO_INTERNAL;
+gpointer ves_icall_System_Threading_Interlocked_Exchange_IntPtr(gpointer *location, gpointer value) MONO_INTERNAL;
 gfloat ves_icall_System_Threading_Interlocked_Exchange_Single(gfloat *location, gfloat value) MONO_INTERNAL;
 gdouble ves_icall_System_Threading_Interlocked_Exchange_Double(gdouble *location, gdouble value) MONO_INTERNAL;
 
 gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand) MONO_INTERNAL;
 gint64 ves_icall_System_Threading_Interlocked_CompareExchange_Long(gint64 *location, gint64 value, gint64 comparand) MONO_INTERNAL;
 MonoObject *ves_icall_System_Threading_Interlocked_CompareExchange_Object(MonoObject **location, MonoObject *value, MonoObject *comparand) MONO_INTERNAL;
+gpointer ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr(gpointer *location, gpointer value, gpointer comparand) MONO_INTERNAL;
 gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single(gfloat *location, gfloat value, gfloat comparand) MONO_INTERNAL;
 gdouble ves_icall_System_Threading_Interlocked_CompareExchange_Double(gdouble *location, gdouble value, gdouble comparand) MONO_INTERNAL;
 MonoObject* ves_icall_System_Threading_Interlocked_CompareExchange_T(MonoObject **location, MonoObject *value, MonoObject *comparand) MONO_INTERNAL;
index 530d16bcdeba9b6d7e70e71ef0153029c0f10053..4182e1d9d8f54aa29fd8559fc951dc2e3baed5c9 100644 (file)
@@ -1751,9 +1751,15 @@ gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gi
 
 MonoObject * ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject **location, MonoObject *value)
 {
-       MONO_ARCH_SAVE_REGS;
+       MonoObject *res;
+       res = (MonoObject *) InterlockedExchangePointer((gpointer *) location, value);
+       mono_gc_wbarrier_generic_nostore (location);
+       return res;
+}
 
-       return (MonoObject *) InterlockedExchangePointer((gpointer *) location, value);
+gpointer ves_icall_System_Threading_Interlocked_Exchange_IntPtr (gpointer *location, gpointer value)
+{
+       return InterlockedExchangePointer(location, value);
 }
 
 gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location, gfloat value)
@@ -1824,9 +1830,15 @@ gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *locati
 
 MonoObject * ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject **location, MonoObject *value, MonoObject *comparand)
 {
-       MONO_ARCH_SAVE_REGS;
+       MonoObject *res;
+       res = (MonoObject *) InterlockedCompareExchangePointer((gpointer *) location, value, comparand);
+       mono_gc_wbarrier_generic_nostore (location);
+       return res;
+}
 
-       return (MonoObject *) InterlockedCompareExchangePointer((gpointer *) location, value, comparand);
+gpointer ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr(gpointer *location, gpointer value, gpointer comparand)
+{
+       return InterlockedCompareExchangePointer(location, value, comparand);
 }
 
 gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *location, gfloat value, gfloat comparand)
@@ -1887,17 +1899,19 @@ ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, g
 MonoObject*
 ves_icall_System_Threading_Interlocked_CompareExchange_T (MonoObject **location, MonoObject *value, MonoObject *comparand)
 {
-       MONO_ARCH_SAVE_REGS;
-
-       return InterlockedCompareExchangePointer ((gpointer *)location, value, comparand);
+       MonoObject *res;
+       res = InterlockedCompareExchangePointer ((gpointer *)location, value, comparand);
+       mono_gc_wbarrier_generic_nostore (location);
+       return res;
 }
 
 MonoObject*
 ves_icall_System_Threading_Interlocked_Exchange_T (MonoObject **location, MonoObject *value)
 {
-       MONO_ARCH_SAVE_REGS;
-
-       return InterlockedExchangePointer ((gpointer *)location, value);
+       MonoObject *res;
+       res = InterlockedExchangePointer ((gpointer *)location, value);
+       mono_gc_wbarrier_generic_nostore (location);
+       return res;
 }
 
 gint32 
index 010c8bb54f54f51bb811ce3618ce060311edcdf5..d40fc212fe378c464251bcc769a6d6444c3b1e3a 100644 (file)
@@ -1,3 +1,8 @@
+2009-07-27  Mark Probst  <mark.probst@gmail.com>
+
+       * method-to-ir.c: Invoke write barriers for the
+       Interlocked.(Compare)Exchange JIT intrinsics.
+
 2009-07-26  Raja R Harinath  <harinath@hurrynot.org>
 
        * Makefile.am (version.h): Fix issues when built out of tree.
index 14b561cb6a078b2de9a314fad481eca4c27931c7..9f9c21b28185650ede6aa839332840112ea04331 100644 (file)
@@ -3966,17 +3966,16 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
 #ifdef MONO_ARCH_HAVE_ATOMIC_EXCHANGE
                if (strcmp (cmethod->name, "Exchange") == 0) {
                        guint32 opcode;
+                       gboolean is_ref = fsig->params [0]->type == MONO_TYPE_OBJECT;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4)
                                opcode = OP_ATOMIC_EXCHANGE_I4;
 #if SIZEOF_REGISTER == 8
-                       else if ((fsig->params [0]->type == MONO_TYPE_I8) ||
-                                        (fsig->params [0]->type == MONO_TYPE_I) ||
-                                        (fsig->params [0]->type == MONO_TYPE_OBJECT))
+                       else if (is_ref || (fsig->params [0]->type == MONO_TYPE_I8) ||
+                                       (fsig->params [0]->type == MONO_TYPE_I))
                                opcode = OP_ATOMIC_EXCHANGE_I8;
 #else
-                       else if ((fsig->params [0]->type == MONO_TYPE_I) ||
-                                        (fsig->params [0]->type == MONO_TYPE_OBJECT))
+                       else if (is_ref || (fsig->params [0]->type == MONO_TYPE_I))
                                opcode = OP_ATOMIC_EXCHANGE_I4;
 #endif
                        else
@@ -4003,15 +4002,23 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        default:
                                g_assert_not_reached ();
                        }
+
+#if HAVE_WRITE_BARRIERS
+                       if (is_ref) {
+                               MonoMethod *write_barrier = mono_gc_get_write_barrier ();
+                               mono_emit_method_call (cfg, write_barrier, &args [0], NULL);
+                       }
+#endif
                }
 #endif /* MONO_ARCH_HAVE_ATOMIC_EXCHANGE */
  
 #ifdef MONO_ARCH_HAVE_ATOMIC_CAS
                if ((strcmp (cmethod->name, "CompareExchange") == 0)) {
                        int size = 0;
+                       gboolean is_ref = MONO_TYPE_IS_REFERENCE (fsig->params [1]);
                        if (fsig->params [1]->type == MONO_TYPE_I4)
                                size = 4;
-                       else if (fsig->params [1]->type == MONO_TYPE_I || MONO_TYPE_IS_REFERENCE (fsig->params [1]))
+                       else if (is_ref || fsig->params [1]->type == MONO_TYPE_I)
                                size = sizeof (gpointer);
                        else if (sizeof (gpointer) == 8 && fsig->params [1]->type == MONO_TYPE_I4)
                                size = 8;
@@ -4034,6 +4041,12 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        } else {
                                /* g_assert_not_reached (); */
                        }
+#if HAVE_WRITE_BARRIERS
+                       if (is_ref) {
+                               MonoMethod *write_barrier = mono_gc_get_write_barrier ();
+                               mono_emit_method_call (cfg, write_barrier, &args [0], NULL);
+                       }
+#endif
                }
 #endif /* MONO_ARCH_HAVE_ATOMIC_CAS */