Browse Source

s390x: Trampoline fixes and implement mono_arch_patch_code_new (#20852)

- Fixes some lack of casting warnings
- Fix formatting
- Sometimes a trampoline may be more than 4GB away from its target. We need to detect this and use a load/branch rather than a jump relative
- Implement `mono_arch_patch_code_new` in lieu of `mono_arch_patch_code`
Neale Ferguson 4 years ago
parent
commit
c868a253f4
3 changed files with 101 additions and 87 deletions
  1. 69 71
      mono/mini/mini-s390x.c
  2. 1 0
      mono/mini/mini-s390x.h
  3. 31 16
      mono/mini/tramp-s390x.c

+ 69 - 71
mono/mini/mini-s390x.c

@@ -1051,9 +1051,9 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
 	size_data *sz;
 	size_data *sz;
 
 
 	if (mp)
 	if (mp)
-		cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
+		cinfo = (CallInfo *) mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
 	else
 	else
-		cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
+		cinfo = (CallInfo *) g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
 
 
 	fr                = 0;
 	fr                = 0;
 	gr                = s390_r2;
 	gr                = s390_r2;
@@ -3485,7 +3485,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 			s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
 			s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
 			}
 			}
 			break;
 			break;
-        case OP_TLS_SET: {
+        	case OP_TLS_SET: {
 			if (s390_is_imm16 (ins->inst_offset)) {
 			if (s390_is_imm16 (ins->inst_offset)) {
 				s390_lghi (code, s390_r13, ins->inst_offset);
 				s390_lghi (code, s390_r13, ins->inst_offset);
 			} else if (s390_is_imm32 (ins->inst_offset)) {
 			} else if (s390_is_imm32 (ins->inst_offset)) {
@@ -3565,7 +3565,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 					mono_add_patch_info (cfg, code - cfg->native_code, 
 					mono_add_patch_info (cfg, code - cfg->native_code, 
 						 MONO_PATCH_INFO_METHOD_JUMP, 
 						 MONO_PATCH_INFO_METHOD_JUMP, 
 						 call->method);
 						 call->method);
-					s390_jcl (code, S390_CC_UN, 0);
+					S390_BR_TEMPLATE (code, s390_r1);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -5350,67 +5350,65 @@ mono_arch_register_lowlevel_calls (void)
  */
  */
 
 
 void
 void
-mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, 
-		      guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
-		      MonoError *error)
+mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, 
+		          guint8 *code, MonoJumpInfo *ji, gpointer target)
 {
 {
-	MonoJumpInfo *patch_info;
-
-	error_init (error);
-
-	for (patch_info = ji; patch_info; patch_info = patch_info->next) {
-		unsigned char *ip = patch_info->ip.i + code;
-		gconstpointer target = NULL;
-
-		target = mono_resolve_patch_target (method, domain, code, 
-						    patch_info, run_cctors, error);
-		return_if_nok (error);
-
-		switch (patch_info->type) {
-			case MONO_PATCH_INFO_IP:
-			case MONO_PATCH_INFO_LDSTR:
-			case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
-			case MONO_PATCH_INFO_LDTOKEN: 
-			case MONO_PATCH_INFO_EXC:
-				s390_patch_addr (ip, (guint64) target);
-				continue;
-			case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR:
-			case MONO_PATCH_INFO_METHOD:
-			case MONO_PATCH_INFO_JIT_ICALL_ID:
-			case MONO_PATCH_INFO_JIT_ICALL_ADDR:
-			case MONO_PATCH_INFO_RGCTX_FETCH:
-			case MONO_PATCH_INFO_ABS: {
-				S390_EMIT_CALL (ip, target);
-				continue;
-			}
-			case MONO_PATCH_INFO_SWITCH: 
-				/*----------------------------------*/
-				/* ip points at the basr r13,0/j +4 */
-				/* instruction the vtable value     */
-				/* follows this (i.e. ip+6)	    */
-				/*----------------------------------*/
-				S390_EMIT_LOAD (ip, target);
-				continue;
-			case MONO_PATCH_INFO_METHODCONST:
-			case MONO_PATCH_INFO_CLASS:
-			case MONO_PATCH_INFO_IMAGE:
-			case MONO_PATCH_INFO_FIELD:
-			case MONO_PATCH_INFO_IID:
-			case MONO_PATCH_INFO_EXC_NAME:
-				target = S390_RELATIVE(target, ip);
-				s390_patch_rel (ip, (guint64) target);
-				continue;
-			case MONO_PATCH_INFO_R4:
-			case MONO_PATCH_INFO_R8:
-				g_assert_not_reached ();
-				continue;
-			default:
-				target = S390_RELATIVE(target, ip);
-				ip += 2;
-				s390_patch_rel (ip, (guint64) target);
-			case MONO_PATCH_INFO_NONE:
-				break;
+	unsigned char *ip = ji->ip.i + code;
+	uintptr_t displace;
+
+	switch (ji->type) {
+	case MONO_PATCH_INFO_IP:
+	case MONO_PATCH_INFO_LDSTR:
+	case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
+	case MONO_PATCH_INFO_LDTOKEN: 
+	case MONO_PATCH_INFO_EXC:
+		s390_patch_addr (ip, (guint64) target);
+		break;
+	case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR:
+	case MONO_PATCH_INFO_METHOD:
+	case MONO_PATCH_INFO_JIT_ICALL_ID:
+	case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+	case MONO_PATCH_INFO_RGCTX_FETCH:
+	case MONO_PATCH_INFO_ABS: {
+		S390_EMIT_CALL (ip, target);
+		break;
+	}
+	case MONO_PATCH_INFO_SWITCH: 
+		/*----------------------------------*/
+		/* ip points at the basr r13,0/j +4 */
+		/* instruction the vtable value     */
+		/* follows this (i.e. ip+6)	    */
+		/*----------------------------------*/
+		S390_EMIT_LOAD (ip, target);
+		break;
+	case MONO_PATCH_INFO_METHODCONST:
+	case MONO_PATCH_INFO_CLASS:
+	case MONO_PATCH_INFO_IMAGE:
+	case MONO_PATCH_INFO_FIELD:
+	case MONO_PATCH_INFO_IID:
+	case MONO_PATCH_INFO_EXC_NAME:
+		target = S390_RELATIVE(target, ip);
+		s390_patch_rel (ip, (guint64) target);
+		break;
+	case MONO_PATCH_INFO_R4:
+	case MONO_PATCH_INFO_R8:
+		g_assert_not_reached ();
+		break;
+	case MONO_PATCH_INFO_METHOD_JUMP:
+		displace = (uintptr_t) S390_RELATIVE(target, ip);
+		if ((displace >= INT_MIN) && (displace <= INT_MAX)) 
+			s390_jg (ip, (gint32) displace);
+		else {
+			S390_SET (ip, s390_r1, target);
+			s390_br  (ip, s390_r1);
 		}
 		}
+		break;
+	case MONO_PATCH_INFO_NONE:
+		break;
+	default:
+		target = S390_RELATIVE(target, ip);
+		ip += 2;
+		s390_patch_rel (ip, (guint64) target);
 	}
 	}
 }
 }
 
 
@@ -5450,7 +5448,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	if (method->save_lmf)
 	if (method->save_lmf)
 		cfg->code_size += 200;
 		cfg->code_size += 200;
 
 
-	cfg->native_code = code = g_malloc (cfg->code_size);
+	cfg->native_code = code = (guint8 *) g_malloc (cfg->code_size);
 
 
 	/**
 	/**
 	 * Create unwind information
 	 * Create unwind information
@@ -6247,7 +6245,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, MonoMethodS
 	if (has_target) {
 	if (has_target) {
 		int size = 32;
 		int size = 32;
 
 
-		start = code = mono_global_codeman_reserve (size);
+		start = code = (guint8 *) mono_global_codeman_reserve (size);
 
 
 		/* Replace the this argument with the target */
 		/* Replace the this argument with the target */
 		s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
 		s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
@@ -6262,7 +6260,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, MonoMethodS
 		CallInfo *cinfo = get_call_info (NULL, sig);
 		CallInfo *cinfo = get_call_info (NULL, sig);
 
 
 		size = 32 + sig->param_count * 8;
 		size = 32 + sig->param_count * 8;
-		start = code = mono_global_codeman_reserve (size);
+		start = code = (guint8 *) mono_global_codeman_reserve (size);
 
 
 		s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
 		s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
 		/* slide down the arguments */
 		/* slide down the arguments */
@@ -6364,7 +6362,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 			return cached;
 			return cached;
 
 
 		if (mono_ee_features.use_aot_trampolines) {
 		if (mono_ee_features.use_aot_trampolines) {
-			start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
+			start = (guint8 *) mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
 		} else {
 		} else {
 			MonoTrampInfo *info;
 			MonoTrampInfo *info;
 			start = get_delegate_invoke_impl (&info, TRUE, sig, FALSE);
 			start = get_delegate_invoke_impl (&info, TRUE, sig, FALSE);
@@ -6390,7 +6388,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 
 
 		if (mono_ee_features.use_aot_trampolines) {
 		if (mono_ee_features.use_aot_trampolines) {
 			char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
 			char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
-			start = mono_aot_get_trampoline (name);
+			start = (guint8 *) mono_aot_get_trampoline (name);
 			g_free (name);
 			g_free (name);
 		} else {
 		} else {
 			MonoTrampInfo *info;
 			MonoTrampInfo *info;
@@ -6427,7 +6425,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod
 	guint8 *code, *start;
 	guint8 *code, *start;
 	int size = 40;
 	int size = 40;
 
 
-	start = code = mono_global_codeman_reserve (size);
+	start = code = (guint8 *) mono_global_codeman_reserve (size);
 
 
 	/*
 	/*
 	 * Replace the "this" argument with the target
 	 * Replace the "this" argument with the target
@@ -6516,10 +6514,10 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
 	}
 	}
 
 
 	if (fail_tramp) {
 	if (fail_tramp) {
-		code = mono_method_alloc_generic_virtual_trampoline (mono_domain_ambient_memory_manager (domain), size);
+		code = (guint8 *) mono_method_alloc_generic_virtual_trampoline (mono_domain_ambient_memory_manager (domain), size);
 	} else {
 	} else {
 		MonoMemoryManager *mem_manager = m_class_get_mem_manager (domain, vtable->klass);
 		MonoMemoryManager *mem_manager = m_class_get_mem_manager (domain, vtable->klass);
-		code = mono_mem_manager_code_reserve (mem_manager, size);
+		code = (guint8 *) mono_mem_manager_code_reserve (mem_manager, size);
 	}
 	}
 
 
 	start = code;
 	start = code;

+ 1 - 0
mono/mini/mini-s390x.h

@@ -81,6 +81,7 @@ struct SeqPointInfo {
 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES			1
 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES			1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX	1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX	1
 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 		1
 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 		1
+#define MONO_ARCH_HAVE_PATCH_CODE_NEW 			1
 
 
 #define S390_STACK_ALIGNMENT		 8
 #define S390_STACK_ALIGNMENT		 8
 #define S390_FIRST_ARG_REG 		s390_r2
 #define S390_FIRST_ARG_REG 		s390_r2

+ 31 - 16
mono/mini/tramp-s390x.c

@@ -106,7 +106,7 @@ mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr)
 	MonoMemoryManager *mem_manager = m_method_get_mem_manager (domain, m);
 	MonoMemoryManager *mem_manager = m_method_get_mem_manager (domain, m);
 	char trampName[128];
 	char trampName[128];
 
 
-	start = code = mono_mem_manager_code_reserve (mem_manager, 28);
+	start = code = (guint8 *) mono_mem_manager_code_reserve (mem_manager, 28);
 
 
 	S390_SET  (code, s390_r1, addr);
 	S390_SET  (code, s390_r1, addr);
 	s390_aghi (code, this_pos, MONO_ABI_SIZEOF (MonoObject));
 	s390_aghi (code, this_pos, MONO_ABI_SIZEOF (MonoObject));
@@ -317,7 +317,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 	/* Now we'll create in 'buf' the S/390 trampoline code. This
 	/* Now we'll create in 'buf' the S/390 trampoline code. This
 	   is the trampoline code common to all methods  */
 	   is the trampoline code common to all methods  */
 		
 		
-	code = buf = mono_global_codeman_reserve(512);
+	code = buf = (guint8 *) mono_global_codeman_reserve(512);
 		
 		
 	if (tramp_type == MONO_TRAMPOLINE_JUMP) 
 	if (tramp_type == MONO_TRAMPOLINE_JUMP) 
 		has_caller = 0;
 		has_caller = 0;
@@ -399,7 +399,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 	/*---------------------------------------------------------------*/	
 	/*---------------------------------------------------------------*/	
 	/* save method info						 */	
 	/* save method info						 */	
 	/*---------------------------------------------------------------*/	
 	/*---------------------------------------------------------------*/	
-	s390_lg    (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1]));
+	s390_lg    (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0]));
 	s390_stg   (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method));				
 	s390_stg   (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method));				
 									
 									
 	/*---------------------------------------------------------------*/	
 	/*---------------------------------------------------------------*/	
