Permalink
Browse files

Move the thread attach code for native-to-managed wrappers to method…

…_to_ir (), instead of emitting it by hand for each architecture. Also make it save/restore the current domain. Fixes #3623.
  • Loading branch information...
1 parent 8814ddb commit 5d8b1ad68d1afa7747b83c97b690d9f81a55c0e8 @vargaz vargaz committed Mar 11, 2012
@@ -309,4 +309,6 @@
<opcode name="mono_icall_addr" input="Pop0" output="PushI" args="InlineI" o1="0xF0" o2="0x0E" flow="next" />
<opcode name="mono_dyn_call" input="Pop0" output="PushI" args="InlineI" o1="0xF0" o2="0x0F" flow="next" />
<opcode name="mono_memory_barrier" input="Pop0" output="Push0" args="InlineI" o1="0xF0" o2="0x10" flow="next" />
+<opcode name="mono_jit_attach" input="Pop0" output="Push0" args="InlineNone" o1="0xF0" o2="0x11" flow="next" />
+<opcode name="mono_jit_detach" input="Pop0" output="Push0" args="InlineNone" o1="0xF0" o2="0x12" flow="next" />
</opdesc>
View
@@ -309,6 +309,8 @@ OPDEF(CEE_MONO_TLS, "mono_tls", Pop0, PushI, InlineI, X, 2, 0xF0, 0x0D, NEXT)
OPDEF(CEE_MONO_ICALL_ADDR, "mono_icall_addr", Pop0, PushI, InlineI, X, 2, 0xF0, 0x0E, NEXT)
OPDEF(CEE_MONO_DYN_CALL, "mono_dyn_call", Pop0, PushI, InlineI, X, 2, 0xF0, 0x0F, NEXT)
OPDEF(CEE_MONO_MEMORY_BARRIER, "mono_memory_barrier", Pop0, Push0, InlineI, X, 2, 0xF0, 0x10, NEXT)
+OPDEF(CEE_MONO_JIT_ATTACH, "mono_jit_attach", Pop0, Push0, InlineNone, X, 2, 0xF0, 0x11, NEXT)
+OPDEF(CEE_MONO_JIT_DETACH, "mono_jit_detach", Pop0, Push0, InlineNone, X, 2, 0xF0, 0x12, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
@@ -8614,6 +8614,13 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
mono_mb_emit_icon (mb, 0);
mono_mb_emit_stloc (mb, 2);
+ /*
+ * Might need to attach the thread to the JIT or change the
+ * domain for the callback.
+ */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_ATTACH);
+
/* we first do all conversions */
tmp_locals = alloca (sizeof (int) * sig->param_count);
for (i = 0; i < sig->param_count; i ++) {
@@ -8740,6 +8747,9 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
}
}
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
+
if (m->retobj_var) {
mono_mb_emit_ldloc (mb, m->retobj_var);
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
@@ -10097,6 +10097,60 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
ip += 5;
break;
}
+ case CEE_MONO_JIT_ATTACH: {
+ MonoInst *args [16];
+ MonoInst *ad_ins, *lmf_ins;
+ MonoBasicBlock *next_bb = NULL;
+
+ cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+
+ EMIT_NEW_PCONST (cfg, ins, NULL);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
+
+#if TARGET_WIN32
+ ad_ins = NULL;
+ lmf_ins = NULL;
+#else
+ ad_ins = mono_get_domain_intrinsic (cfg);
+ lmf_ins = mono_get_lmf_intrinsic (cfg);
+#endif
+
+ if (MONO_ARCH_HAVE_TLS_GET && ad_ins && lmf_ins) {
+ NEW_BBLOCK (cfg, next_bb);
+
+ MONO_ADD_INS (cfg->cbb, ad_ins);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, ad_ins->dreg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, next_bb);
+
+ MONO_ADD_INS (cfg->cbb, lmf_ins);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, lmf_ins->dreg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, next_bb);
+
+ if (cfg->compile_aot) {
+ /* AOT code is only used in the root domain */
+ EMIT_NEW_PCONST (cfg, args [0], NULL);
+ } else {
+ EMIT_NEW_PCONST (cfg, args [0], cfg->domain);
+ }
+ ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
+ }
+
+ if (next_bb)
+ MONO_START_BB (cfg, next_bb);
+ ip += 2;
+ break;
+ }
+ case CEE_MONO_JIT_DETACH: {
+ MonoInst *args [16];
+
+ /* Restore the original domain */
+ dreg = alloc_ireg (cfg);
+ EMIT_NEW_UNALU (cfg, args [0], OP_MOVE, dreg, cfg->orig_domain_var->dreg);
+ mono_emit_jit_icall (cfg, mono_jit_set_domain, args);
+ ip += 2;
+ break;
+ }
default:
g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
break;
@@ -7006,61 +7006,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
}
}
- /* Might need to attach the thread to the JIT or change the domain for the callback */
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- guint64 domain = (guint64)cfg->domain;
-
- args_clobbered = TRUE;
-
- /*
- * The call might clobber argument registers, but they are already
- * saved to the stack/global regs.
- */
- if (appdomain_tls_offset != -1 && lmf_tls_offset != -1) {
- guint8 *buf, *no_domain_branch;
-
- code = mono_amd64_emit_tls_get (code, AMD64_RAX, appdomain_tls_offset);
- if (cfg->compile_aot) {
- /* AOT code is only used in the root domain */
- amd64_mov_reg_imm (code, AMD64_ARG_REG1, 0);
- } else {
- if ((domain >> 32) == 0)
- amd64_mov_reg_imm_size (code, AMD64_ARG_REG1, domain, 4);
- else
- amd64_mov_reg_imm_size (code, AMD64_ARG_REG1, domain, 8);
- }
- amd64_alu_reg_reg (code, X86_CMP, AMD64_RAX, AMD64_ARG_REG1);
- no_domain_branch = code;
- x86_branch8 (code, X86_CC_NE, 0, 0);
- code = mono_amd64_emit_tls_get ( code, AMD64_RAX, lmf_addr_tls_offset);
- amd64_test_reg_reg (code, AMD64_RAX, AMD64_RAX);
- buf = code;
- x86_branch8 (code, X86_CC_NE, 0, 0);
- amd64_patch (no_domain_branch, code);
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_jit_thread_attach", TRUE);
- amd64_patch (buf, code);
-#ifdef HOST_WIN32
- /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
- /* FIXME: Add a separate key for LMF to avoid this */
- amd64_alu_reg_imm (code, X86_ADD, AMD64_RAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
-#endif
- } else {
- g_assert (!cfg->compile_aot);
- if (cfg->compile_aot) {
- /* AOT code is only used in the root domain */
- amd64_mov_reg_imm (code, AMD64_ARG_REG1, 0);
- } else {
- if ((domain >> 32) == 0)
- amd64_mov_reg_imm_size (code, AMD64_ARG_REG1, domain, 4);
- else
- amd64_mov_reg_imm_size (code, AMD64_ARG_REG1, domain, 8);
- }
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_jit_thread_attach", TRUE);
- }
- }
-
if (method->save_lmf) {
code = emit_save_lmf (cfg, code, lmf_var->inst_offset, &args_clobbered);
}
View
@@ -5309,17 +5309,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- if (cfg->compile_aot)
- /* AOT code is only used in the root domain */
- code = mono_arm_emit_load_imm (code, ARMREG_R0, 0);
- else
- code = mono_arm_emit_load_imm (code, ARMREG_R0, (guint32)cfg->domain);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_jit_thread_attach");
- code = emit_call_seq (cfg, code);
- }
-
if (method->save_lmf)
code = emit_save_lmf (cfg, code, alloc_size - lmf_offset);
@@ -5243,11 +5243,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- mips_load_const (code, mips_a0, cfg->domain);
- mips_call (code, mips_t9, (gpointer)mono_jit_thread_attach);
- }
-
if (method->save_lmf) {
mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
View
@@ -5069,22 +5069,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- if (cfg->compile_aot)
- /* AOT code is only used in the root domain */
- ppc_load_ptr (code, ppc_r3, 0);
- else
- ppc_load_ptr (code, ppc_r3, cfg->domain);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
- if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
- ppc_load_func (code, ppc_r0, 0);
- ppc_mtlr (code, ppc_r0);
- ppc_blrl (code);
- } else {
- ppc_bl (code, 0);
- }
- }
-
if (method->save_lmf) {
if (lmf_pthread_key != -1) {
emit_tls_access (code, ppc_r3, lmf_pthread_key);
@@ -5281,27 +5281,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
pos++;
}
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- if (cfg->compile_aot)
- /* AOT code is only used in the root domain */
- s390_lghi (code, s390_r2, 0);
- else {
- s390_basr(code, s390_r14, 0);
- s390_j (code, 6);
- s390_llong(code, cfg->domain);
- s390_lg (code, s390_r2, 0, s390_r14, 4);
- }
-
- s390_basr(code, s390_r14, 0);
- s390_j (code, 6);
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_jit_thread_attach");
- s390_llong(code, 0);
- s390_lg (code, s390_r1, 0, s390_r14, 4);
- s390_basr (code, s390_r14, s390_r1);
- }
-
if (method->save_lmf) {
/*---------------------------------------------------------------*/
/* build the MonoLMF structure on the stack - see mini-s390x.h */
View
@@ -5049,52 +5049,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
alloc_size = cfg->stack_offset;
pos = 0;
- if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
- /* Might need to attach the thread to the JIT or change the domain for the callback */
- if (appdomain_tls_offset != -1 && lmf_tls_offset != -1) {
- guint8 *buf, *no_domain_branch;
-
- code = mono_x86_emit_tls_get (code, X86_EAX, appdomain_tls_offset);
- x86_alu_reg_imm (code, X86_CMP, X86_EAX, GPOINTER_TO_UINT (cfg->domain));
- no_domain_branch = code;
- x86_branch8 (code, X86_CC_NE, 0, 0);
- code = mono_x86_emit_tls_get ( code, X86_EAX, lmf_tls_offset);
- x86_test_reg_reg (code, X86_EAX, X86_EAX);
- buf = code;
- x86_branch8 (code, X86_CC_NE, 0, 0);
- x86_patch (no_domain_branch, code);
-
- x86_alu_reg_imm (code, X86_SUB, X86_ESP, 4);
- x86_push_imm (code, cfg->domain);
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
- x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
- x86_patch (buf, code);
-#ifdef TARGET_WIN32
- /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
- /* FIXME: Add a separate key for LMF to avoid this */
- x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
-#endif
- }
- else {
- x86_alu_reg_imm (code, X86_SUB, X86_ESP, 4);
- if (cfg->compile_aot) {
- /*
- * This goes before the saving of callee saved regs, so save the got reg
- * ourselves.
- */
- x86_push_reg (code, MONO_ARCH_GOT_REG);
- code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
- x86_push_imm (code, 0);
- } else {
- x86_push_imm (code, cfg->domain);
- }
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach");
- x86_alu_reg_imm (code, X86_ADD, X86_ESP, 8);
- if (cfg->compile_aot)
- x86_pop_reg (code, MONO_ARCH_GOT_REG);
- }
- }
-
if (method->save_lmf) {
pos += sizeof (MonoLMF);
View
@@ -2574,10 +2574,17 @@ mono_set_lmf_addr (gpointer lmf_addr)
#endif
}
-/* Called by native->managed wrappers */
-void
+/*
+ * mono_jit_thread_attach:
+ *
+ * Called by native->managed wrappers. Returns the original domain which needs to be
+ * restored, or NULL.
+ */
+MonoDomain*
mono_jit_thread_attach (MonoDomain *domain)
{
+ MonoDomain *orig;
+
if (!domain)
/*
* Happens when called from AOTed code which is only used in the root
@@ -2597,10 +2604,21 @@ mono_jit_thread_attach (MonoDomain *domain)
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
}
#endif
- if (mono_domain_get () != domain)
- mono_domain_set (domain, TRUE);
+ orig = mono_domain_get ();
+ if (orig != domain)
+ mono_domain_set (domain, TRUE);
+
+ return orig != domain ? orig : NULL;
}
+/* Called by native->managed wrappers */
+void
+mono_jit_set_domain (MonoDomain *domain)
+{
+ if (domain)
+ mono_domain_set (domain, TRUE);
+}
+
/**
* mono_thread_abort:
* @obj: exception object
@@ -2784,6 +2802,12 @@ mono_get_thread_intrinsic (MonoCompile* cfg)
return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
}
+MonoInst*
+mono_get_lmf_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_get_lmf_tls_offset ());
+}
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
@@ -6491,7 +6515,8 @@ mini_init (const char *filename, const char *runtime_version)
register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
- register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "void", TRUE);
+ register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
+ register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
register_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
View
@@ -1257,6 +1257,9 @@ typedef struct {
MonoGenericSharingContext *generic_sharing_context;
+ /* For native-to-managed wrappers, the saved old domain */
+ MonoInst *orig_domain_var;
+
unsigned char *cil_start;
#ifdef __native_client_codegen__
/* this alloc is not aligned, native_code */
@@ -1823,14 +1826,16 @@ gpointer mono_jit_compile_method (MonoMethod *method) MONO_INTERNAL;
MonoLMF * mono_get_lmf (void) MONO_INTERNAL;
MonoLMF** mono_get_lmf_addr (void) MONO_INTERNAL;
void mono_set_lmf (MonoLMF *lmf) MONO_INTERNAL;
-void mono_jit_thread_attach (MonoDomain *domain);
+MonoDomain *mono_jit_thread_attach (MonoDomain *domain);
+void mono_jit_set_domain (MonoDomain *domain);
MonoNativeTlsKey mono_get_jit_tls_key (void) MONO_INTERNAL;
gint32 mono_get_jit_tls_offset (void) MONO_INTERNAL;
gint32 mono_get_lmf_tls_offset (void) MONO_INTERNAL;
gint32 mono_get_lmf_addr_tls_offset (void) MONO_INTERNAL;
MonoInst* mono_get_jit_tls_intrinsic (MonoCompile *cfg) MONO_INTERNAL;
MonoInst* mono_get_domain_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
MonoInst* mono_get_thread_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
+MonoInst* mono_get_lmf_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
GList *mono_varlist_insert_sorted (MonoCompile *cfg, GList *list, MonoMethodVar *mv, int sort_type) MONO_INTERNAL;
GList *mono_varlist_sort (MonoCompile *cfg, GList *list, int sort_type) MONO_INTERNAL;
void mono_analyze_liveness (MonoCompile *cfg) MONO_INTERNAL;
Oops, something went wrong. Retry.

0 comments on commit 5d8b1ad

Please sign in to comment.