Skip to content

Commit

Permalink
[x86] Add monitor enter v4 fastpath.
Browse files Browse the repository at this point in the history
  • Loading branch information
BrzVlad committed Jan 13, 2015
1 parent 7786ec1 commit 5b0fbd4
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 26 deletions.
9 changes: 9 additions & 0 deletions mono/metadata/monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,15 @@ ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject
*lockTaken = res == 1;
}

void
mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken)
{
if (*lock_taken == 1)
mono_raise_exception (mono_get_exception_argument ("lockTaken", "lockTaken is already true"));

ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (obj, INFINITE, lock_taken);
}

gboolean
ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
{
Expand Down
3 changes: 3 additions & 0 deletions mono/metadata/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ mono_monitor_try_enter (MonoObject *obj, uint32_t ms);
MONO_API mono_bool
mono_monitor_enter (MonoObject *obj);

MONO_API void
mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken);

MONO_API unsigned int
mono_object_get_size (MonoObject *o);

Expand Down
11 changes: 10 additions & 1 deletion mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,9 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
/* We clobber ECX, since EAX is used as MONO_ARCH_MONITOR_OBJECT_REG */
#ifdef MONO_ARCH_MONITOR_OBJECT_REG
g_assert (MONO_ARCH_MONITOR_OBJECT_REG != X86_ECX);
#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
g_assert (MONO_ARCH_MONITOR_LOCK_TAKEN_REG != X86_ECX);
#endif
#endif

code = buf;
Expand Down Expand Up @@ -2960,6 +2963,7 @@ is_plt_patch (MonoJumpInfo *patch_info)
case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
return TRUE;
Expand Down Expand Up @@ -5081,6 +5085,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
}
case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_SEQ_POINT_INFO:
break;
Expand Down Expand Up @@ -5964,8 +5969,12 @@ emit_trampolines (MonoAotCompile *acfg)
mono_arch_get_nullified_class_init_trampoline (&info);
emit_trampoline (acfg, acfg->got_offset, info);
#if defined(MONO_ARCH_MONITOR_OBJECT_REG)
mono_arch_create_monitor_enter_trampoline (&info, TRUE);
mono_arch_create_monitor_enter_trampoline (&info, FALSE, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
mono_arch_create_monitor_enter_trampoline (&info, TRUE, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
#endif
mono_arch_create_monitor_exit_trampoline (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
#endif
Expand Down
4 changes: 4 additions & 0 deletions mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3240,6 +3240,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
Expand Down Expand Up @@ -4380,6 +4381,9 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou
} else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter")) {
target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
target = mono_create_ftnptr_malloc (target);
} else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter_v4")) {
target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
target = mono_create_ftnptr_malloc (target);
} else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
target = mono_create_ftnptr_malloc (target);
Expand Down
21 changes: 21 additions & 0 deletions mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static MonoMethodSignature *helper_sig_generic_class_init_trampoline_llvm;
static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
static MonoMethodSignature *helper_sig_monitor_enter_exit_trampoline;
static MonoMethodSignature *helper_sig_monitor_enter_exit_trampoline_llvm;
static MonoMethodSignature *helper_sig_monitor_enter_v4_trampoline_llvm;

/*
* Instruction metadata
Expand Down Expand Up @@ -364,6 +365,7 @@ mono_create_helper_signatures (void)
helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
helper_sig_monitor_enter_exit_trampoline = mono_create_icall_signature ("void");
helper_sig_monitor_enter_exit_trampoline_llvm = mono_create_icall_signature ("void object");
helper_sig_monitor_enter_v4_trampoline_llvm = mono_create_icall_signature ("void object ptr");
}

static MONO_NEVER_INLINE void
Expand Down Expand Up @@ -5585,6 +5587,25 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
}

return (MonoInst*)call;
#if defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
} else if (strcmp (cmethod->name, "Enter") == 0 && fsig->param_count == 2) {
MonoCallInst *call;

if (COMPILE_LLVM (cfg)) {
/*
* Pass the argument normally, the LLVM backend will handle the
* calling convention problems.
*/
call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER_V4, NULL, helper_sig_monitor_enter_v4_trampoline_llvm, args);
} else {
call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_MONITOR_ENTER_V4,
NULL, helper_sig_monitor_enter_exit_trampoline, NULL);
mono_call_inst_add_outarg_reg (cfg, call, args [0]->dreg, MONO_ARCH_MONITOR_OBJECT_REG, FALSE);
mono_call_inst_add_outarg_reg (cfg, call, args [1]->dreg, MONO_ARCH_MONITOR_LOCK_TAKEN_REG, FALSE);
}

