[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