[mono/mono] [2 commits] 0701d9d0: [amd64] Instead of saving callee saved registers in the LMF in trampoline frames, save a pointer to the register array inside the trampoline frame.

"Zoltan Varga ([email protected])" <[email protected]> Tue, 19 Nov 2013 16:17:22 +0000
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <000001427126df99-b4a801ee-41ed-4b75-979a-db2fad62ef78-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/90e5ec63d5d2...54d1751b24bf

   Commit: 0701d9d07fddcd0c78978a6cb03b6707942e7e67
   Author: Zoltan Varga <[email protected]> (vargaz)
     Date: 2013-11-19 16:14:42 GMT
      URL: https://github.com/mono/mono/commit/0701d9d07fddcd0c78978a6cb03b6707942e7e67

[amd64] Instead of saving callee saved registers in the LMF in trampoline frames, save a pointer to the register array inside the trampoline frame.

Changed paths:
  M mono/mini/exceptions-amd64.c
  M mono/mini/mini-amd64.h
  M mono/mini/tramp-amd64.c

Modified: mono/mini/exceptions-amd64.c
===================================================================
@@ -664,7 +664,7 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
 
 		if (*lmf && ((*lmf) != jit_tls->first_lmf) && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp)) {
 			/* remove any unused lmf */
-			*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+			*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
 		}
 
 #ifndef MONO_AMD64_NO_PUSHES
@@ -688,7 +688,7 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
 
 			memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
 
-			*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+			*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
 
 			frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
 
@@ -729,17 +729,36 @@ void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
 		new_ctx->rbp = (*lmf)->rbp;
 		new_ctx->rsp = (*lmf)->rsp;
 
-		new_ctx->rbx = (*lmf)->rbx;
-		new_ctx->r12 = (*lmf)->r12;
-		new_ctx->r13 = (*lmf)->r13;
-		new_ctx->r14 = (*lmf)->r14;
-		new_ctx->r15 = (*lmf)->r15;
+		if (((guint64)(*lmf)->previous_lmf) & 4) {
+			MonoLMFTramp *ext = (MonoLMFTramp*)(*lmf);
+
+			/* Trampoline frame */
+			new_ctx->rbx = ext->regs [AMD64_RBX];
+			new_ctx->r12 = ext->regs [AMD64_R12];
+			new_ctx->r13 = ext->regs [AMD64_R13];
+			new_ctx->r14 = ext->regs [AMD64_R14];
+			new_ctx->r15 = ext->regs [AMD64_R15];
+#ifdef TARGET_WIN32
+			new_ctx->rdi = ext->regs [AMD64_RDI];
+			new_ctx->rsi = ext->regs [AMD64_RSI];
+#endif
+		} else {
+			/*
+			 * The registers saved in the LMF will be restored using the normal unwind info,
+			 * when the wrapper frame is processed.
+			 */
+			new_ctx->rbx = 0;
+			new_ctx->r12 = 0;
+			new_ctx->r13 = 0;
+			new_ctx->r14 = 0;
+			new_ctx->r15 = 0;
 #ifdef TARGET_WIN32
-		new_ctx->rdi = (*lmf)->rdi;
-		new_ctx->rsi = (*lmf)->rsi;
+			new_ctx->rdi = 0;
+			new_ctx->rsi = 0;
 #endif
+		}
 
-		*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+		*lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
 
 		return TRUE;
 	}

Modified: mono/mini/mini-amd64.h
===================================================================
@@ -159,11 +159,12 @@ struct sigcontext {
 
 struct MonoLMF {
 	/* 
-	 * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise,
+	 * If the lowest bit is set, then this LMF has the rip field set. Otherwise,
 	 * the rip field is not set, and the rsp field points to the stack location where
 	 * the caller ip is saved.
-	 * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
+	 * If the second lowest bit is set, then this is a MonoLMFExt structure, and
 	 * the other fields are not valid.
+	 * If the third lowest bit is set, then this is a MonoLMFTramp structure.
 	 */
 	gpointer    previous_lmf;
 	gpointer    lmf_addr;
@@ -187,6 +188,12 @@ struct MonoLMF {
 #endif
 };
 
+/* LMF structure used by the JIT trampolines */
+typedef struct {
+	struct MonoLMF lmf;
+	guint64 *regs;
+} MonoLMFTramp;
+
 typedef struct MonoCompileArch {
 	gint32 localloc_offset;
 	gint32 reg_save_area_offset;

Modified: mono/mini/tramp-amd64.c
===================================================================
@@ -428,7 +428,7 @@
 
 	code = buf = mono_global_codeman_reserve (kMaxCodeSize);
 
-	framesize = kMaxCodeSize + sizeof (MonoLMF);
+	framesize = kMaxCodeSize + sizeof (MonoLMFTramp);
 	framesize = (framesize + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
 
 	orig_rsp_to_rbp_offset = 0;
@@ -583,7 +583,7 @@
 
 	/* Save LMF begin */
 
-	offset += sizeof (MonoLMF);
+	offset += sizeof (MonoLMFTramp);
 	lmf_offset = - offset;
 
 	/* Save ip */
@@ -599,16 +599,9 @@
 	amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
 	amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
 	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
-	/* Save callee saved regs */
-#ifdef TARGET_WIN32
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rdi), AMD64_RDI, sizeof(mgreg_t));
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsi), AMD64_RSI, sizeof(mgreg_t));
-#endif
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rbx), AMD64_RBX, sizeof(mgreg_t));
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r12), AMD64_R12, sizeof(mgreg_t));
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r13), AMD64_R13, sizeof(mgreg_t));
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r14), AMD64_R14, sizeof(mgreg_t));
-	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r15), AMD64_R15, sizeof(mgreg_t));
+	/* Save pointer to registers */
+	amd64_lea_membase (code, AMD64_R11, AMD64_RBP, saved_regs_offset);
+	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMFTramp, regs), AMD64_R11, sizeof(mgreg_t));
 
 	if (aot) {
 		code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
@@ -620,9 +613,10 @@
 	/* Save lmf_addr */
 	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), AMD64_RAX, sizeof(gpointer));
 	/* Save previous_lmf */
