From bfe949041c9e41a0c0e6f4fa7d7340579350b690 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Mon, 27 Jul 2009 11:28:11 +0000 Subject: [PATCH] 2009-07-27 Mark Probst * 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 * method-to-ir.c: Invoke write barriers for the Interlocked.(Compare)Exchange JIT intrinsics. svn path=/trunk/mono/; revision=138722 --- mono/metadata/ChangeLog | 6 ++++++ mono/metadata/icall-def.h | 4 ++-- mono/metadata/threads-types.h | 2 ++ mono/metadata/threads.c | 34 ++++++++++++++++++++++++---------- mono/mini/ChangeLog | 5 +++++ mono/mini/method-to-ir.c | 25 +++++++++++++++++++------ 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index d6d3c3a1f68..70dde5036af 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,9 @@ +2009-07-27 Mark Probst + + * 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 * icall.c (ves_icall_Type_GetNestedType): Throw an exception when diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 56908ae0e79..4341a5a52f8 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -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) diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index d1c8346fbf5..7e83c51f9cf 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -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; diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 530d16bcdeb..4182e1d9d8f 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -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 diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 010c8bb54f5..d40fc212fe3 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,8 @@ +2009-07-27 Mark Probst + + * method-to-ir.c: Invoke write barriers for the + Interlocked.(Compare)Exchange JIT intrinsics. + 2009-07-26 Raja R Harinath * Makefile.am (version.h): Fix issues when built out of tree. diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 14b561cb6a0..9f9c21b2818 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -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 */ -- 2.25.1