X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fexceptions-sparc.c;h=8d0f7af6e028df62ef06c0be025b23e0b95bf90b;hb=83bc684f2d1e634e50ac3725cb70d93c655eed84;hp=2213e8333d5b0b8e4eee4281b8a1e1d3435615f3;hpb=704ad2cf915397c4a6176bbddaa42eb5e51bba5f;p=mono.git diff --git a/mono/mini/exceptions-sparc.c b/mono/mini/exceptions-sparc.c index 2213e8333d5..8d0f7af6e02 100644 --- a/mono/mini/exceptions-sparc.c +++ b/mono/mini/exceptions-sparc.c @@ -1,5 +1,5 @@ /* - * exceptions-sparc.c: exception support for 64 bit sparc + * exceptions-sparc.c: exception support for sparc * * Authors: * Mark Crichton (crichton@gimp.org) @@ -22,6 +22,7 @@ #include #include #include +#include #include "mini.h" #include "mini-sparc.h" @@ -38,16 +39,20 @@ * Returns a pointer to a method which restores a previously saved sigcontext. */ gpointer -mono_arch_get_restore_context (void) +mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) { - static guint32 start [32]; + static guint32 *start; static int inited = 0; guint32 *code; + g_assert (!aot); + if (info) + *info = NULL; + if (inited) return start; - code = start; + code = start = mono_global_codeman_reserve (32 * sizeof (guint32)); sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, ip), sparc_i7); sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, sp), sparc_i6); @@ -58,6 +63,8 @@ mono_arch_get_restore_context (void) g_assert ((code - start) < 32); + mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start); + inited = 1; return start; @@ -73,17 +80,21 @@ mono_arch_get_restore_context (void) * call_filter (MonoContext *ctx, gpointer ip) */ gpointer -mono_arch_get_call_filter (void) +mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) { - static guint32 start [64]; + static guint32 *start; static int inited = 0; guint32 *code; int i; + g_assert (!aot); + if (info) + *info = NULL; + if (inited) return start; - code = start; + code = start = mono_global_codeman_reserve (64 * sizeof (guint32)); /* * There are two frames here: @@ -145,20 +156,22 @@ mono_arch_get_call_filter (void) g_assert ((code - start) < 64); + mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start); + inited = 1; return start; } static void -throw_exception (MonoObject *exc, gpointer sp, gpointer ip) +throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow) { MonoContext ctx; static void (*restore_context) (MonoContext *); gpointer *window; if (!restore_context) - restore_context = mono_arch_get_restore_context (); + restore_context = mono_get_restore_context (); window = MONO_SPARC_WINDOW_ADDR (sp); ctx.sp = (gpointer*)sp; @@ -167,7 +180,8 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip) if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; - mono_ex->stack_trace = NULL; + if (!rethrow) + mono_ex->stack_trace = NULL; } mono_handle_exception (&ctx, exc, ip, FALSE); restore_context (&ctx); @@ -175,61 +189,105 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip) g_assert_not_reached (); } +static gpointer +get_throw_exception (gboolean rethrow) +{ + guint32 *start, *code; + + code = start = mono_global_codeman_reserve (16 * sizeof (guint32)); + + sparc_save_imm (code, sparc_sp, -512, sparc_sp); + + sparc_flushw (code); + sparc_mov_reg_reg (code, sparc_i0, sparc_o0); + sparc_mov_reg_reg (code, sparc_fp, sparc_o1); + sparc_mov_reg_reg (code, sparc_i7, sparc_o2); + sparc_set (code, rethrow, sparc_o3); + sparc_set (code, throw_exception, sparc_o7); + sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite); + sparc_nop (code); + + g_assert ((code - start) <= 16); + + mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start); + + return start; +} + /** - * mono_arch_get_throw_exception_by_name: + * mono_arch_get_throw_exception: * * Returns a function pointer which can be used to raise exceptions. * The returned function has the following - * signature: void (*func) (char *exc_name); + * signature: void (*func) (MonoException *exc); */ -gpointer -mono_arch_get_throw_exception (void) +gpointer +mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - static guint32 start [32]; + static guint32* start; static int inited = 0; - guint32 *code; + + g_assert (!aot); + if (info) + *info = NULL; if (inited) return start; inited = 1; - code = start; - sparc_save_imm (code, sparc_sp, -512, sparc_sp); + start = get_throw_exception (FALSE); - sparc_flushw (code); - sparc_mov_reg_reg (code, sparc_i0, sparc_o0); - sparc_mov_reg_reg (code, sparc_fp, sparc_o1); - sparc_mov_reg_reg (code, sparc_i7, sparc_o2); - sparc_set (code, throw_exception, sparc_o7); - sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite); - sparc_nop (code); + return start; +} - g_assert ((code - start) < 32); +gpointer +mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) +{ + static guint32* start; + static int inited = 0; + + g_assert (!aot); + if (info) + *info = NULL; + + if (inited) + return start; + + inited = 1; + + start = get_throw_exception (TRUE); return start; } /** - * mono_arch_get_throw_exception_by_name: + * mono_arch_get_throw_corlib_exception: * * Returns a function pointer which can be used to raise * corlib exceptions. The returned function has the following - * signature: void (*func) (char *exc_name, gpointer ip); + * signature: void (*func) (guint32 ex_token, guint32 offset); + * Here, offset is the offset which needs to be substracted from the caller IP + * to get the IP of the throw. Passing the offset has the advantage that it + * needs no relocations in the caller. */ -gpointer -mono_arch_get_throw_exception_by_name (void) +gpointer +mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - static guint32 start [64]; + static guint32 *start; static int inited = 0; guint32 *code; int reg; + g_assert (!aot); + if (info) + *info = NULL; + if (inited) return start; inited = 1; - code = start; + code = start = mono_global_codeman_reserve (64 * sizeof (guint32)); #ifdef SPARCV9 reg = sparc_g4; @@ -237,29 +295,34 @@ mono_arch_get_throw_exception_by_name (void) reg = sparc_g1; #endif + sparc_mov_reg_reg (code, sparc_o7, sparc_o2); sparc_save_imm (code, sparc_sp, -160, sparc_sp); - sparc_mov_reg_reg (code, sparc_i0, sparc_o2); - sparc_set (code, mono_defaults.corlib, sparc_o0); - sparc_set (code, "System", sparc_o1); - sparc_set (code, mono_exception_from_name, sparc_o7); + sparc_set (code, MONO_TOKEN_TYPE_DEF, sparc_o7); + sparc_add (code, FALSE, sparc_i0, sparc_o7, sparc_o1); + sparc_set (code, mono_defaults.exception_class->image, sparc_o0); + sparc_set (code, mono_exception_from_token, sparc_o7); sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite); sparc_nop (code); /* Return to the caller, so exception handling does not see this frame */ sparc_restore (code, sparc_o0, sparc_g0, sparc_o0); - /* Put original return address into %o7 */ - sparc_mov_reg_reg (code, sparc_o1, sparc_o7); - sparc_set (code, mono_arch_get_throw_exception (), reg); + /* Compute throw ip */ + sparc_sll_imm (code, sparc_o1, 2, sparc_o1); + sparc_sub (code, 0, sparc_o2, sparc_o1, sparc_o7); + + sparc_set (code, mono_arch_get_throw_exception (NULL, FALSE), reg); /* Use a jmp instead of a call so o7 is preserved */ sparc_jmpl_imm (code, reg, 0, sparc_g0); sparc_nop (code); g_assert ((code - start) < 32); + mono_arch_flush_icache ((guint8*)start, (guint8*)code - (guint8*)start); + return start; -} +} /* mono_arch_find_jit_info: * @@ -270,30 +333,22 @@ mono_arch_get_throw_exception_by_name (void) * the @lmf if necessary. @native_offset return the IP offset from the * start of the function or -1 if that info is not available. */ -MonoJitInfo * -mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx, - MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset, - gboolean *managed) +gboolean +mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, + MonoJitInfo *ji, MonoContext *ctx, + MonoContext *new_ctx, MonoLMF **lmf, + mgreg_t **save_locations, + StackFrameInfo *frame) { - MonoJitInfo *ji; - gpointer ip = MONO_CONTEXT_GET_IP (ctx); gpointer *window; - /* Avoid costly table lookup during stack overflow */ - if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size))) - ji = prev_ji; - else - ji = mono_jit_info_table_find (domain, ip); + memset (frame, 0, sizeof (StackFrameInfo)); + frame->ji = ji; - if (managed) - *managed = FALSE; + *new_ctx = *ctx; if (ji != NULL) { - *new_ctx = *ctx; - - if (managed) - if (!ji->method->wrapper_type) - *managed = TRUE; + frame->type = FRAME_TYPE_MANAGED; if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) { /* remove any unused lmf */ @@ -306,24 +361,21 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf new_ctx->sp = (gpointer*)(window [sparc_i6 - 16]); new_ctx->fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (new_ctx->sp) [sparc_i6 - 16]); - *res = *ji; - return res; + return TRUE; } else { if (!(*lmf)) - return NULL; - - *new_ctx = *ctx; + return FALSE; if (!(*lmf)->method) - return (gpointer)-1; + return FALSE; - if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->ip))) { - *res = *ji; - } else { - memset (res, 0, sizeof (MonoJitInfo)); - res->method = (*lmf)->method; - } + ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->ip, NULL); + if (!ji) + return FALSE; + + frame->ji = ji; + frame->type = FRAME_TYPE_MANAGED_TO_NATIVE; new_ctx->ip = (*lmf)->ip; new_ctx->sp = (*lmf)->sp; @@ -331,16 +383,65 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf *lmf = (*lmf)->previous_lmf; - return res; + return TRUE; } } +#ifdef __linux__ + gboolean -mono_arch_has_unwind_info (gconstpointer addr) +mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) +{ + MonoContext mctx; + struct sigcontext *sc = sigctx; + gpointer *window; + +#ifdef SPARCV9 + mctx.ip = (gpointer) sc->sigc_regs.tpc; + mctx.sp = (gpointer) sc->sigc_regs.u_regs[14]; +#else + mctx.ip = (gpointer) sc->si_regs.pc; + mctx.sp = (gpointer) sc->si_regs.u_regs[14]; +#endif + + window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS); + mctx.fp = window [sparc_fp - 16]; + + mono_handle_exception (&mctx, obj, mctx.ip, test_only); + +#ifdef SPARCV9 + sc->sigc_regs.tpc = (unsigned long) mctx.ip; + sc->sigc_regs.tnpc = (unsigned long) (mctx.ip + 4); + sc->sigc_regs.u_regs[14] = (unsigned long) mctx.sp; +#else + sc->si_regs.pc = (unsigned long) mctx.ip; + sc->si_regs.npc = (unsigned long) (mctx.ip + 4); + sc->si_regs.u_regs[14] = (unsigned long) mctx.sp; +#endif + + window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS); + window [sparc_fp - 16] = mctx.fp; + + return TRUE; +} + +gpointer +mono_arch_ip_from_context (void *sigctx) { - return FALSE; + struct sigcontext *sc = sigctx; + gpointer *ret; + +#ifdef SPARCV9 + ret = (gpointer) sc->sigc_regs.tpc; +#else + ret = (gpointer) sc->si_regs.pc; +#endif + + return ret; } +#else /* !__linux__ */ + gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) { @@ -353,12 +454,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) * under documented under solaris. The code below seems to work under * Solaris 9. */ -#ifndef __linux__ g_assert (!ctx->uc_mcontext.gwins); -#else - /* better, but doesn't work all the time. need to rethink! */ - g_assert (!ctx->uc_mcontext.gregs); -#endif mctx.ip = ctx->uc_mcontext.gregs [REG_PC]; mctx.sp = ctx->uc_mcontext.gregs [REG_SP]; @@ -384,3 +480,4 @@ mono_arch_ip_from_context (void *sigctx) return (gpointer)ctx->uc_mcontext.gregs [REG_PC]; } +#endif