-	/* Set the lowest bit to 1 to signal that this LMF has the ip field set */
+	/* Set the lowest bit to signal that this LMF has the ip field set */
+	/* Set the third lowest bit to signal that this is a MonoLMFTramp structure */
 	amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
-	amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 1, sizeof(gpointer));
+	amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 0x5, sizeof(gpointer));
 	amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
 	/* Set new lmf */
 	amd64_lea_membase (code, AMD64_R11, AMD64_RBP, lmf_offset);
@@ -670,9 +664,8 @@
 	amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, res_offset, sizeof(mgreg_t));	
 
 	/* Restore LMF */
-
 	amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
-	amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 1, sizeof(gpointer));
+	amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 0x5, sizeof(gpointer));
 	amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sizeof(gpointer));
 	amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
 

   Commit: 54d1751b24bfa99fbdba3744c6c06d2484898a3c
   Author: Zoltan Varga <[email protected]> (vargaz)
     Date: 2013-11-19 16:14:42 GMT
      URL: https://github.com/mono/mono/commit/54d1751b24bfa99fbdba3744c6c06d2484898a3c

[sdb] Move the setup of the sdb invoke LMF structure to an arch-specific function mono_arch_init_lmf_ext ().

Changed paths:
  M mono/mini/debugger-agent.c
  M mono/mini/mini-amd64.c
  M mono/mini/mini-arm.c
  M mono/mini/mini-mips.c
  M mono/mini/mini-ppc.c
  M mono/mini/mini-s390x.c
  M mono/mini/mini-x86.c
  M mono/mini/mini.h

Modified: mono/mini/debugger-agent.c
===================================================================
@@ -6313,39 +6313,7 @@ static void CALLBACK notify_thread_apc (ULONG_PTR param)
 
 		/* Setup our lmf */
 		memset (&ext, 0, sizeof (ext));
-#ifdef TARGET_AMD64
-		ext.lmf.previous_lmf = *(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.rsp = (gssize)&ext;
-#elif defined(TARGET_X86)
-		ext.lmf.previous_lmf = (gsize)*(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_ARM)
-		ext.lmf.previous_lmf = *(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.sp = (gssize)&ext;
-#elif defined(TARGET_POWERPC)
-		ext.lmf.previous_lmf = *(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_S390X)
-		ext.lmf.previous_lmf = *(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_MIPS)
-		ext.lmf.previous_lmf = *(lmf_addr);
-		/* Mark that this is a MonoLMFExt */
-		ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
-		ext.lmf.iregs [mips_sp] = (gssize)&ext;
-#else
-		g_assert_not_reached ();
-#endif
+		mono_arch_init_lmf_ext (&ext, *lmf_addr);
 
 		ext.debugger_invoke = TRUE;
 		memcpy (&ext.ctx, &invoke->ctx, sizeof (MonoContext));

Modified: mono/mini/mini-amd64.c
===================================================================
@@ -8743,4 +8743,13 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
 	return info;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.rsp = (gssize)ext;
+}
+
 #endif

Modified: mono/mini/mini-arm.c
===================================================================
@@ -6573,6 +6573,15 @@ enum {
 	return info;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.sp = (gssize)ext;
+}
+
 /*
  * mono_arch_set_target:
  *

Modified: mono/mini/mini-mips.c
===================================================================
@@ -6151,4 +6151,13 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
 	return NULL;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.iregs [mips_sp] = (gssize)ext;
+}
+
 #endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */

Modified: mono/mini/mini-ppc.c
===================================================================
@@ -5956,4 +5956,13 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
 	return NULL;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.ebp = (gssize)ext;
+}
+
 #endif

Modified: mono/mini/mini-s390x.c
===================================================================
@@ -6384,6 +6384,23 @@ gboolean is_unsigned (MonoInst *next)
 	return NULL;
 }
 
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- mono_arch_init_lmf_ext.                               */
+/*                                                                  */
+/* Function -                                                       */
+/*                                                                  */
+/*------------------------------------------------------------------*/
+
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.ebp = (gssize)ext;
+}
+
 /*========================= End of Function ========================*/
 
 #endif

Modified: mono/mini/mini-x86.c
===================================================================
@@ -6807,6 +6807,15 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
 	return NULL;
 }
 
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+	ext->lmf.previous_lmf = (gsize)prev_lmf;
+	/* Mark that this is a MonoLMFExt */
+	ext->lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+	ext->lmf.ebp = (gssize)ext;
+}
+
 #endif
 
 #if defined(MONOTOUCH) || defined(MONO_EXTENSIONS)

Modified: mono/mini/mini.h
===================================================================
@@ -2317,6 +2317,7 @@ int               mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoB
 void     mono_arch_skip_single_step             (MonoContext *ctx) MONO_INTERNAL;
 gpointer mono_arch_get_seq_point_info           (MonoDomain *domain, guint8 *code) MONO_INTERNAL;
 void     mono_arch_setup_resume_sighandler_ctx  (MonoContext *ctx, gpointer func) MONO_INTERNAL;
+void     mono_arch_init_lmf_ext                 (MonoLMFExt *ext, gpointer prev_lmf) MONO_INTERNAL;
 #endif
 
 #ifdef USE_JUMP_TABLES


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches