projects
/
mono.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge pull request #654 from alesliehughes/master
[mono.git]
/
mono
/
metadata
/
monitor.c
diff --git
a/mono/metadata/monitor.c
b/mono/metadata/monitor.c
index f86ff5c0cd637264609614e96fdfdcd09a256dfd..9933f1dd48730ba5f4d5ae377a67752543063a85 100644
(file)
--- a/
mono/metadata/monitor.c
+++ b/
mono/metadata/monitor.c
@@
-26,6
+26,7
@@
#include <mono/metadata/marshal.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-time.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-time.h>
+#include <mono/utils/atomic.h>
/*
* Pull the list of opcodes
/*
* Pull the list of opcodes
@@
-242,7
+243,9
@@
mon_finalize (MonoThreadsSync *mon)
mon->data = monitor_freelist;
monitor_freelist = mon;
mon->data = monitor_freelist;
monitor_freelist = mon;
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_sync_blocks--;
mono_perfcounters->gc_sync_blocks--;
+#endif
}
/* LOCKING: this is called with monitor_mutex held */
}
/* LOCKING: this is called with monitor_mutex held */
@@
-268,7
+271,7
@@
mon_new (gsize id)
new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
}
}
new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
}
}
- mono_gc_weak_link_remove (&new->data);
+ mono_gc_weak_link_remove (&new->data
, FALSE
);
new->data = monitor_freelist;
monitor_freelist = new;
}
new->data = monitor_freelist;
monitor_freelist = new;
}
@@
-309,8
+312,11
@@
mon_new (gsize id)
new->owner = id;
new->nest = 1;
new->owner = id;
new->nest = 1;
+ new->data = NULL;
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_sync_blocks++;
mono_perfcounters->gc_sync_blocks++;
+#endif
return new;
}
return new;
}
@@
-536,7
+542,9
@@
retry:
}
/* The object must be locked by someone else... */
}
/* The object must be locked by someone else... */
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_contentions++;
mono_perfcounters->thread_contentions++;
+#endif
/* If ms is 0 we don't block, but just fail straight away */
if (ms == 0) {
/* If ms is 0 we don't block, but just fail straight away */
if (ms == 0) {
@@
-612,8
+620,10
@@
retry_contended:
InterlockedIncrement (&mon->entry_count);
InterlockedIncrement (&mon->entry_count);
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_queue_len++;
mono_perfcounters->thread_queue_max++;
mono_perfcounters->thread_queue_len++;
mono_perfcounters->thread_queue_max++;
+#endif
thread = mono_thread_internal_current ();
mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
thread = mono_thread_internal_current ();
mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
@@
-627,7
+637,9
@@
retry_contended:
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
InterlockedDecrement (&mon->entry_count);
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
InterlockedDecrement (&mon->entry_count);
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_queue_len--;
mono_perfcounters->thread_queue_len--;
+#endif
if (ms != INFINITE) {
now = mono_msec_ticks ();
if (ms != INFINITE) {
now = mono_msec_ticks ();
@@
-773,8
+785,10
@@
mono_monitor_get_object_monitor_weak_link (MonoObject *object)
return NULL;
}
return NULL;
}
+#ifndef DISABLE_JIT
+
static void
static void
-emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *syncp_true_false_branch,
+emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *
true_locktaken_branch, int *
syncp_true_false_branch,
int *thin_hash_branch, gboolean branch_on_true)
{
/*
int *thin_hash_branch, gboolean branch_on_true)
{
/*
@@
-785,6
+799,17
@@
emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch
mono_mb_emit_byte (mb, CEE_LDARG_0);
*obj_null_branch = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
mono_mb_emit_byte (mb, CEE_LDARG_0);
*obj_null_branch = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+ /*
+ ldarg.1
+ ldind.i1
+ brtrue.s true_locktaken
+ */
+ if (true_locktaken_branch) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDIND_I1);
+ *true_locktaken_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+ }
+
/*
ldarg 0 obj
conv.i objp
/*
ldarg 0 obj
conv.i objp
@@
-826,23
+851,58
@@
emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch
*syncp_true_false_branch = mono_mb_emit_short_branch (mb, branch_on_true ? CEE_BRTRUE_S : CEE_BRFALSE_S);
}
*syncp_true_false_branch = mono_mb_emit_short_branch (mb, branch_on_true ? CEE_BRTRUE_S : CEE_BRFALSE_S);
}
+#endif
+
+static MonoMethod* monitor_il_fastpaths[3];
+
+gboolean
+mono_monitor_is_il_fastpath_wrapper (MonoMethod *method)
+{
+ int i;
+ for (i = 0; i < 3; ++i) {
+ if (monitor_il_fastpaths [i] == method)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+enum {
+ FASTPATH_ENTER,
+ FASTPATH_ENTERV4,
+ FASTPATH_EXIT
+};
+
+
static MonoMethod*
static MonoMethod*
-
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method
)
+
register_fastpath (MonoMethod *method, int idx
)
{
{
- static MonoMethod *fast_monitor_enter;
- static MonoMethod *compare_exchange_method;
+ mono_memory_barrier ();
+ monitor_il_fastpaths [idx] = method;
+ return method;
+}
+static MonoMethod*
+mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
+{
MonoMethodBuilder *mb;
MonoMethodBuilder *mb;
- int obj_null_branch, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch, thin_hash_branch;
+ MonoMethod *res;
+ static MonoMethod *compare_exchange_method;
+ int obj_null_branch, true_locktaken_branch = 0, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch, thin_hash_branch;
int tid_loc, syncp_loc, owner_loc;
int thread_tls_offset;
int tid_loc, syncp_loc, owner_loc;
int thread_tls_offset;
+ gboolean is_v4 = mono_method_signature (monitor_enter_method)->param_count == 2;
+ int fast_path_idx = is_v4 ? FASTPATH_ENTERV4 : FASTPATH_ENTER;
+ WrapperInfo *info;
+
+ /* The !is_v4 version is not used/tested */
+ g_assert (is_v4);
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
- if (
fast_monitor_enter
)
- return
fast_monitor_enter
;
+ if (
monitor_il_fastpaths [fast_path_idx]
)
+ return
monitor_il_fastpaths [fast_path_idx]
;
if (!compare_exchange_method) {
MonoMethodDesc *desc;
if (!compare_exchange_method) {
MonoMethodDesc *desc;
@@
-857,17
+917,18
@@
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
return NULL;
}
return NULL;
}
- mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorEnter", MONO_WRAPPER_UNKNOWN);
+ mb = mono_mb_new (mono_defaults.monitor_class,
is_v4 ? "FastMonitorEnterV4" :
"FastMonitorEnter", MONO_WRAPPER_UNKNOWN);
mb->method->slot = -1;
mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC |
METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
mb->method->slot = -1;
mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC |
METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
+#ifndef DISABLE_JIT
tid_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
owner_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
tid_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
owner_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &syncp_null_branch, &thin_hash_branch, FALSE);
+ emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch,
is_v4 ? &true_locktaken_branch : NULL,
&syncp_null_branch, &thin_hash_branch, FALSE);
/*
mono. tls thread_tls_offset threadp
/*
mono. tls thread_tls_offset threadp
@@
-917,6
+978,12
@@
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
mono_mb_emit_byte (mb, CEE_LDC_I4_0);
mono_mb_emit_managed_call (mb, compare_exchange_method, NULL);
has_owner_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
mono_mb_emit_byte (mb, CEE_LDC_I4_0);
mono_mb_emit_managed_call (mb, compare_exchange_method, NULL);
has_owner_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+
+ if (is_v4) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
mono_mb_emit_byte (mb, CEE_RET);
/*
mono_mb_emit_byte (mb, CEE_RET);
/*
@@
-947,6
+1014,13
@@
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
mono_mb_emit_byte (mb, CEE_LDC_I4_1);
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_STIND_I4);
mono_mb_emit_byte (mb, CEE_LDC_I4_1);
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_STIND_I4);
+
+ if (is_v4) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
+
mono_mb_emit_byte (mb, CEE_RET);
/*
mono_mb_emit_byte (mb, CEE_RET);
/*
@@
-962,32
+1036,41
@@
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
mono_mb_patch_short_branch (mb, syncp_null_branch);
mono_mb_patch_short_branch (mb, has_owner_branch);
mono_mb_patch_short_branch (mb, other_owner_branch);
mono_mb_patch_short_branch (mb, syncp_null_branch);
mono_mb_patch_short_branch (mb, has_owner_branch);
mono_mb_patch_short_branch (mb, other_owner_branch);
+ if (true_locktaken_branch)
+ mono_mb_patch_short_branch (mb, true_locktaken_branch);
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_byte (mb, CEE_LDARG_0);
+ if (is_v4)
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_managed_call (mb, monitor_enter_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
mono_mb_emit_managed_call (mb, monitor_enter_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
+#endif
- fast_monitor_enter = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5);
- mono_mb_free (mb);
+ res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5), fast_path_idx);
- return fast_monitor_enter;
+ info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo));
+ info->subtype = is_v4 ? WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4 : WRAPPER_SUBTYPE_FAST_MONITOR_ENTER;
+ mono_marshal_set_wrapper_info (res, info);
+
+ mono_mb_free (mb);
+ return res;
}
static MonoMethod*
mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method)
{
}
static MonoMethod*
mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method)
{
- static MonoMethod *fast_monitor_exit;
-
MonoMethodBuilder *mb;
MonoMethodBuilder *mb;
+ MonoMethod *res;
int obj_null_branch, has_waiting_branch, has_syncp_branch, owned_branch, nested_branch, thin_hash_branch;
int thread_tls_offset;
int syncp_loc;
int obj_null_branch, has_waiting_branch, has_syncp_branch, owned_branch, nested_branch, thin_hash_branch;
int thread_tls_offset;
int syncp_loc;
+ WrapperInfo *info;
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
- if (
fast_monitor_exit
)
- return
fast_monitor_exit
;
+ if (
monitor_il_fastpaths [FASTPATH_EXIT]
)
+ return
monitor_il_fastpaths [FASTPATH_EXIT]
;
mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorExit", MONO_WRAPPER_UNKNOWN);
mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorExit", MONO_WRAPPER_UNKNOWN);
@@
-995,9
+1078,10
@@
mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method)
mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC |
METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC |
METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
+#ifndef DISABLE_JIT
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &has_syncp_branch, &thin_hash_branch, TRUE);
+ emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch,
NULL,
&has_syncp_branch, &thin_hash_branch, TRUE);
/*
ret
/*
ret
@@
-1121,11
+1205,16
@@
mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method)
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_managed_call (mb, monitor_exit_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_managed_call (mb, monitor_exit_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
+#endif
-
fast_monitor_exit = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5
);
+
res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5), FASTPATH_EXIT
);
mono_mb_free (mb);
mono_mb_free (mb);
- return fast_monitor_exit;
+ info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo));
+ info->subtype = WRAPPER_SUBTYPE_FAST_MONITOR_EXIT;
+ mono_marshal_set_wrapper_info (res, info);
+
+ return res;
}
MonoMethod*
}
MonoMethod*