return (MonoInst*)call;
#endif
} else if (strcmp (cmethod->name, "Exit") == 0) {
MonoCallInst *call;

Expand Down
3 changes: 2 additions & 1 deletion mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,8 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
* their own calling convention on some platforms.
*/
#ifndef TARGET_AMD64
if (abs_ji->type == MONO_PATCH_INFO_MONITOR_ENTER || abs_ji->type == MONO_PATCH_INFO_MONITOR_EXIT || abs_ji->type == MONO_PATCH_INFO_GENERIC_CLASS_INIT)
if (abs_ji->type == MONO_PATCH_INFO_MONITOR_ENTER || abj_ji->type == MONO_PATCH_INFO_MONITOR_ENTER_V4 ||
abs_ji->type == MONO_PATCH_INFO_MONITOR_EXIT || abs_ji->type == MONO_PATCH_INFO_GENERIC_CLASS_INIT)
LLVM_FAILURE (ctx, "trampoline with own cconv");
#endif
target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE);
Expand Down
47 changes: 46 additions & 1 deletion mono/mini/mini-trampolines.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,17 @@ mono_monitor_enter_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, gui
mono_monitor_enter (obj);
}

void
mono_monitor_enter_v4_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
{
#ifdef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
char *lock_taken = (char*)regs [MONO_ARCH_MONITOR_LOCK_TAKEN_REG];
mono_monitor_enter_v4 (obj, lock_taken);
#else
g_assert_not_reached ();
#endif
}

void
mono_monitor_exit_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp)
{
Expand Down Expand Up @@ -1255,6 +1266,8 @@ mono_get_trampoline_func (MonoTrampolineType tramp_type)
#endif
case MONO_TRAMPOLINE_MONITOR_ENTER:
return mono_monitor_enter_trampoline;
case MONO_TRAMPOLINE_MONITOR_ENTER_V4:
return mono_monitor_enter_v4_trampoline;
case MONO_TRAMPOLINE_MONITOR_EXIT:
return mono_monitor_exit_trampoline;
case MONO_TRAMPOLINE_VCALL:
Expand Down Expand Up @@ -1306,6 +1319,7 @@ mono_trampolines_init (void)
mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING] = create_trampoline_code (MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING);
#endif
mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER);
mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_ENTER_V4] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_ENTER_V4);
mono_trampoline_code [MONO_TRAMPOLINE_MONITOR_EXIT] = create_trampoline_code (MONO_TRAMPOLINE_MONITOR_EXIT);
mono_trampoline_code [MONO_TRAMPOLINE_VCALL] = create_trampoline_code (MONO_TRAMPOLINE_VCALL);
#ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
Expand Down Expand Up @@ -1641,7 +1655,37 @@ mono_create_monitor_enter_trampoline (void)
if (!code) {
MonoTrampInfo *info;

code = mono_arch_create_monitor_enter_trampoline (&info, FALSE);
code = mono_arch_create_monitor_enter_trampoline (&info, FALSE, FALSE);
mono_tramp_info_register (info);
}

mono_trampolines_unlock ();
#else
code = NULL;
g_assert_not_reached ();
#endif

return code;
}