@@ -435,7 +435,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
 	}
 	}
 
 
 	/* Arg 3: Trampoline argument */
 	/* Arg 3: Trampoline argument */
-	s390_lg (buf, s390_r4, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1]));
+	s390_lg (buf, s390_r4, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0]));
 
 
 	/* Arg 4: trampoline address. */
 	/* Arg 4: trampoline address. */
 	S390_SET (buf, s390_r5, buf);
 	S390_SET (buf, s390_r5, buf);
@@ -534,7 +534,7 @@ void
 mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
 mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg)
 {
 {
 	/* FIXME: This is not thread safe */
 	/* FIXME: This is not thread safe */
-	guint8 *code = ji->code_start;
+	guint8 *code = (guint8 *) ji->code_start;
 
 
 	S390_SET  (code, s390_r1, func);
 	S390_SET  (code, s390_r1, func);
 	S390_SET  (code, s390_r2, func_arg);
 	S390_SET  (code, s390_r2, func_arg);
@@ -556,7 +556,7 @@ gpointer
 mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len)
 mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len)
 {
 {
 	guint8 *code, *buf, *tramp;
 	guint8 *code, *buf, *tramp;
-	gint32 displace;
+	gint64 displace;
 
 
 	tramp = mono_get_trampoline_code (tramp_type);
 	tramp = mono_get_trampoline_code (tramp_type);
 
 
@@ -565,11 +565,16 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty
 	/* purpose is to provide the generic part with the          */
 	/* purpose is to provide the generic part with the          */
 	/* MonoMethod *method pointer. We'll use r1 to keep it.     */
 	/* MonoMethod *method pointer. We'll use r1 to keep it.     */
 	/*----------------------------------------------------------*/
 	/*----------------------------------------------------------*/
-	code = buf = mono_mem_manager_code_reserve (mem_manager, SPECIFIC_TRAMPOLINE_SIZE);
+	code = buf = (guint8 *) mono_mem_manager_code_reserve (mem_manager, SPECIFIC_TRAMPOLINE_SIZE);
 
 
-	S390_SET  (buf, s390_r1, arg1);
+	S390_SET  (buf, s390_r0, arg1);
 	displace = (tramp - buf) / 2;
 	displace = (tramp - buf) / 2;
-	s390_jg   (buf, displace);
+	if ((displace >= INT_MIN) && (displace <= INT_MAX))
+		s390_jg   (buf, (gint32) displace);
+	else {
+		S390_SET  (buf, s390_r1, tramp);
+		s390_br   (buf, s390_r1);
+	}
 
 
 	/* Flush instruction cache, since we've generated code */
 	/* Flush instruction cache, since we've generated code */
 	mono_arch_flush_icache (code, buf - code);
 	mono_arch_flush_icache (code, buf - code);
@@ -602,7 +607,7 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
 	guint8 *tramp;
 	guint8 *tramp;
 	guint8 *code, *buf;
 	guint8 *code, *buf;
 	guint8 **rgctx_null_jumps;
 	guint8 **rgctx_null_jumps;
-	gint32 displace;
+	gint64 displace;
 	int tramp_size,
 	int tramp_size,
 	    depth, 
 	    depth, 
 	    index, 
 	    index, 
@@ -630,11 +635,11 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
 	else
 	else
 		tramp_size += 12;
 		tramp_size += 12;
 
 
-	code = buf = mono_global_codeman_reserve (tramp_size);
+	code = buf = (guint8 *) mono_global_codeman_reserve (tramp_size);
 
 
 	unwind_ops = mono_arch_get_cie_program ();
 	unwind_ops = mono_arch_get_cie_program ();
 
 
-	rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
+	rgctx_null_jumps = (guint8 **) g_malloc (sizeof (guint8*) * (depth + 2));
 
 
 	if (mrgctx) {
 	if (mrgctx) {
 		/* get mrgctx ptr */
 		/* get mrgctx ptr */
@@ -690,7 +695,12 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info
 
 
 	/* jump to the actual trampoline */
 	/* jump to the actual trampoline */
 	displace = (tramp - code) / 2;
 	displace = (tramp - code) / 2;
-	s390_jg (code, displace);
+	if ((displace >= INT_MIN) && (displace <= INT_MAX))
+		s390_jg (code, displace);
+	else {
+		S390_SET (code, s390_r1, tramp);
+		s390_br  (code, s390_r1);
+	}
 
 
 	mono_arch_flush_icache (buf, code - buf);
 	mono_arch_flush_icache (buf, code - buf);
 	MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
 	MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
@@ -719,17 +729,22 @@ gpointer
 mono_arch_get_static_rgctx_trampoline (MonoMemoryManager *mem_manager, gpointer arg, gpointer addr)
 mono_arch_get_static_rgctx_trampoline (MonoMemoryManager *mem_manager, gpointer arg, gpointer addr)
 {
 {
 	guint8 *code, *start;
 	guint8 *code, *start;
-	gint32 displace;
+	gint64 displace;
 	int buf_len;
 	int buf_len;
 	MonoDomain *domain = mono_domain_get ();
 	MonoDomain *domain = mono_domain_get ();
 
 
 	buf_len = 32;
 	buf_len = 32;
 
 
-	start = code = mono_mem_manager_code_reserve (mem_manager, buf_len);
+	start = code = (guint8 *) mono_mem_manager_code_reserve (mem_manager, buf_len);
 
 
 	S390_SET  (code, MONO_ARCH_RGCTX_REG, arg);
 	S390_SET  (code, MONO_ARCH_RGCTX_REG, arg);
 	displace = ((uintptr_t) addr - (uintptr_t) code) / 2;
 	displace = ((uintptr_t) addr - (uintptr_t) code) / 2;
-	s390_jg   (code, displace);
+	if ((displace >= INT_MIN) && (displace <= INT_MAX))
+		s390_jg (code, (gint32) displace);
+	else {
+		S390_SET (code, s390_r1, addr);
+		s390_br (code, s390_r1);
+	}
 	g_assert ((code - start) < buf_len);
 	g_assert ((code - start) < buf_len);
 
 
 	mono_arch_flush_icache (start, code - start);
 	mono_arch_flush_icache (start, code - start);