From 8c36d04c87713b7251de9c591f551788efa4db7a Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Wed, 27 May 2015 11:24:37 -0400 Subject: [PATCH] Add support for OP_GENERIC_CLASS_INIT Add support for async callback --- mono/arch/s390x/s390x-codegen.h | 1 + mono/mini/cpu-s390x.md | 2 + mono/mini/exceptions-s390x.c | 78 +++++++++++++++++++-- mono/mini/mini-s390x.c | 46 +++++++++++-- mono/mini/mini-s390x.h | 7 +- mono/mini/tramp-s390x.c | 118 +++++++++++++++----------------- 6 files changed, 176 insertions(+), 76 deletions(-) diff --git a/mono/arch/s390x/s390x-codegen.h b/mono/arch/s390x/s390x-codegen.h index cd3df077ff6..05e83101039 100644 --- a/mono/arch/s390x/s390x-codegen.h +++ b/mono/arch/s390x/s390x-codegen.h @@ -1002,6 +1002,7 @@ typedef struct { #define s390_tmhl(c, r, m) S390_RI(c, 0xa72, r, m) #define s390_tmlh(c, r, m) S390_RI(c, 0xa70, r, m) #define s390_tmll(c, r, m) S390_RI(c, 0xa71, r, m) +#define s390_tm(c, b, d, v) S390_SI(c, 0x91, b, d, v) #define s390_x(c, r, x, b, d) S390_RX(c, 0x57, r, x, b, d) #define s390_xihf(c, r, v) S390_RIL_1(c, 0xc06, r, v) #define s390_xilf(c, r, v) S390_RIL_1(c, 0xc07, r, v) diff --git a/mono/mini/cpu-s390x.md b/mono/mini/cpu-s390x.md index 091c6b1103d..df26513baca 100644 --- a/mono/mini/cpu-s390x.md +++ b/mono/mini/cpu-s390x.md @@ -389,3 +389,5 @@ gc_liveness_def: len:0 gc_liveness_use: len:0 gc_spill_slot_liveness_def: len:0 gc_param_slot_liveness_def: len:0 + +generic_class_init: src1:A len:32 diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c index f5689e9624b..85961685e67 100644 --- a/mono/mini/exceptions-s390x.c +++ b/mono/mini/exceptions-s390x.c @@ -66,8 +66,11 @@ /* P r o t o t y p e s */ /*------------------------------------------------------------------*/ -gboolean mono_arch_handle_exception (void *ctx, - gpointer obj); +static void throw_exception (MonoObject *, unsigned long, unsigned long, + gulong *, gdouble *, gint32 *, guint, gboolean); +static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **, + int, gboolean, gboolean); +static void handle_signal_exception (gpointer); /*========================= End of Prototypes ======================*/ @@ -462,7 +465,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, StackFrameInfo *frame) { gpointer ip = (gpointer) MONO_CONTEXT_GET_IP (ctx); - MonoS390StackFrame *sframe; memset (frame, 0, sizeof (StackFrameInfo)); frame->ji = ji; @@ -519,6 +521,29 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /*========================= End of Function ========================*/ +/*------------------------------------------------------------------*/ +/* */ +/* Name - handle_signal_exception */ +/* */ +/* Function - Handle an exception raised by the JIT code. */ +/* */ +/* Parameters - obj - The exception object */ +/* */ +/*------------------------------------------------------------------*/ + +static void +handle_signal_exception (gpointer obj) +{ + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); + MonoContext ctx; + + memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext)); + mono_handle_exception (&ctx, obj); + mono_restore_context (&ctx); +} + +/*========================= End of Function ========================*/ + /*------------------------------------------------------------------*/ /* */ /* Name - mono_arch_handle_exception */ @@ -531,9 +556,52 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /*------------------------------------------------------------------*/ gboolean -mono_arch_handle_exception (void *uc, gpointer obj) +mono_arch_handle_exception (void *sigctx, gpointer obj) +{ + MonoContext mctx; + + /* + * Handling the exception in the signal handler is problematic, since the original + * signal is disabled, and we could run arbitrary code though the debugger. So + * resume into the normal stack and do most work there if possible. + */ + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); + + /* Pass the ctx parameter in TLS */ + mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx); + + mctx = jit_tls->ex_ctx; + mono_arch_setup_async_callback (&mctx, handle_signal_exception, obj); + mono_monoctx_to_sigctx (&mctx, sigctx); + + return TRUE; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_setup_async_callback */ +/* */ +/* Function - Establish the async callback. */ +/* */ +/* Parameters - ctx - Context */ +/* async_cb - Callback routine address */ +/* user_data - Data to be passed to callback */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data) { - return mono_handle_exception (uc, obj); + uintptr_t sp = (uintptr_t) MONO_CONTEXT_GET_SP(ctx); + + ctx->uc_mcontext.gregs[2] = (unsigned long) user_data; + + sp -= S390_MINIMAL_STACK_SIZE; + *(unsigned long *)sp = MONO_CONTEXT_GET_SP(ctx); + MONO_CONTEXT_SET_BP(ctx, sp); + MONO_CONTEXT_SET_IP(ctx, (unsigned long) async_cb); } /*========================= End of Function ========================*/ diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index 0df2e1a0b36..2a0b5198b90 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -267,6 +267,7 @@ if (ins->inst_target_bb->native_offset) { \ #include #include #include +#include #include "mini-s390x.h" #include "cpu-s390x.h" @@ -4119,7 +4120,29 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } - + case OP_GENERIC_CLASS_INIT: { + static int byte_offset = -1; + static guint8 bitmask; + guint16 *jump; + + g_assert (ins->sreg1 == S390_FIRST_ARG_REG); + + if (byte_offset < 0) + mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask); + + s390_tm (code, ins->sreg1, byte_offset, bitmask); + s390_jo (code, 0); CODEPTR(code, jump); + + mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ADDR, + "specific_trampoline_generic_class_init"); + S390_CALL_TEMPLATE(code, s390_r14); + + PTRSLOT (code, jump); + + ins->flags |= MONO_INST_GC_CALLSITE; + ins->backend.pc_offset = code - cfg->native_code; + break; + } case OP_BR: EMIT_UNCOND_BRANCH(ins); break; @@ -4592,6 +4615,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_MEMORY_BARRIER: s390_mem (code); break; +#if USE_COOP_GC + case OP_GC_SAFE_POINT: { + guint8 *br; + + s390_chi (code, ins->sreg1, 1); + s390_je (code, 0); CODEPTR(code, br); + mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS, + mono_threads_state_poll); + S390_CALL_TEMPLATE (code, s390_r14); + PTRSLOT (code, br); + break; + } +#endif case OP_GC_LIVENESS_DEF: case OP_GC_LIVENESS_USE: case OP_GC_PARAM_SLOT_LIVENESS_DEF: @@ -5565,9 +5601,7 @@ mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) gpointer mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code) { - MonoLMF *lmf = (MonoLMF *) ((gchar *) regs - sizeof(MonoLMF)); - - return (gpointer) lmf->gregs [s390_r2]; + return (gpointer) regs [s390_r2]; } /*========================= End of Function ========================*/ @@ -5951,9 +5985,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoMethod* mono_arch_find_imt_method (mgreg_t *regs, guint8 *code) { - MonoLMF *lmf = (MonoLMF *) ((gchar *) regs - sizeof(MonoLMF)); - - return ((MonoMethod *) lmf->gregs [MONO_ARCH_IMT_REG]); + return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]); } /*========================= End of Function ========================*/ diff --git a/mono/mini/mini-s390x.h b/mono/mini/mini-s390x.h index dd121873e7d..740ae80e1e3 100644 --- a/mono/mini/mini-s390x.h +++ b/mono/mini/mini-s390x.h @@ -50,7 +50,7 @@ typedef struct #define MONO_ARCH_HAVE_TLS_GET 1 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1 #define MONO_ARCH_IMT_REG s390_r9 -#define MONO_ARCH_VTABLE_REG MONO_ARCH_IMT_REG +#define MONO_ARCH_VTABLE_REG S390_FIRST_ARG_REG #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1 @@ -61,6 +61,8 @@ typedef struct #define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1 #define MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD 1 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1 +#define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1 +#define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1 #define MONO_ARCH_MONITOR_OBJECT_REG s390_r2 #define MONO_ARCH_LOCK_TAKEN_REG s390_r1 @@ -97,7 +99,8 @@ typedef struct #define MONO_ARCH_FPSTACK_SIZE 0 #define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? s390_r2 : \ - ((desc == 'g') ? s390_f0 : - 1)) + ((desc == 'g') ? s390_f0 : \ + ((desc == 'A') ? S390_FIRST_ARG_REG : -1))) #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g')) diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c index 2b6854849f0..af00ab54a25 100644 --- a/mono/mini/tramp-s390x.c +++ b/mono/mini/tramp-s390x.c @@ -20,20 +20,11 @@ /* D e f i n e s */ /*------------------------------------------------------------------*/ -#define GR_SAVE_SIZE 4*sizeof(long) -#define FP_SAVE_SIZE 16*sizeof(double) -#define METHOD_SAVE_OFFSET S390_MINIMAL_STACK_SIZE -#define CREATE_GR_OFFSET METHOD_SAVE_OFFSET+8 -#define CREATE_FP_OFFSET CREATE_GR_OFFSET+GR_SAVE_SIZE -#define CREATE_LMF_OFFSET CREATE_FP_OFFSET+FP_SAVE_SIZE -#define CREATE_STACK_SIZE (CREATE_LMF_OFFSET+2*sizeof(long)+sizeof(MonoLMF)) -#define GENERIC_REG_OFFSET CREATE_STACK_SIZE + \ - S390_REG_SAVE_OFFSET + \ - 3*sizeof(long) +#define LMFReg s390_r13 -/*------------------------------------------------------------------*/ -/* Method-specific trampoline code fragment sizes */ -/*------------------------------------------------------------------*/ +/* + * Method-specific trampoline code fragment sizes + */ #define SPECIFIC_TRAMPOLINE_SIZE 96 /*========================= End of Defines =========================*/ @@ -65,6 +56,11 @@ /* T y p e d e f s */ /*------------------------------------------------------------------*/ +typedef struct { + guint8 stk[S390_MINIMAL_STACK_SIZE]; /* Standard s390x stack */ + struct MonoLMF LMF; /* LMF */ +} trampStack_t; + /*========================= End of Typedefs ========================*/ /*------------------------------------------------------------------*/ @@ -226,7 +222,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf { char *tramp_name; guint8 *buf, *tramp, *code; - int i, offset, lmfOffset, has_caller; + int i, offset, has_caller; GSList *unwind_ops = NULL; MonoJumpInfo *ji = NULL; @@ -250,16 +246,29 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf s390_stmg (buf, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); s390_lgr (buf, s390_r11, s390_r15); - s390_aghi (buf, STK_BASE, -CREATE_STACK_SIZE); + s390_aghi (buf, STK_BASE, -sizeof(trampStack_t)); s390_stg (buf, s390_r11, 0, STK_BASE, 0); - s390_stg (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); - s390_stmg (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET); - /* Save the FP registers */ - offset = CREATE_FP_OFFSET; + /*---------------------------------------------------------------*/ + /* we build the MonoLMF structure on the stack - see mini-s390.h */ + /* Keep in sync with the code in mono_arch_emit_prolog */ + /*---------------------------------------------------------------*/ + + s390_lgr (buf, LMFReg, STK_BASE); + s390_aghi (buf, LMFReg, G_STRUCT_OFFSET(trampStack_t, LMF)); + + /*---------------------------------------------------------------*/ + /* Save general and floating point registers in LMF */ + /*---------------------------------------------------------------*/ + s390_stmg (buf, s390_r0, s390_r1, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); + s390_stmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); + s390_mvc (buf, 10*sizeof(gulong), LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[6]), + s390_r11, S390_REG_SAVE_OFFSET); + + offset = G_STRUCT_OFFSET(MonoLMF, fregs[0]); for (i = s390_f0; i <= s390_f15; ++i) { - s390_std (buf, i, 0, STK_BASE, offset); - offset += 8; + s390_std (buf, i, 0, LMFReg, offset); + offset += sizeof(gdouble); } /*---------------------------------------------------------- @@ -271,20 +280,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf S390_SET (buf, s390_r1, mono_get_lmf_addr); s390_basr (buf, s390_r14, s390_r1); - - /*---------------------------------------------------------------*/ - /* we build the MonoLMF structure on the stack - see mini-s390.h */ - /* Keep in sync with the code in mono_arch_emit_prolog */ - /*---------------------------------------------------------------*/ - lmfOffset = CREATE_STACK_SIZE - sizeof(MonoLMF); - - s390_lgr (buf, s390_r13, STK_BASE); - s390_aghi (buf, s390_r13, lmfOffset); /*---------------------------------------------------------------*/ /* Set lmf.lmf_addr = jit_tls->lmf */ /*---------------------------------------------------------------*/ - s390_stg (buf, s390_r2, 0, s390_r13, + s390_stg (buf, s390_r2, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); /*---------------------------------------------------------------*/ @@ -295,26 +295,25 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /*---------------------------------------------------------------*/ /* Set our lmf as the current lmf */ /*---------------------------------------------------------------*/ - s390_stg (buf, s390_r13, 0, s390_r2, 0); + s390_stg (buf, LMFReg, 0, s390_r2, 0); /*---------------------------------------------------------------*/ /* Have our lmf.previous_lmf point to the last lmf */ /*---------------------------------------------------------------*/ - s390_stg (buf, s390_r0, 0, s390_r13, + s390_stg (buf, s390_r0, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); /*---------------------------------------------------------------*/ /* save method info */ /*---------------------------------------------------------------*/ - s390_lg (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); - s390_stg (buf, s390_r1, 0, s390_r13, - G_STRUCT_OFFSET(MonoLMF, method)); + s390_lg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1])); + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method)); /*---------------------------------------------------------------*/ /* save the current SP */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, STK_BASE, 0); - s390_stg (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, ebp)); /*---------------------------------------------------------------*/ /* save the current IP */ @@ -324,28 +323,16 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf } else { s390_lghi (buf, s390_r1, 0); } - s390_stg (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); + s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, eip)); - /*---------------------------------------------------------------*/ - /* Save general and floating point registers */ - /*---------------------------------------------------------------*/ - s390_mvc (buf, 4*sizeof(gulong), s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[2]), - STK_BASE, CREATE_GR_OFFSET); - s390_mvc (buf, 10*sizeof(gulong), s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[6]), - s390_r11, S390_REG_SAVE_OFFSET); - - /* Simply copy fpregs already saved above */ - s390_mvc (buf, 16*sizeof(double), s390_r13, G_STRUCT_OFFSET(MonoLMF, fregs[0]), - STK_BASE, CREATE_FP_OFFSET); - /*---------------------------------------------------------------*/ /* STEP 2: call the C trampoline function */ /*---------------------------------------------------------------*/ /* Set arguments */ - /* Arg 1: mgreg_t *regs. We pass sp instead */ - s390_la (buf, s390_r2, 0, STK_BASE, CREATE_STACK_SIZE); + /* Arg 1: mgreg_t *regs */ + s390_la (buf, s390_r2, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); /* Arg 2: code (next address to the instruction that called us) */ if (has_caller) { @@ -356,9 +343,10 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /* Arg 3: Trampoline argument */ if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT) - s390_lg (buf, s390_r4, 0, STK_BASE, GENERIC_REG_OFFSET); + s390_lg (buf, s390_r4, 0, LMFReg, + G_STRUCT_OFFSET(MonoLMF, gregs[MONO_ARCH_VTABLE_REG])); else - s390_lg (buf, s390_r4, 0, STK_BASE, METHOD_SAVE_OFFSET); + s390_lg (buf, s390_r4, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1])); /* Arg 4: trampoline address. */ S390_SET (buf, s390_r5, buf); @@ -375,25 +363,25 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /*---------------------------------------------------------- STEP 3: Restore the LMF ----------------------------------------------------------*/ - restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE); + restoreLMF(buf, STK_BASE, sizeof(trampStack_t)); /*---------------------------------------------------------- STEP 4: call the compiled method ----------------------------------------------------------*/ - /* Restore registers */ - - s390_lmg (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET); + /* Restore parameter registers */ + s390_lmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); /* Restore the FP registers */ - offset = CREATE_FP_OFFSET; + offset = G_STRUCT_OFFSET(MonoLMF, fregs[0]); for (i = s390_f0; i <= s390_f15; ++i) { - s390_ld (buf, i, 0, STK_BASE, offset); - offset += 8; + s390_ld (buf, i, 0, LMFReg, offset); + offset += sizeof(gdouble); } /* Restore stack pointer and jump to the code - - R14 contains the return address to our caller */ + * R14 contains the return address to our caller + */ s390_lgr (buf, STK_BASE, s390_r11); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); @@ -475,6 +463,12 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty case MONO_TRAMPOLINE_MONITOR_EXIT: s390_lgr (buf, s390_r1, s390_r2); break; + /* + * Generic class trampoline arg is in r2 + */ + case MONO_TRAMPOLINE_GENERIC_CLASS_INIT: + s390_lgr (buf, s390_r1, s390_r2); + break; default : S390_SET (buf, s390_r1, arg1); } -- 2.25.1