diff options
author | Neale Ferguson <neale@sinenomine.net> | 2021-02-17 02:54:21 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-17 02:54:21 +0300 |
commit | c868a253f451000af8f7060ab0ea605bc58593ce (patch) | |
tree | 0a7966fa39a1b96eb6b3da47b9166691a9b6bd3d | |
parent | d6c2313a95058e9d6ee8d4b9b33cbaf9dfec1048 (diff) |
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`
-rw-r--r-- | mono/mini/mini-s390x.c | 140 | ||||
-rw-r--r-- | mono/mini/mini-s390x.h | 1 | ||||
-rw-r--r-- | mono/mini/tramp-s390x.c | 47 |
3 files changed, 101 insertions, 87 deletions
diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 612dcb0f5a8..138f64e82cc 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -1051,9 +1051,9 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) size_data *sz; if (mp) - cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm); + cinfo = (CallInfo *) mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm); else - cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm); + cinfo = (CallInfo *) g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm); fr = 0; 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); } break; - case OP_TLS_SET: { + case OP_TLS_SET: { if (s390_is_imm16 (ins->inst_offset)) { s390_lghi (code, s390_r13, 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_PATCH_INFO_METHOD_JUMP, 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 -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) 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 @@ -6247,7 +6245,7 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, MonoMethodS if (has_target) { 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 */ 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); 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)); /* slide down the arguments */ @@ -6364,7 +6362,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe return cached; 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 { MonoTrampInfo *info; 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) { 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); } else { MonoTrampInfo *info; @@ -6427,7 +6425,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod guint8 *code, *start; 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 @@ -6516,10 +6514,10 @@ mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, } 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 { 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; diff --git a/mono/mini/mini-s390x.h b/mono/mini/mini-s390x.h index 2b94792bd47..aaa5c33b642 100644 --- a/mono/mini/mini-s390x.h +++ b/mono/mini/mini-s390x.h @@ -81,6 +81,7 @@ struct SeqPointInfo { #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1 #define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1 +#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1 #define S390_STACK_ALIGNMENT 8 #define S390_FIRST_ARG_REG s390_r2 diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c index 8695f380a74..7c08412863d 100644 --- a/mono/mini/tramp-s390x.c +++ b/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); 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_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 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) has_caller = 0; @@ -399,7 +399,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /*---------------------------------------------------------------*/ /* 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)); /*---------------------------------------------------------------*/ @@ -435,7 +435,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf } /* 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. */ S390_SET (buf, s390_r5, buf); @@ -534,7 +534,7 @@ void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) { /* 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_r2, func_arg); @@ -556,7 +556,7 @@ gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len) { guint8 *code, *buf, *tramp; - gint32 displace; + gint64 displace; 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 */ /* 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; - 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 */ 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 *code, *buf; guint8 **rgctx_null_jumps; - gint32 displace; + gint64 displace; int tramp_size, depth, index, @@ -630,11 +635,11 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info else 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 (); - rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2)); + rgctx_null_jumps = (guint8 **) g_malloc (sizeof (guint8*) * (depth + 2)); if (mrgctx) { /* get mrgctx ptr */ @@ -690,7 +695,12 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info /* jump to the actual trampoline */ 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_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) { guint8 *code, *start; - gint32 displace; + gint64 displace; int buf_len; MonoDomain *domain = mono_domain_get (); 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); 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); mono_arch_flush_icache (start, code - start); |