gpointer
mono_create_monitor_enter_v4_trampoline (void)
{
static gpointer code;

if (mono_aot_only) {
if (!code)
code = mono_aot_get_trampoline ("monitor_enter_v4_trampoline");
return code;
}

#if defined(MONO_ARCH_MONITOR_OBJECT_REG) && defined(MONO_ARCH_MONITOR_LOCK_TAKEN_REG)
mono_trampolines_lock ();

if (!code) {
MonoTrampInfo *info;

code = mono_arch_create_monitor_enter_trampoline (&info, TRUE, FALSE);
mono_tramp_info_register (info);
}

Expand Down Expand Up @@ -1749,6 +1793,7 @@ static const char*tramp_names [MONO_TRAMPOLINE_NUM] = {
"restore_stack_prot",
"generic_virtual_remoting",
"monitor_enter",
"monitor_enter_v4",
"monitor_exit",
"vcall",
"handler_block_guard"
Expand Down
1 change: 1 addition & 0 deletions mono/mini/mini-x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -5056,6 +5056,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
case MONO_PATCH_INFO_RGCTX_FETCH:
case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
#if defined(__native_client_codegen__) && defined(__native_client__)
Expand Down
1 change: 1 addition & 0 deletions mono/mini/mini-x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ typedef struct {
#define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
#if defined(__linux__) || defined (__APPLE__)
#define MONO_ARCH_MONITOR_OBJECT_REG X86_EAX
#define MONO_ARCH_MONITOR_LOCK_TAKEN_REG X86_EDX
#endif
#if !defined(__native_client_codegen__)
#define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
Expand Down
4 changes: 4 additions & 0 deletions mono/mini/mini.c
Original file line number Diff line number Diff line change
Expand Up @@ -3247,6 +3247,7 @@ mono_patch_info_hash (gconstpointer data)
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GOT_OFFSET:
return (ji->type << 8);
Expand Down Expand Up @@ -3663,6 +3664,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
case MONO_PATCH_INFO_MONITOR_ENTER:
target = mono_create_monitor_enter_trampoline ();
break;
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
target = mono_create_monitor_enter_v4_trampoline ();
break;
case MONO_PATCH_INFO_MONITOR_EXIT:
target = mono_create_monitor_exit_trampoline ();
break;
Expand Down
7 changes: 6 additions & 1 deletion mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,7 @@ typedef enum {
MONO_TRAMPOLINE_RESTORE_STACK_PROT,
MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
MONO_TRAMPOLINE_MONITOR_ENTER,
MONO_TRAMPOLINE_MONITOR_ENTER_V4,
MONO_TRAMPOLINE_MONITOR_EXIT,
MONO_TRAMPOLINE_VCALL,
MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD,
Expand All @@ -1258,12 +1259,14 @@ typedef enum {
(t) == MONO_TRAMPOLINE_RESTORE_STACK_PROT || \
(t) == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 || \
(t) == MONO_TRAMPOLINE_MONITOR_EXIT)

/* These trampolines receive an argument directly in a register */
#define MONO_TRAMPOLINE_TYPE_HAS_ARG(t) \
((t) == MONO_TRAMPOLINE_GENERIC_CLASS_INIT || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER || \
(t) == MONO_TRAMPOLINE_MONITOR_ENTER_V4 || \
(t) == MONO_TRAMPOLINE_MONITOR_EXIT || \
(t) == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)

Expand Down Expand Up @@ -2214,6 +2217,7 @@ MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoDomain *domain,
gpointer mono_create_delegate_virtual_trampoline (MonoDomain *domain, MonoClass *klass, MonoMethod *method) MONO_INTERNAL;
gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset) MONO_INTERNAL;
gpointer mono_create_monitor_enter_trampoline (void) MONO_INTERNAL;
gpointer mono_create_monitor_enter_v4_trampoline (void) MONO_INTERNAL;
gpointer mono_create_monitor_exit_trampoline (void) MONO_INTERNAL;
gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) MONO_INTERNAL;
gpointer mono_create_llvm_imt_trampoline (MonoDomain *domain, MonoMethod *m, int vt_offset) MONO_LLVM_INTERNAL;
Expand All @@ -2231,6 +2235,7 @@ gpointer mono_aot_plt_trampoline (mgreg_t *regs, guint8 *code, guint8 *
void mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp) MONO_INTERNAL;
void mono_generic_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, guint8 *tramp) MONO_INTERNAL;
void mono_monitor_enter_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
void mono_monitor_enter_v4_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
void mono_monitor_exit_trampoline (mgreg_t *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
gconstpointer mono_get_trampoline_func (MonoTrampolineType tramp_type);
gpointer mini_get_vtable_trampoline (int slot_index) MONO_INTERNAL;
Expand Down Expand Up @@ -2310,7 +2315,7 @@ gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampI
gpointer mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info) MONO_INTERNAL;
gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
guint8 *mono_arch_create_llvm_native_thunk (MonoDomain *domain, guint8* addr) MONO_LLVM_INTERNAL;
GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MONO_INTERNAL;
Expand Down
1 change: 1 addition & 0 deletions mono/mini/patch-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ PATCH_INFO(METHOD_RGCTX, "method_rgctx")
PATCH_INFO(RGCTX_FETCH, "rgctx_fetch")
PATCH_INFO(GENERIC_CLASS_INIT, "generic_class_init")
PATCH_INFO(MONITOR_ENTER, "monitor_enter")
PATCH_INFO(MONITOR_ENTER_V4, "monitor_enter_v4")
PATCH_INFO(MONITOR_EXIT, "monitor_exit")
PATCH_INFO(MSCORLIB_GOT_ADDR, "mscorlib_got_addr")
PATCH_INFO(SEQ_POINT_INFO, "seq_point_info")
Expand Down
7 changes: 5 additions & 2 deletions mono/mini/tramp-amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ mono_arch_create_generic_class_init_trampoline (MonoTrampInfo **info, gboolean a
#ifdef MONO_ARCH_MONITOR_OBJECT_REG

gpointer
mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
{
guint8 *tramp;
guint8 *code, *buf;
Expand All @@ -974,6 +974,9 @@ mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
int status_reg = AMD64_RAX;

g_assert (MONO_ARCH_MONITOR_OBJECT_REG == obj_reg);
#ifndef MONO_ARCH_MONITOR_LOCK_TAKEN_REG
g_assert (!is_v4);
#endif

mono_monitor_threads_sync_members_offset (&status_offset, &nest_offset);
g_assert (MONO_THREADS_SYNC_MEMBER_SIZE (status_offset) == sizeof (guint32));
Expand Down Expand Up @@ -1223,7 +1226,7 @@ mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot)
#else

gpointer
mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean aot)
mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot)
{
g_assert_not_reached ();
return NULL;
Expand Down
Loading

0 comments on commit 5b0fbd4

Please sign in to comment.