+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
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)
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)
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;
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)
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)
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
+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.
#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
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;
} 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 */