From 95b41821414661b24ce2abd65a7b3ca2256c01a8 Mon Sep 17 00:00:00 2001 From: neale Date: Mon, 10 Jan 2005 21:13:14 +0000 Subject: [PATCH] - Fix atomic ops on s390 - Implement OP_ATOMIC_xxx operations on s390 - Standardize exception handling on s390 with other platforms - Enable out of line bblock support - Check vtable slot belongs to domain when building trampoline git-svn-id: svn+ssh://mono-cvs.ximian.com/source/trunk/mono@38647 e3ebcda4-bce8-0310-ba0a-eca2169e7518 --- mono/arch/s390/ChangeLog | 4 + mono/arch/s390/s390-codegen.h | 2 + mono/arch/s390x/ChangeLog | 5 +- mono/arch/s390x/s390x-codegen.h | 6 + mono/io-layer/ChangeLog | 3 + mono/io-layer/atomic.h | 2 +- mono/mini/ChangeLog | 11 + mono/mini/Makefile.am | 3 +- mono/mini/cpu-s390.md | 5 +- mono/mini/exceptions-s390.c | 456 +++----------------------------------- mono/mini/inssel-s390.brg | 18 +- mono/mini/mini-exceptions.c | 4 + mono/mini/mini-ops.h | 1 - mono/mini/mini-s390.c | 480 +++++++++++++++++++++------------------- mono/mini/mini-s390.h | 72 +++++- mono/mini/tramp-s390.c | 105 ++++----- 16 files changed, 456 insertions(+), 721 deletions(-) diff --git a/mono/arch/s390/ChangeLog b/mono/arch/s390/ChangeLog index 1f01e893f..5186c80af 100644 --- a/mono/arch/s390/ChangeLog +++ b/mono/arch/s390/ChangeLog @@ -1,3 +1,7 @@ +2004-12-15 Neale Ferguson + + * s390-codegen.h: Add some new instructions (CS, CDS) + 2004-11-15 Neale Ferguson * s390-codegen.h: Minor macro modifications diff --git a/mono/arch/s390/s390-codegen.h b/mono/arch/s390/s390-codegen.h index e21940762..38c7cbeb9 100644 --- a/mono/arch/s390/s390-codegen.h +++ b/mono/arch/s390/s390-codegen.h @@ -584,12 +584,14 @@ typedef struct { #define s390_cdb(c, r, x, b, d) S390_RXE(c, 0xed19, r, x, b, d) #define s390_cdbr(c, r1, r2) S390_RRE(c, 0xb319, r1, r2) #define s390_cdfbr(c, r1, r2) S390_RRE(c, 0xb395, r1, r2) +#define s390_cds(c, r1, r2, b, d) S390_RX(c, 0xbb, r1, r2, b, d) #define s390_cebr(c, r1, r2) S390_RRE(c, 0xb309, r1, r2) #define s390_cfdbr(c, r1, m, r2) S390_RRF_2(c, 0xb399, r1, m, r2) #define s390_chi(c, r, i) S390_RI(c, 0xa7e, r, i) #define s390_cl(c, r, x, b, d) S390_RX(c, 0x55, r, x, b, d) #define s390_clr(c, r1, r2) S390_RR(c, 0x15, r1, r2) #define s390_cr(c, r1, r2) S390_RR(c, 0x19, r1, r2) +#define s390_cs(c, r1, r2, b, d) S390_RX(c, 0xba, r1, r2, b, d) #define s390_ddbr(c, r1, r2) S390_RRE(c, 0xb31d, r1, r2) #define s390_debr(c, r1, r2) S390_RRE(c, 0xb30d, r1, r2) #define s390_didbr(c, r1, r2, m, r3) S390_RRF_3(c, 0xb35b, r1, r2, m, r3) diff --git a/mono/arch/s390x/ChangeLog b/mono/arch/s390x/ChangeLog index c65fce577..1cb7ef6d2 100644 --- a/mono/arch/s390x/ChangeLog +++ b/mono/arch/s390x/ChangeLog @@ -1,4 +1,7 @@ +2004-12-15 Neale Ferguson + + * s390x-codegen.h: Add some new instructions (CS, CSG, CSY, CDS, CDSG, CDSY) + 2004-08-03 Neale Ferguson * s390x-codegen.h Makefile.am tramp.c: S/390 64-bit interpreter - diff --git a/mono/arch/s390x/s390x-codegen.h b/mono/arch/s390x/s390x-codegen.h index 456f84035..ce9281c3b 100644 --- a/mono/arch/s390x/s390x-codegen.h +++ b/mono/arch/s390x/s390x-codegen.h @@ -592,6 +592,9 @@ typedef struct { #define s390_cdb(c, r, x, b, d) S390_RXE(c, 0xed19, r, x, b, d) #define s390_cdbr(c, r1, r2) S390_RRE(c, 0xb319, r1, r2) #define s390_cdfbr(c, r1, r2) S390_RRE(c, 0xb395, r1, r2) +#define s390_cds(c, r1, r2, b, d) S390_RX(c, 0xbb, r1, r2, b, d) +#define s390_cdsg(c, r1, r2, b, d) S390_RSY(c, 0xeb3e, r1, r2, b, d) +#define s390_cdsy(c, r1, r2, b, d) S390_RSY(c, 0xeb31, r1, r2, b, d) #define s390_cebr(c, r1, r2) S390_RRE(c, 0xb309, r1, r2) #define s390_cfdbr(c, r1, m, r2) S390_RRF_2(c, 0xb399, r1, m, r2) #define s390_cg(c, r, x, b, d) S390_RXY(c, 0xe320, r, x, b, d) @@ -603,6 +606,9 @@ typedef struct { #define s390_clgr(c, r1, r2) S390_RRE(c, 0xb921, r1, r2) #define s390_clr(c, r1, r2) S390_RR(c, 0x15, r1, r2) #define s390_cr(c, r1, r2) S390_RR(c, 0x19, r1, r2) +#define s390_cs(c, r1, r2, b, d) S390_RX(c, 0xba, r1, r2, b, d) +#define s390_csg(c, r1, r2, b, d) S390_RSY(c, 0xeb30, r1, r2, b, d) +#define s390_csy(c, r1, r2, b, d) S390_RSY(c, 0xeb14, r1, r2, b, d) #define s390_ddbr(c, r1, r2) S390_RRE(c, 0xb31d, r1, r2) #define s390_debr(c, r1, r2) S390_RRE(c, 0xb30d, r1, r2) #define s390_didbr(c, r1, r2, m, r3) S390_RRF_3(c, 0xb35b, r1, r2, m, r3) diff --git a/mono/io-layer/ChangeLog b/mono/io-layer/ChangeLog index 503785334..ea64ce029 100644 --- a/mono/io-layer/ChangeLog +++ b/mono/io-layer/ChangeLog @@ -1,3 +1,6 @@ +Mon Jan 10 16:15:19 EST 2005 Neale Ferguson + + * atomic.h: Fix functions on s390. Mon Jan 10 20:30:19 CET 2005 Paolo Molaro diff --git a/mono/io-layer/atomic.h b/mono/io-layer/atomic.h index 49d3dc1d0..c11f06ad0 100644 --- a/mono/io-layer/atomic.h +++ b/mono/io-layer/atomic.h @@ -366,7 +366,7 @@ InterlockedExchange(volatile gint32 *val, gint32 new_val) { gint32 ret; - __asm__ __volatile__ ("\tLA\t1,%1\n" + __asm__ __volatile__ ("\tLA\t1,%0\n" "0:\tL\t%1,%0\n" "\tCS\t%1,%2,0(1)\n" "\tJNZ\t0b" diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 09f21d0de..d894c5591 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,14 @@ +Mon Jan 10 16:11:16 EST 2005 Neale Ferguson + + * mini-ops.h, inssel-s390.brg, cpu-s390.md: Support OP_ATOMIC__xxx + operations. + + * tramp-s390.c: Check vtable slot belongs to the domain. + + * mini-exceptions.c, exceptions-s390.c: Standardize exception handling + as per other platforms. + + * mini-s390.c, mini-s390.h: Enable out-of-line bblock support. Mon Jan 10 18:53:05 CET 2005 Paolo Molaro diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index d4b3e380d..f5449fce9 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -128,11 +128,12 @@ ppc_sources = \ sparc_sources = \ mini-sparc.c \ mini-sparc.h \ - mini-exceptions.c \ + mini-exceptions.c \ exceptions-sparc.c \ tramp-sparc.c s390_sources = \ + mini-exceptions.c \ mini-s390.c \ mini-s390.h \ exceptions-s390.c \ diff --git a/mono/mini/cpu-s390.md b/mono/mini/cpu-s390.md index ca06f2b24..e25383235 100644 --- a/mono/mini/cpu-s390.md +++ b/mono/mini/cpu-s390.md @@ -61,6 +61,9 @@ and_imm: dest:i src1:i len:16 aot_const: dest:i len:8 arg: arglist: +atomic_add_i4: src1:b src2:i dest:i len:16 +atomic_exchange_i4: src1:b src2:i dest:i len:14 +atomic_add_new_i4: src1:b src2:i dest:i len:20 beq.s: beq: len:8 bge.s: @@ -449,7 +452,7 @@ ret: retarg: s390_move: len:48 dest:b src1:b s390_setf4ret: dest:f src1:f len:4 clob:r -s390_tls_get: dest:i len:44 +tls_get: dest:i len:44 sbb: dest:i src1:i src2:i len:6 sbb_imm: dest:i src1:i len:14 setfreg: dest:f src1:f len:4 clob:r diff --git a/mono/mini/exceptions-s390.c b/mono/mini/exceptions-s390.c index c26c9e572..06b5984b4 100644 --- a/mono/mini/exceptions-s390.c +++ b/mono/mini/exceptions-s390.c @@ -20,21 +20,6 @@ /* D e f i n e s */ /*------------------------------------------------------------------*/ -#define MONO_CONTEXT_SET_IP(ctx,ip) \ - do { \ - (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \ - (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \ - } while (0); - -#define MONO_CONTEXT_SET_BP(ctx,bp) \ - do { \ - (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \ - (ctx)->uc_stack.ss_sp = (unsigned long)bp; \ - } while (0); - -#define MONO_CONTEXT_GET_IP(ctx) context_get_ip ((ctx)) -#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15])) - #define S390_CALLFILTER_INTREGS S390_MINIMAL_STACK_SIZE #define S390_CALLFILTER_FLTREGS S390_CALLFILTER_INTREGS+(16*sizeof(gulong)) #define S390_CALLFILTER_ACCREGS S390_CALLFILTER_FLTREGS+(16*sizeof(gdouble)) @@ -74,20 +59,6 @@ /*========================= End of Includes ========================*/ /*------------------------------------------------------------------*/ -/* T y p e d e f s */ -/*------------------------------------------------------------------*/ - -typedef struct -{ - void *prev; - void *unused[5]; - void *regs[8]; - void *return_address; -} MonoS390StackFrame; - -/*========================= End of Typedefs ========================*/ - -/*------------------------------------------------------------------*/ /* P r o t o t y p e s */ /*------------------------------------------------------------------*/ @@ -105,26 +76,6 @@ gboolean mono_arch_handle_exception (void *ctx, /*------------------------------------------------------------------*/ /* */ -/* Name - context_get_ip */ -/* */ -/* Function - Extract the current instruction address from the */ -/* context. */ -/* */ -/*------------------------------------------------------------------*/ - -static inline gpointer -context_get_ip (MonoContext *ctx) -{ - gpointer ip; - - ip = (gpointer) ((gint32) (ctx->uc_mcontext.psw.addr) & 0x7fffffff); - return ip; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - mono_arch_has_unwind_info */ /* */ /* Function - Tests if a function has a DWARF exception table */ @@ -142,7 +93,7 @@ mono_arch_has_unwind_info (gconstpointer addr) /*------------------------------------------------------------------*/ /* */ -/* Name - arch_get_call_filter */ +/* Name - mono_arch_get_call_filter */ /* */ /* Function - Return a pointer to a method which calls an */ /* exception filter. We also use this function to */ @@ -151,8 +102,8 @@ mono_arch_has_unwind_info (gconstpointer addr) /* */ /*------------------------------------------------------------------*/ -static gpointer -arch_get_call_filter (void) +gpointer +mono_arch_get_call_filter (void) { static guint8 start [512]; static int inited = 0; @@ -209,7 +160,8 @@ arch_get_call_filter (void) /*------------------------------------------------------*/ /* Load all registers with values from the context */ /*------------------------------------------------------*/ - s390_lm (code, s390_r3, s390_r12, s390_r13, G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[3])); + s390_lm (code, s390_r3, s390_r12, s390_r13, + G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[3])); pos = G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs[0]); for (i = 0; i < 16; ++i) { s390_ld (code, i, 0, s390_r13, pos); @@ -462,35 +414,6 @@ mono_arch_get_throw_exception_by_name (void) /*------------------------------------------------------------------*/ /* */ -/* Name - glist_to_array */ -/* */ -/* Function - Convert a list to a mono array. */ -/* */ -/*------------------------------------------------------------------*/ - -static MonoArray * -glist_to_array (GList *list) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - int len, i; - - if (!list) - return NULL; - - len = g_list_length (list); - res = mono_array_new (domain, mono_defaults.int_class, len); - - for (i = 0; list; list = list->next, i++) - mono_array_set (res, gpointer, i, list->data); - - return res; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - mono_arch_find_jit_info */ /* */ /* Function - This function is used to gather informatoin from */ @@ -537,7 +460,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, *new_ctx = *ctx; - if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { + if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) { /* remove any unused lmf */ *lmf = (*lmf)->previous_lmf; } @@ -571,7 +494,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, g_free (source_location); g_free (tmpaddr); } - sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_BP (ctx); + sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_SP (ctx); MONO_CONTEXT_SET_BP (new_ctx, sframe->prev); sframe = (MonoS390StackFrame *) sframe->prev; MONO_CONTEXT_SET_IP (new_ctx, sframe->return_address); @@ -613,177 +536,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, /*------------------------------------------------------------------*/ /* */ -/* Name - ves_icall_get_trace */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -MonoArray * -ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info) -{ - MonoDomain *domain = mono_domain_get (); - MonoArray *res; - MonoArray *ta = exc->trace_ips; - int i, len; - - if (ta == NULL) { - return mono_array_new (domain, mono_defaults.stack_frame_class, 0); - } - - len = mono_array_length (ta); - - res = mono_array_new (domain, mono_defaults.stack_frame_class, - len > skip ? len - skip : 0); - - for (i = skip; i < len; i++) { - MonoJitInfo *ji; - MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class); - gpointer ip = mono_array_get (ta, gpointer, i); - - ji = mono_jit_info_table_find (domain, ip); - if (ji == NULL) { - mono_array_set (res, gpointer, i, sf); - continue; - } - - sf->method = mono_method_get_object (domain, ji->method, NULL); - sf->native_offset = (char *)ip - (char *)ji->code_start; - - sf->il_offset = mono_debug_il_offset_from_address (ji->method, sf->native_offset, domain); - - if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, sf->native_offset, &sf->line, domain); - - sf->filename = filename? mono_string_new (domain, filename): NULL; - sf->column = 0; - - g_free (filename); - } - - mono_array_set (res, gpointer, i, sf); - } - - return res; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_jit_walk_stack */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -void -mono_jit_walk_stack (MonoStackWalk func, gboolean do_il_offset, gpointer user_data) { - MonoDomain *domain = mono_domain_get (); - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - MonoJitInfo *ji, rji; - gint native_offset, il_offset; - gboolean managed; - MonoContext ctx, new_ctx; - - MONO_CONTEXT_SET_IP (&ctx, __builtin_return_address (0)); - MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (1)); - - while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) { - - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, - &ctx, &new_ctx, NULL, &lmf, - &native_offset, &managed); - g_assert (ji); - - if (ji == (gpointer)-1) - return; - - il_offset = do_il_offset ? mono_debug_il_offset_from_address (ji->method, native_offset, domain): -1; - - if (func (ji->method, native_offset, il_offset, managed, user_data)) - return; - - ctx = new_ctx; - } -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - ves_icall_get_frame_info */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -MonoBoolean -ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, - MonoReflectionMethod **method, - gint32 *iloffset, gint32 *native_offset, - MonoString **file, gint32 *line, gint32 *column) -{ - MonoDomain *domain = mono_domain_get (); - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - MonoJitInfo *ji, rji; - MonoContext ctx, new_ctx; - - MONO_CONTEXT_SET_IP (&ctx, ves_icall_get_frame_info); - MONO_CONTEXT_SET_BP (&ctx, __builtin_frame_address (0)); - - skip++; - - do { - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, - &ctx, &new_ctx, NULL, &lmf, - native_offset, NULL); - - ctx = new_ctx; - - if (!ji || ji == (gpointer)-1 || - MONO_CONTEXT_GET_BP (&ctx) >= jit_tls->end_of_stack) - return FALSE; - - /*---------------------------------------------------*/ - /* skip all wrappers ?? */ - /*---------------------------------------------------*/ - if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE || - ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE || - ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH || - ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK || - ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) - continue; - - skip--; - - } while (skip >= 0); - - *method = mono_method_get_object (domain, ji->method, NULL); - *iloffset = mono_debug_il_offset_from_address (ji->method, *native_offset, domain); - - if (need_file_info) { - gchar *filename; - - filename = mono_debug_source_location_from_address (ji->method, *native_offset, line, domain); - - *file = filename? mono_string_new (domain, filename): NULL; - *column = 0; - - g_free (filename); - } - - return TRUE; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - mono_arch_handle_exception */ /* */ /* Function - Handle an exception raised by the JIT code. */ @@ -798,180 +550,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info, gboolean mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only) { - MonoContext *ctx = uc; - MonoDomain *domain = mono_domain_get (); - MonoJitInfo *ji, rji; - static int (*call_filter) (MonoContext *, gpointer, gpointer) = NULL; - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); - MonoLMF *lmf = jit_tls->lmf; - GList *trace_ips = NULL; - GString *traceStr = NULL; - MonoException *mono_ex; - MonoString *initialStackTrace = NULL; - int frameCount = 0; - - g_assert (ctx != NULL); - memset(&rji, 0, sizeof(rji)); - if (!obj) { - MonoException *ex = mono_get_exception_null_reference (); - ex->message = mono_string_new (domain, - "Object reference not set to an instance of an object"); - obj = (MonoObject *)ex; - } - - if (mono_object_isinst (obj, mono_defaults.exception_class)) { - mono_ex = (MonoException*)obj; - initialStackTrace = mono_ex->stack_trace; - } else { - mono_ex = NULL; - } - - - if (!call_filter) - call_filter = arch_get_call_filter (); - - g_assert (jit_tls->end_of_stack); - g_assert (jit_tls->abort_func); - - if (!test_only) { - MonoContext ctx_cp = *ctx; - if (mono_jit_trace_calls != NULL) - g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name); - if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) { - if (mono_break_on_exc) - G_BREAKPOINT (); - mono_unhandled_exception (obj); - } - } - - memset (&rji, 0, sizeof(rji)); - - while (1) { - MonoContext new_ctx; - char *trace = NULL; - gboolean needTrace = FALSE; - - if (test_only && (frameCount < 1000)) { - needTrace = TRUE; - if (!traceStr) - traceStr = g_string_new (""); - } - - ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx, - test_only ? &trace : NULL, &lmf, NULL, NULL); - if (!ji) { - g_warning ("Exception inside function without unwind info"); - g_assert_not_reached (); - } - - if (ji != (gpointer)-1) { - frameCount++; - - if ((test_only) && - (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) && - (mono_ex)) { - if (!initialStackTrace && (frameCount < 1000)) { - trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx)); - g_string_append (traceStr, trace); - g_string_append_c (traceStr, '\n'); - } - } - - if (ji->num_clauses) { - int i; - - g_assert (ji->clauses); - - for (i = 0; i < ji->num_clauses; i++) { - MonoJitExceptionInfo *ei = &ji->clauses [i]; - gboolean filtered = FALSE; - - - if (ei->try_start < MONO_CONTEXT_GET_IP (ctx) && - MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) { - /* catch block */ - if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || - (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) { - g_assert (ji->exvar_offset); - *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj; - if (!initialStackTrace && - traceStr) { - mono_ex->stack_trace = mono_string_new (domain, traceStr->str); - } - } - - if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) - filtered = call_filter (ctx, ei->data.filter, obj); - - if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) && - (mono_object_isinst (obj, ei->data.catch_class)) || - (filtered)) { - if (test_only) { - if (mono_ex) { - trace_ips = g_list_reverse (trace_ips); - mono_ex->trace_ips = glist_to_array (trace_ips); - } - g_list_free (trace_ips); - g_free (trace); - if (traceStr) - g_string_free (traceStr, TRUE); - - return TRUE; - } - - if (mono_jit_trace_calls != NULL) - g_print ("EXCEPTION: catch found at clause %d of %s - caught at %p with sp %p\n", - i, mono_method_full_name (ji->method, TRUE), - ei->handler_start, - MONO_CONTEXT_GET_BP(ctx)); - MONO_CONTEXT_SET_IP (ctx, ei->handler_start); - jit_tls->lmf = lmf; - g_free (trace); - if (traceStr) - g_string_free (traceStr, TRUE); - return FALSE; - } - - if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && - MONO_CONTEXT_GET_IP (ctx) < ei->try_end && - (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) { - if (mono_jit_trace_calls != NULL) - g_print ("EXCEPTION: finally clause %d of %s handled at: %p using sp: %p\n", - i, mono_method_full_name (ji->method, TRUE), - ei->handler_start, - MONO_CONTEXT_GET_BP(ctx)); - call_filter (ctx, ei->handler_start, NULL); - } - - } - } - } - } - - g_free (trace); - - *ctx = new_ctx; - - if ((ji == (gpointer)-1) || - (MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack)) { - if (!test_only) { - jit_tls->lmf = lmf; - jit_tls->abort_func (obj); - g_assert_not_reached (); - } else { - if (mono_ex) { - trace_ips = g_list_reverse (trace_ips); - mono_ex->trace_ips = glist_to_array (trace_ips); - } - g_list_free (trace_ips); - if (traceStr) - g_string_free (traceStr, TRUE); - return FALSE; - } - } - } - - g_assert_not_reached (); + return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc), test_only); } /*========================= End of Function ========================*/ @@ -997,6 +576,24 @@ mono_arch_ip_from_context (void *sigctx) /*------------------------------------------------------------------*/ /* */ +/* Name - mono_arch_get_restore_context */ +/* */ +/* Function - Return the address of the routine that will rest- */ +/* ore the context. */ +/* */ +/*------------------------------------------------------------------*/ + +gpointer +mono_arch_get_restore_context () +{ + return setcontext; +} + + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ /* Name - mono_arch_is_int_overflow */ /* */ /* Function - Inspect the code that raised the SIGFPE signal */ @@ -1053,6 +650,7 @@ mono_arch_is_int_overflow (void *uc, void *info) default: arithExc = TRUE; } + ctx->uc_mcontext.psw.addr = code; return (arithExc); } diff --git a/mono/mini/inssel-s390.brg b/mono/mini/inssel-s390.brg index f8a11a882..fba017d08 100644 --- a/mono/mini/inssel-s390.brg +++ b/mono/mini/inssel-s390.brg @@ -699,8 +699,24 @@ base: CEE_LDOBJ (OP_S390_STKARG) "0" { tree->inst_basereg = tmpr; } -reg: OP_S390_TLS_GET { +reg: OP_ATOMIC_ADD_NEW_I4 (base, reg), +reg: OP_ATOMIC_ADD_I4 (base, reg) { + tree->opcode = tree->opcode; + tree->inst_basereg = state->left->tree->inst_basereg; + tree->inst_offset = state->left->tree->inst_offset; tree->dreg = state->reg1; + tree->sreg2 = state->right->reg1; + + mono_bblock_add_inst (s->cbb, tree); +} + +reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) { + tree->opcode = OP_ATOMIC_EXCHANGE_I4; + tree->dreg = state->reg1; + tree->sreg2 = state->right->reg1; + tree->inst_basereg = state->left->tree->inst_basereg; + tree->inst_offset = state->left->tree->inst_offset; + mono_bblock_add_inst (s->cbb, tree); } diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 976c563f1..e2b1acfc8 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -594,7 +594,11 @@ mono_handle_exception (MonoContext *ctx, gpointer obj, gpointer original_ip, gbo MonoJitExceptionInfo *ei = &ji->clauses [i]; gboolean filtered = FALSE; +#ifdef __s390__ + if (ei->try_start < MONO_CONTEXT_GET_IP (ctx) && +#else if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) && +#endif MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) { /* catch block */ diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index 733e08f50..54bc9096f 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -497,4 +497,3 @@ MINI_OP(OP_S390_ARGPTR, "s390_argptr") MINI_OP(OP_S390_STKARG, "s390_stkarg") MINI_OP(OP_S390_MOVE, "s390_move") MINI_OP(OP_S390_SETF4RET, "s390_setf4ret") -MINI_OP(OP_S390_TLS_GET, "s390_tls_get") diff --git a/mono/mini/mini-s390.c b/mono/mini/mini-s390.c index 8368dc03e..f5b5551e0 100644 --- a/mono/mini/mini-s390.c +++ b/mono/mini/mini-s390.c @@ -99,6 +99,8 @@ if (ins->flags & MONO_INST_BRLABEL) { \ #undef DEBUG #define DEBUG(a) if (cfg->verbose_level > 1) a +#define MAX_EXC 16 + /*----------------------------------------*/ /* use s390_r2-s390_r5 as temp registers */ /*----------------------------------------*/ @@ -498,7 +500,7 @@ decodeParm(MonoType *type, void *curParm, int size) if (type->byref) { printf("[BYREF:%p], ", *((char **) curParm)); } else { - simpleType = type->type; + simpleType = mono_type_get_underlying_type(type)->type; enum_parmtype: switch (simpleType) { case MONO_TYPE_I : @@ -548,7 +550,7 @@ enum_parmtype: case MONO_TYPE_OBJECT : { MonoObject *obj = *((MonoObject **) curParm); MonoClass *class; - if (obj) { + if ((obj) && (obj->vtable)) { printf("[CLASS/OBJ:"); class = obj->vtable->klass; if (class == mono_defaults.string_class) { @@ -641,6 +643,8 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) void *curParm; fname = mono_method_full_name (method, TRUE); +if (strcmp("(wrapper native-to-managed) Tests:call_int_delegate (Tests/return_int_delegate)",fname) == 0) +printf("!!\n"); indent (1); printf ("ENTER: %s(", fname); g_free (fname); @@ -832,7 +836,7 @@ handle_enum: case MONO_TYPE_OBJECT: { MonoObject *o = va_arg (ap, MonoObject *); - if (o) { + if ((o) && (o->vtable)) { if (o->vtable->klass == mono_defaults.boolean_class) { printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject))); } else if (o->vtable->klass == mono_defaults.int32_class) { @@ -1036,8 +1040,11 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) GList *regs = NULL; int i, top = 13; + if (cfg->flags & MONO_CFG_HAS_ALLOCA) + cfg->frame_reg = s390_r11; + for (i = 8; i < top; ++i) { - if (cfg->frame_reg != i) + if (cfg->frame_reg != i) regs = g_list_prepend (regs, GUINT_TO_POINTER (i)); } @@ -3977,7 +3984,7 @@ guint8 cond; s390_ledbr (code, ins->dreg, ins->sreg1); } break; - case OP_S390_TLS_GET: { + case OP_TLS_GET: { if (s390_is_uimm16 (ins->inst_offset)) { s390_lhi (code, s390_r13, ins->inst_offset); } else { @@ -3997,16 +4004,24 @@ guint8 cond; } break; case CEE_JMP: { - int fParm; + int iParm, fParm, pOffset; if (cfg->method->save_lmf) restoreLMF(code, cfg->frame_reg, cfg->stack_usage); if (cfg->flags & MONO_CFG_HAS_TAIL) { - s390_lm (code, s390_r2, s390_r5, STK_BASE, - S390_PARM_SAVE_OFFSET); - for (fParm = 0; fParm < 4; fParm++) - s390_ld (code, fParm, 0, STK_BASE, - S390_FLOAT_SAVE_OFFSET+fParm*sizeof(double)); + pOffset = S390_PARM_SAVE_OFFSET; + s390_l (code, s390_r13, 0, STK_BASE, 0); + for (iParm = s390_r2; + iParm <= s390_r5; + iParm++, pOffset+sizeof(gint32)) { + if (cfg->used_int_regs & (1 << iParm)) + s390_l (code, iParm, 0, s390_r13, pOffset); + } + pOffset = S390_FLOAT_SAVE_OFFSET; + for (fParm = 0; + fParm < 4; + fParm++, pOffset+sizeof(double)) + s390_ld (code, fParm, 0, s390_r13, pOffset); } code = backUpStackPtr(cfg, code); @@ -4615,6 +4630,31 @@ guint8 cond; } } break; + case OP_ATOMIC_ADD_I4: { + s390_lr (code, s390_r1, ins->sreg2); + s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset); + s390_a (code, s390_r1, 0, ins->inst_basereg, ins->inst_offset); + s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset); + s390_jnz (code, -7); + s390_lr (code, ins->dreg, s390_r1); + } + break; + case OP_ATOMIC_ADD_NEW_I4: { + s390_lr (code, s390_r1, ins->sreg2); + s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset); + s390_a (code, s390_r1, 0, ins->inst_basereg, ins->inst_offset); + s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset); + s390_jnz (code, -7); + s390_lr (code, ins->dreg, s390_r1); + } + break; + case OP_ATOMIC_EXCHANGE_I4: { + s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset); + s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset); + s390_jnz (code, -4); + s390_lr (code, ins->dreg, s390_r0); + } + break; default: g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__); g_assert_not_reached (); @@ -4667,163 +4707,50 @@ mono_arch_register_lowlevel_calls (void) /*------------------------------------------------------------------*/ void -mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors) +mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, + guint8 *code, MonoJumpInfo *ji, gboolean run_cctors) { MonoJumpInfo *patch_info; for (patch_info = ji; patch_info; patch_info = patch_info->next) { unsigned char *ip = patch_info->ip.i + code; - gint32 target = 0; + gconstpointer target = NULL; + + target = mono_resolve_patch_target (method, domain, code, + patch_info, run_cctors); switch (patch_info->type) { - case MONO_PATCH_INFO_BB: - target = S390_RELATIVE((patch_info->data.bb->native_offset+code), - ip); - ip += 2; /* Skip over op-code */ - break; - case MONO_PATCH_INFO_ABS: - target = S390_RELATIVE(patch_info->data.target, ip); - ip += 2; /* Skip over op-code */ - break; - case MONO_PATCH_INFO_LABEL: - target = S390_RELATIVE((patch_info->data.inst->inst_c0+code),ip); - ip += 2; /* Skip over op-code */ - break; - case MONO_PATCH_INFO_IP: - target = ip; - continue; - case MONO_PATCH_INFO_METHOD_REL: - g_assert_not_reached (); - *((gpointer *)(ip)) = code + patch_info->data.offset; - continue; - case MONO_PATCH_INFO_INTERNAL_METHOD: { - MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name); - if (!mi) { - g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name); + case MONO_PATCH_INFO_IP: + case MONO_PATCH_INFO_EXC_NAME: + case MONO_PATCH_INFO_LDSTR: + case MONO_PATCH_INFO_TYPE_FROM_HANDLE: + case MONO_PATCH_INFO_LDTOKEN: + case MONO_PATCH_INFO_EXC: + 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) */ + /*----------------------------------*/ + *((gconstpointer *)(ip+6)) = target; + target = NULL; + 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: + target = S390_RELATIVE(target, ip); + continue; + case MONO_PATCH_INFO_R4: + case MONO_PATCH_INFO_R8: + case MONO_PATCH_INFO_METHOD_REL: g_assert_not_reached (); - } - target = S390_RELATIVE(mono_icall_get_wrapper (mi), ip); - ip += 2; /* Skip over op-code */ - break; - } - case MONO_PATCH_INFO_METHOD_JUMP: { - GSList *list; - - /*------------------------------------------------------*/ - /* get the trampoline to the method from the domain */ - /*------------------------------------------------------*/ - target = mono_create_jump_trampoline (domain, - patch_info->data.method, - TRUE); - target = S390_RELATIVE(target, ip); - if (!domain->jump_target_hash) - domain->jump_target_hash = g_hash_table_new (NULL, NULL); - list = g_hash_table_lookup (domain->jump_target_hash, - patch_info->data.method); - list = g_slist_prepend (list, ip); - g_hash_table_insert (domain->jump_target_hash, - patch_info->data.method, list); - ip +=2; - break; - } - case MONO_PATCH_INFO_METHOD: - if (patch_info->data.method == method) { - target = S390_RELATIVE(code, ip); - } else { - /* get the trampoline to the method from the domain */ - target = S390_RELATIVE(mono_arch_create_jit_trampoline (patch_info->data.method), ip); - target = mono_arch_create_jit_trampoline(patch_info->data.method); + continue; + default: target = S390_RELATIVE(target, ip); - } - ip += 2; /* Skip over op-code */ - break; - case MONO_PATCH_INFO_SWITCH: { - gpointer *table = (gpointer *)patch_info->data.target; - int i; - /*------------------------------------------------------*/ - /* ip is pointing at the basr r13,0/j +4 instruction */ - /* the vtable value follows this (i.e. ip+6) */ - /*------------------------------------------------------*/ - *((gconstpointer *)(ip+6)) = table; - - for (i = 0; i < patch_info->table_size; i++) { - table [i] = (int)patch_info->data.table [i] + code; - } - continue; - } - case MONO_PATCH_INFO_METHODCONST: - case MONO_PATCH_INFO_CLASS: - case MONO_PATCH_INFO_IMAGE: - case MONO_PATCH_INFO_FIELD: - target = S390_RELATIVE(patch_info->data.target, ip); - continue; - case MONO_PATCH_INFO_R4: - case MONO_PATCH_INFO_R8: - g_assert_not_reached (); - *((gconstpointer *)(ip + 2)) = patch_info->data.target; - continue; - case MONO_PATCH_INFO_IID: - mono_class_init (patch_info->data.klass); - target = S390_RELATIVE(patch_info->data.klass->interface_id, ip); - continue; - case MONO_PATCH_INFO_VTABLE: - target = S390_RELATIVE(mono_class_vtable (domain, patch_info->data.klass),ip); - ip += 2; - continue; - case MONO_PATCH_INFO_CLASS_INIT: - target = S390_RELATIVE(mono_create_class_init_trampoline (mono_class_vtable (domain, patch_info->data.klass)), ip); - ip += 2; - break; - case MONO_PATCH_INFO_SFLDA: { - MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent); - if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && mono_class_needs_cctor_run (vtable->klass, method)) - /* Done by the generated code */ - ; - else { - if (run_cctors) - mono_runtime_class_init (vtable); - } - target = S390_RELATIVE((char*)vtable->data + patch_info->data.field->offset, ip); - ip += 2; - continue; - } - case MONO_PATCH_INFO_EXC_NAME: - *((gconstpointer *)(ip)) = patch_info->data.name; - continue; - case MONO_PATCH_INFO_LDSTR: - target = mono_ldstr (domain, patch_info->data.token->image, - mono_metadata_token_index (patch_info->data.token->token)); - continue; - case MONO_PATCH_INFO_TYPE_FROM_HANDLE: { - gpointer handle; - MonoClass *handle_class; - - handle = mono_ldtoken (patch_info->data.token->image, - patch_info->data.token->token, - &handle_class, NULL); - mono_class_init (handle_class); - mono_class_init (mono_class_from_mono_type (handle)); - - target = handle; - continue; - } - case MONO_PATCH_INFO_LDTOKEN: { - gpointer handle; - MonoClass *handle_class; - - handle = mono_ldtoken (patch_info->data.token->image, - patch_info->data.token->token, - &handle_class, NULL); - mono_class_init (handle_class); - - target = handle; - continue; - } - case MONO_PATCH_INFO_EXC: - /* everything is dealt with at epilog output time */ - continue; - default: - g_assert_not_reached (); + ip += 2; } s390_patch (ip, target); } @@ -4833,41 +4760,6 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_max_epilog_size */ -/* */ -/* Function - Determine the maximum size of the epilog code. */ -/* */ -/*------------------------------------------------------------------*/ - -int -mono_arch_max_epilog_size (MonoCompile *cfg) -{ - int max_epilog_size = 96; - MonoJumpInfo *patch_info; - - if (cfg->method->save_lmf) - max_epilog_size += 128; - - if (mono_jit_trace_calls != NULL) - max_epilog_size += 128; - - if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) - max_epilog_size += 128; - - /* count the number of exception infos */ - - for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { - if (patch_info->type == MONO_PATCH_INFO_EXC) - max_epilog_size += 26; - } - - return max_epilog_size; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - mono_arch_emit_prolog */ /* */ /* Function - Create the instruction sequence for a function */ @@ -5174,6 +5066,22 @@ mono_arch_emit_epilog (MonoCompile *cfg) MonoMethod *method = cfg->method; int tracing = 0; guint8 *code; + int max_epilog_size = 96; + + if (cfg->method->save_lmf) + max_epilog_size += 128; + + if (mono_jit_trace_calls != NULL) + max_epilog_size += 128; + + if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) + max_epilog_size += 128; + + while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) { + cfg->code_size *= 2; + cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); + mono_jit_stats.code_reallocs++; + } code = cfg->native_code + cfg->code_len; @@ -5193,37 +5101,108 @@ mono_arch_emit_epilog (MonoCompile *cfg) s390_lm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (code, s390_r14); - /* add code to raise exceptions */ + cfg->code_len = code - cfg->native_code; + + g_assert (cfg->code_len < cfg->code_size); + +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_emit_exceptions */ +/* */ +/* Function - Emit the blocks to handle exception conditions. */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_emit_exceptions (MonoCompile *cfg) +{ + MonoJumpInfo *patch_info; + guint8 *code; + int nThrows = 0, + exc_count = 0, + iExc; + guint32 code_size; + MonoClass *exc_classes [MAX_EXC]; + guint8 *exc_throw_start [MAX_EXC], + *exc_throw_end [MAX_EXC]; + + for (patch_info = cfg->patch_info; + patch_info; + patch_info = patch_info->next) { + if (patch_info->type == MONO_PATCH_INFO_EXC) + exc_count++; + } + + code_size = exc_count * 26; + + while ((cfg->code_len + code_size) > (cfg->code_size - 16)) { + cfg->code_size *= 2; + cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); + mono_jit_stats.code_reallocs++; + } + + code = cfg->native_code + cfg->code_len; + + /*---------------------------------------------------------------------*/ + /* Add code to raise exceptions */ + /*---------------------------------------------------------------------*/ for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { switch (patch_info->type) { case MONO_PATCH_INFO_EXC: { + guint8 *ip = patch_info->ip.i + cfg->native_code, + *buf, buf2; + MonoClass *exc_class; + guint32 throw_ip; + /*-----------------------------------------------------*/ /* Patch the branch in epilog to come here */ /*-----------------------------------------------------*/ - s390_patch (patch_info->ip.i+cfg->native_code+2, - S390_RELATIVE(code,patch_info->ip.i+cfg->native_code)); - /*-----------------------------------------------------*/ - /* Patch the parameter passed to the handler */ - /*-----------------------------------------------------*/ - s390_basr (code, s390_r13, 0); - s390_j (code, 4); - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_EXC_NAME, - patch_info->data.target); - s390_word (code, 0); - /*-----------------------------------------------------*/ - /* Load the return address and the parameter register */ - /*-----------------------------------------------------*/ - s390_larl (code, s390_r14, S390_RELATIVE((patch_info->ip.i + - cfg->native_code + 8), code)); - s390_l (code, s390_r2, 0, s390_r13, 4); - /*-----------------------------------------------------*/ - /* Reuse the current patch to set the jump */ - /*-----------------------------------------------------*/ - patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD; - patch_info->data.name = "mono_arch_throw_exception_by_name"; - patch_info->ip.i = code - cfg->native_code; - s390_jcl (code, S390_CC_UN, 0); + s390_patch (ip + 2, S390_RELATIVE(code,ip)); + + exc_class = mono_class_from_name (mono_defaults.corlib, + "System", + patch_info->data.name); + g_assert (exc_class); + throw_ip = patch_info->ip.i; + + for (iExc = 0; iExc < nThrows; ++iExc) + if (exc_classes [iExc] == exc_class) + break; + + if (iExc < nThrows) { + s390_jcl (code, S390_CC_UN, exc_throw_start [iExc]); + patch_info->type = MONO_PATCH_INFO_NONE; + } else { + + if (nThrows < MAX_EXC) { + exc_classes [nThrows] = exc_class; + exc_throw_start [nThrows] = code; + } + + /*---------------------------------------------*/ + /* Patch the parameter passed to the handler */ + /*---------------------------------------------*/ + s390_basr (code, s390_r13, 0); + s390_j (code, 4); + s390_word (code, patch_info->data.target); + /*---------------------------------------------*/ + /* Load return address & parameter register */ + /*---------------------------------------------*/ + s390_larl (code, s390_r14, S390_RELATIVE((patch_info->ip.i + + cfg->native_code + 8), code)); + s390_l (code, s390_r2, 0, s390_r13, 4); + /*---------------------------------------------*/ + /* Reuse the current patch to set the jump */ + /*---------------------------------------------*/ + patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD; + patch_info->data.name = "mono_arch_throw_exception_by_name"; + patch_info->ip.i = code - cfg->native_code; + s390_jcl (code, S390_CC_UN, 0); + } break; } default: @@ -5389,7 +5368,8 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_re /*------------------------------------------------------------------*/ MonoInst* -mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) +mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, + MonoMethodSignature *fsig, MonoInst **args) { MonoInst *ins = NULL; @@ -5398,6 +5378,43 @@ mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethod MONO_INST_NEW (cfg, ins, OP_SQRT); ins->inst_i0 = args [0]; } + } else if(cmethod->klass->image == mono_defaults.corlib && + (strcmp (cmethod->klass->name_space, "System.Threading") == 0) && + (strcmp (cmethod->klass->name, "Interlocked") == 0)) { + + if (strcmp (cmethod->name, "Increment") == 0 && + fsig->params [0]->type == MONO_TYPE_I4) { + MonoInst *ins_iconst; + + MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_NEW_I4); + MONO_INST_NEW (cfg, ins_iconst, OP_ICONST); + ins_iconst->inst_c0 = 1; + + ins->inst_i0 = args [0]; + ins->inst_i1 = ins_iconst; + } else if (strcmp (cmethod->name, "Decrement") == 0 && + fsig->params [0]->type == MONO_TYPE_I4) { + MonoInst *ins_iconst; + + MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_NEW_I4); + MONO_INST_NEW (cfg, ins_iconst, OP_ICONST); + ins_iconst->inst_c0 = -1; + + ins->inst_i0 = args [0]; + ins->inst_i1 = ins_iconst; + } else if (strcmp (cmethod->name, "Exchange") == 0 && + fsig->params [0]->type == MONO_TYPE_I4) { + MONO_INST_NEW (cfg, ins, OP_ATOMIC_EXCHANGE_I4); + + ins->inst_i0 = args [0]; + ins->inst_i1 = args [1]; + } else if (strcmp (cmethod->name, "Add") == 0 && + fsig->params [0]->type == MONO_TYPE_I4) { + MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4); + + ins->inst_i0 = args [0]; + ins->inst_i1 = args [1]; + } } return ins; } @@ -5445,7 +5462,7 @@ mono_arch_print_tree (MonoInst *tree, int arity) mono_arch_regname (tree->sreg1)); done = 1; break; - case OP_S390_TLS_GET: + case OP_TLS_GET: printf ("[0x%x(0x%x,%s)]", tree->inst_offset, tree->inst_imm, mono_arch_regname (tree->sreg1)); @@ -5498,7 +5515,7 @@ mono_arch_get_domain_intrinsic (MonoCompile* cfg) if (appdomain_tls_offset == -1) return NULL; - MONO_INST_NEW (cfg, ins, OP_S390_TLS_GET); + MONO_INST_NEW (cfg, ins, OP_TLS_GET); ins->inst_offset = appdomain_tls_offset; return (ins); } @@ -5523,9 +5540,26 @@ mono_arch_get_thread_intrinsic (MonoCompile* cfg) if (thread_tls_offset == -1) return NULL; - MONO_INST_NEW (cfg, ins, OP_S390_TLS_GET); + MONO_INST_NEW (cfg, ins, OP_TLS_GET); ins->inst_offset = thread_tls_offset; return (ins); } /*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_flush_register_windows */ +/* */ +/* Function - */ +/* */ +/* Returns - */ +/* */ +/*------------------------------------------------------------------*/ + +void +mono_arch_flush_register_windows (void) +{ +} + +/*========================= End of Function ========================*/ diff --git a/mono/mini/mini-s390.h b/mono/mini/mini-s390.h index fc3023494..457ec78c0 100644 --- a/mono/mini/mini-s390.h +++ b/mono/mini/mini-s390.h @@ -117,15 +117,28 @@ typedef struct ucontext MonoContext; typedef struct MonoCompileArch { } MonoCompileArch; -#define MONO_ARCH_EMULATE_FCONV_TO_I8 1 -#define MONO_ARCH_EMULATE_LCONV_TO_R8 1 -#define MONO_ARCH_EMULATE_LCONV_TO_R4 1 -#define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1 -#define MONO_ARCH_EMULATE_LMUL 1 -#define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1 -#define MONO_ARCH_NEED_DIV_CHECK 1 +typedef struct +{ + void *prev; + void *unused[5]; + void *regs[8]; + void *return_address; +} MonoS390StackFrame; + +#define MONO_ARCH_EMULATE_FCONV_TO_I8 1 +#define MONO_ARCH_EMULATE_LCONV_TO_R8 1 +#define MONO_ARCH_EMULATE_LCONV_TO_R4 1 +#define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1 +#define MONO_ARCH_EMULATE_LMUL 1 +#define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1 +#define MONO_ARCH_NEED_DIV_CHECK 1 +#define MONO_ARCH_HAVE_OUT_OF_LINE_BBLOCKS 1 +// #define MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION 1 #define MONO_ARCH_USE_SIGACTION 1 +// #define CUSTOM_STACK_WALK 1 +// #define CUSTOM_EXCEPTION_HANDLING 1 +#define mono_find_jit_info mono_arch_find_jit_info #define S390_STACK_ALIGNMENT 8 #define S390_FIRST_ARG_REG s390_r2 @@ -147,6 +160,51 @@ typedef struct MonoCompileArch { #define S390_CC_EQ 8 #define S390_ALIGN(v, a) (((a) > 0 ? (((v) + ((a) - 1)) & ~((a) - 1)) : (v))) +#define MONO_CONTEXT_SET_IP(ctx,ip) \ + do { \ + (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \ + (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \ + } while (0); + +#define MONO_CONTEXT_SET_SP(ctx,bp) MONO_CONTEXT_SET_BP((ctx),(bp)) +#define MONO_CONTEXT_SET_BP(ctx,bp) \ + do { \ + (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \ + (ctx)->uc_stack.ss_sp = (unsigned long)bp; \ + } while (0); + +#define MONO_CONTEXT_GET_IP(ctx) context_get_ip ((ctx)) +#define MONO_CONTEXT_GET_BP(ctx) MONO_CONTEXT_GET_SP((ctx)) +#define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15])) + +#define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \ + MonoS390StackFrame *sframe; \ + __asm__ volatile("l %0,0(15)" : "=r" (sframe)); \ + MONO_CONTEXT_SET_BP ((ctx), sframe->prev); \ + sframe = (MonoS390StackFrame*)sframe->prev; \ + MONO_CONTEXT_SET_IP ((ctx), sframe->return_address); \ + } while (0) + +/*------------------------------------------------------------------*/ +/* */ +/* Name - context_get_ip */ +/* */ +/* Function - Extract the current instruction address from the */ +/* context. */ +/* */ +/*------------------------------------------------------------------*/ + +static inline gpointer +context_get_ip (MonoContext *ctx) +{ + gpointer ip; + + ip = (gpointer) ((gint32) (ctx->uc_mcontext.psw.addr) & 0x7fffffff); + return ip; +} + +/*========================= End of Function ========================*/ + /*------------------------------------------------------------------*/ /* */ /* Name - s390_patch */ diff --git a/mono/mini/tramp-s390.c b/mono/mini/tramp-s390.c index 1153dd9e8..c88eefd1b 100644 --- a/mono/mini/tramp-s390.c +++ b/mono/mini/tramp-s390.c @@ -113,24 +113,20 @@ get_unbox_trampoline (MonoMethod *method, gpointer addr) int this_pos = s390_r2; start = addr; - if ((method->klass->valuetype)) { -// if ((method->klass->valuetype) && -// (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) { - if ((!method->signature->ret->byref) && - (MONO_TYPE_ISSTRUCT (method->signature->ret))) - this_pos = s390_r3; - - start = code = g_malloc (28); - - s390_basr (code, s390_r13, 0); - s390_j (code, 4); - s390_word (code, addr); - s390_l (code, s390_r1, 0, s390_r13, 4); - s390_ahi (code, this_pos, sizeof(MonoObject)); - s390_br (code, s390_r1); - - g_assert ((code - start) <= 28); - } + if ((!method->signature->ret->byref) && + (MONO_TYPE_ISSTRUCT (method->signature->ret))) + this_pos = s390_r3; + + start = code = g_malloc (28); + + s390_basr (code, s390_r13, 0); + s390_j (code, 4); + s390_word (code, addr); + s390_l (code, s390_r1, 0, s390_r13, 4); + s390_ahi (code, this_pos, sizeof(MonoObject)); + s390_br (code, s390_r1); + + g_assert ((code - start) <= 28); return start; } @@ -184,37 +180,43 @@ s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp) fname = mono_method_full_name (method, TRUE); codeJi = mono_jit_info_table_find (mono_domain_get(), code); addrJi = mono_jit_info_table_find (mono_domain_get(), addr); + if (mono_method_same_domain (codeJi, addrJi)) { + + opcode = *((unsigned short *) (code - 6)); + switch (opcode) { + case 0x5810 : + /* This is a bras r14,r1 instruction */ + code -= 4; + reg = *code >> 4; + displace = *((short *)code) & 0x0fff; + if (reg > 5) + base = *((int *) (sp + S390_REG_SAVE_OFFSET+ + sizeof(int)*(reg-6))); + else + base = *((int *) (sp + CREATE_GR_OFFSET+ + sizeof(int)*(reg-2))); + + if ((method->klass->valuetype) && + (!mono_aot_is_got_entry(code, base))) + addr = get_unbox_trampoline(method, addr); - opcode = *((unsigned short *) (code - 6)); - switch (opcode) { - case 0x5810 : - /* This is a bras r14,r1 instruction */ - code -= 4; - reg = *code >> 4; - displace = *((short *)code) & 0x0fff; - if (reg > 5) - base = *((int *) (sp + S390_REG_SAVE_OFFSET+ - sizeof(int)*(reg-6))); - else - base = *((int *) (sp + CREATE_GR_OFFSET+ - sizeof(int)*(reg-2))); - addr = get_unbox_trampoline(method, addr); - if (mono_method_same_domain (codeJi, addrJi)) { code = base + displace; - s390_patch(code, addr); - } - break; - case 0xc0e5 : - /* This is the 'brasl' instruction */ - code -= 4; - displace = ((gint32) addr - (gint32) (code - 2)) / 2; - if (mono_method_same_domain (codeJi, addrJi)) { - s390_patch (code, displace); - mono_arch_flush_icache (code, 4); - } - break; - default : - g_error("Unable to patch instruction prior to %p",code); + if (mono_domain_owns_vtable_slot(mono_domain_get(), + code)) + s390_patch(code, addr); + break; + case 0xc0e5 : + /* This is the 'brasl' instruction */ + code -= 4; + displace = ((gint32) addr - (gint32) (code - 2)) / 2; + if (mono_method_same_domain (codeJi, addrJi)) { + s390_patch (code, displace); + mono_arch_flush_icache (code, 4); + } + break; + default : + g_error("Unable to patch instruction prior to %p",code); + } } } @@ -551,12 +553,6 @@ mono_arch_create_jit_trampoline (MonoMethod *method) static guint8 *vc = NULL; gint32 displace; - if (method->info) - return (method->info); - - if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) - return (mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method))); - vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC); /* This is the method-specific part of the trampoline. Its purpose is @@ -579,9 +575,6 @@ mono_arch_create_jit_trampoline (MonoMethod *method) /* Sanity check */ g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE); - method->info = code; - mono_jit_stats.method_trampolines++; - return code; } -- 2.11.4.GIT