[mono/mono] c574de06: [jit] Add support for generating the push/pop the LMF from the LMF stack as IR instead of hand-written assembly code in the backends. Not yet used.
"Zoltan Varga (
[email protected])" <
[email protected]>
Sun, 3 Nov 2013 13:40:27 +0000
| Newsgroups |
gmane.comp.gnome.mono.patches |
| Message-ID |
<000001421e317779-bb4e5103-ce5c-4695-85ce-de861457a207-000000@email.amazonses.com> |
Branch: refs/heads/master
Home: https://github.com/mono/mono
Compare: https://github.com/mono/mono/compare/abc18e4340c8...c574de067d18
Commit: c574de067d185cb7b8cdd5afecc2c66871cd9f94
Author: Zoltan Varga <[email protected]> (vargaz)
Date: 2013-11-03 13:38:44 GMT
URL: https://github.com/mono/mono/commit/c574de067d185cb7b8cdd5afecc2c66871cd9f94
[jit] Add support for generating the push/pop the LMF from the LMF stack as IR instead of hand-written assembly code in the backends. Not yet used.
Changed paths:
M mono/mini/method-to-ir.c
M mono/mini/mini-ops.h
M mono/mini/mini.c
M mono/mini/mini.h
Modified: mono/mini/method-to-ir.c
===================================================================
@@ -1868,6 +1868,118 @@
}
}
+static void
+emit_tls_set (MonoCompile *cfg, int sreg1, int tls_key)
+{
+ MonoInst *ins, *c;
+
+ if (cfg->compile_aot) {
+ EMIT_NEW_TLS_OFFSETCONST (cfg, c, tls_key);
+ MONO_INST_NEW (cfg, ins, OP_TLS_SET_REG);
+ ins->sreg1 = sreg1;
+ ins->sreg2 = c->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ MONO_INST_NEW (cfg, ins, OP_TLS_SET);
+ ins->sreg1 = sreg1;
+ ins->inst_offset = mini_get_tls_offset (tls_key);
+ MONO_ADD_INS (cfg->cbb, ins);
+ }
+}
+
+/*
+ * emit_push_lmf:
+ *
+ * Emit IR to push the current LMF onto the LMF stack.
+ */
+static void
+emit_push_lmf (MonoCompile *cfg)
+{
+ /*
+ * Emit IR to push the LMF:
+ * lmf_addr = <lmf_addr from tls>
+ * lmf->lmf_addr = lmf_addr
+ * lmf->prev_lmf = *lmf_addr
+ * *lmf_addr = lmf
+ */
+ int lmf_reg, lmf_addr_reg, prev_lmf_reg;
+ MonoInst *ins, *lmf_ins;
+
+ if (!cfg->lmf_ir)
+ return;
+
+ if (cfg->lmf_ir_mono_lmf) {
+ /* Load current lmf */
+ lmf_ins = mono_get_lmf_intrinsic (cfg);
+ g_assert (lmf_ins);
+ MONO_ADD_INS (cfg->cbb, lmf_ins);
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+ /* Save previous_lmf */
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
+ /* Set new LMF */
+ emit_tls_set (cfg, lmf_reg, OP_TLS_SET_REG);
+ } else {
+ lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
+ if (lmf_ins)
+ MONO_ADD_INS (cfg->cbb, lmf_ins);
+ else
+ lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
+ lmf_addr_reg = lmf_ins->dreg;
+
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+ /* Save lmf_addr */
+ if (!cfg->lmf_addr_var)
+ cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, cfg->lmf_addr_var->dreg, lmf_ins->dreg);
+ prev_lmf_reg = alloc_preg (cfg);
+ /* Save previous_lmf */
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_addr_reg, 0);
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg);
+ /* Set new lmf */
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, lmf_reg);
+ }
+}
+
+/*
+ * emit_pop_lmf:
+ *
+ * Emit IR to pop the current LMF from the LMF stack.
+ */
+static void
+emit_pop_lmf (MonoCompile *cfg)
+{
+ int lmf_reg, lmf_addr_reg, prev_lmf_reg;
+ MonoInst *ins;
+
+ if (!cfg->lmf_ir)
+ return;
+
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+
+ if (cfg->lmf_ir_mono_lmf) {
+ /* Load previous_lmf */
+ prev_lmf_reg = alloc_preg (cfg);
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ /* Set new LMF */
+ emit_tls_set (cfg, prev_lmf_reg, OP_TLS_SET_REG);
+ } else {
+ /*
+ * Emit IR to pop the LMF:
+ * *(lmf->lmf_addr) = lmf->prev_lmf
+ */
+ /* This could be called before emit_push_lmf () */
+ if (!cfg->lmf_addr_var)
+ cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ lmf_addr_reg = cfg->lmf_addr_var->dreg;
+ prev_lmf_reg = alloc_preg (cfg);
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
+ }
+}
+
static int
ret_type_to_call_opcode (MonoType *type, int calli, int virt, MonoGenericSharingContext *gsctx)
{
@@ -8374,6 +8486,9 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
cfg->ret_var_set = TRUE;
}
} else {
+ if (cfg->lmf_var && cfg->cbb->in_count)
+ emit_pop_lmf (cfg);
+
if (cfg->ret) {
MonoType *ret_type = mono_method_signature (method)->ret;
@@ -11761,6 +11876,11 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal
bblock->next_bb = end_bblock;
}
+ if (cfg->lmf_var) {
+ cfg->cbb = init_localsbb;
+ emit_push_lmf (cfg);
+ }
+
if (cfg->method == method && cfg->domainvar) {
MonoInst *store;
MonoInst *get_domain;
Modified: mono/mini/mini-ops.h
===================================================================
@@ -608,7 +608,10 @@
/* arch-dep tls access */
MINI_OP(OP_TLS_GET, "tls_get", IREG, NONE, NONE)
-MINI_OP(OP_TLS_GET_REG, "tls_get_reg", IREG, IREG, NONE)
+MINI_OP(OP_TLS_GET_REG, "tls_get_reg", IREG, IREG, NONE)
+/* inst_offset contains the TLS offset */
+MINI_OP(OP_TLS_SET, "tls_set", NONE, IREG, NONE)
+MINI_OP(OP_TLS_SET_REG, "tls_set_reg", NONE, IREG, IREG)
MINI_OP(OP_LOAD_GOTADDR, "load_gotaddr", IREG, NONE, NONE)
MINI_OP(OP_DUMMY_USE, "dummy_use", NONE, IREG, NONE)
Modified: mono/mini/mini.c
===================================================================
@@ -3012,6 +3012,12 @@ void *mono_global_codeman_reserve (int size)
return mono_create_tls_get (cfg, TLS_KEY_LMF);
}
+MonoInst*
+mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
+}
+
#endif /* !DISABLE_JIT */
void
@@ -3707,6 +3713,13 @@ void *mono_global_codeman_reserve (int size)
g_print ("locals done\n");
mono_arch_create_vars (cfg);
+
+ if (cfg->method->save_lmf && cfg->create_lmf_var) {
+ MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ lmf_var->flags |= MONO_INST_VOLATILE;
+ lmf_var->flags |= MONO_INST_LMF;
+ cfg->lmf_var = lmf_var;
+ }
}
void
Modified: mono/mini/mini.h
===================================================================
@@ -1396,6 +1396,9 @@ enum {
/* For native-to-managed wrappers, the saved old domain */
MonoInst *orig_domain_var;
+ MonoInst *lmf_var;
+ MonoInst *lmf_addr_var;
+
unsigned char *cil_start;
#ifdef __native_client_codegen__
/* this alloc is not aligned, native_code */
@@ -1441,6 +1444,17 @@ enum {
guint disable_vreg_to_lvreg : 1;
guint disable_deadce_vars : 1;
guint disable_out_of_line_bblocks : 1;
+ guint create_lmf_var : 1;
+ /*
+ * When this is set, the code to push/pop the LMF from the LMF stack is generated as IR
+ * instead of being generated in emit_prolog ()/emit_epilog ().
+ */
+ guint lmf_ir : 1;
+ /*
+ * Whenever to use the mono_lmf TLS variable instead of indirection through the
+ * mono_lmf_addr TLS variable.
+ */
+ guint lmf_ir_mono_lmf : 1;
guint gen_write_barriers : 1;
guint init_ref_vars : 1;
guint extend_live_ranges : 1;
@@ -1988,6 +2002,7 @@ enum {
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;
+MonoInst* mono_get_lmf_addr_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;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches