2006-06-21 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / exceptions-amd64.c
index 947aaacf09ab6f570376784cdccc5c88f16398e9..22c0f5f0250a36996144a69589acf4ac3f79d493 100644 (file)
@@ -264,12 +264,23 @@ throw_exception (MonoObject *exc, guint64 rip, guint64 rsp,
        ctx.r14 = r14;
        ctx.r15 = r15;
 
-       if (mono_debugger_throw_exception ((gpointer)(rip - 8), (gpointer)rsp, exc)) {
+       if (!rethrow && mono_debugger_throw_exception ((gpointer)(rip - 8), (gpointer)rsp, exc)) {
                /*
                 * The debugger wants us to stop on the `throw' instruction.
                 * By the time we get here, it already inserted a breakpoint on
                 * eip - 8 (which is the address of the `mov %r15,%rdi ; callq throw').
                 */
+
+               /* FIXME FIXME
+                *
+                * In case of a rethrow, the JIT is emitting code like this:
+                *
+                *    mov    0xffffffffffffffd0(%rbp),%rax'
+                *    mov    %rax,%rdi
+                *    callq  throw
+                *
+                * Here, restore_context() wouldn't restore the %rax register correctly.
+                */
                ctx.rip = rip - 8;
                ctx.rsp = rsp + 8;
                restore_context (&ctx);
@@ -470,6 +481,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
 
        if (ji != NULL) {
                int offset;
+               gboolean omit_fp = (ji->used_regs & (1 << 31)) > 0;
 
                *new_ctx = *ctx;
 
@@ -487,8 +499,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                         * We only need to do this if the exception was raised in managed
                         * code, since otherwise the lmf was already popped of the stack.
                         */
-                       if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+                       if (*lmf && ((*lmf) != jit_tls->first_lmf) && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp)) {
+                               new_ctx->rbp = (*lmf)->ebp;
                                new_ctx->rbx = (*lmf)->rbx;
+                               new_ctx->rsp = (*lmf)->rsp;
                                new_ctx->r12 = (*lmf)->r12;
                                new_ctx->r13 = (*lmf)->r13;
                                new_ctx->r14 = (*lmf)->r14;
@@ -496,12 +510,21 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                        }
                }
                else {
-                       offset = -1;
+                       offset = omit_fp ? 0 : -1;
                        /* restore caller saved registers */
                        for (i = 0; i < AMD64_NREG; i ++)
                                if (AMD64_IS_CALLEE_SAVED_REG (i) && (ji->used_regs & (1 << i))) {
-                                       guint64 reg = *((guint64 *)ctx->SC_EBP + offset);
-                                       offset --;
+                                       guint64 reg;
+
+                                       if (omit_fp) {
+                                               reg = *((guint64*)ctx->rsp + offset);
+                                               offset ++;
+                                       }
+                                       else {
+                                               reg = *((guint64 *)ctx->SC_EBP + offset);
+                                               offset --;
+                                       }
+
                                        switch (i) {
                                        case AMD64_RBX:
                                                new_ctx->rbx = reg;
@@ -518,22 +541,34 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                                        case AMD64_R15:
                                                new_ctx->r15 = reg;
                                                break;
+                                       case AMD64_RBP:
+                                               new_ctx->rbp = reg;
+                                               break;
                                        default:
                                                g_assert_not_reached ();
                                        }
                                }
                }
 
-               if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
+               if (*lmf && ((*lmf) != jit_tls->first_lmf) && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp)) {
                        /* remove any unused lmf */
                        *lmf = (*lmf)->previous_lmf;
                }
 
-               /* Pop EBP and the return address */
-               new_ctx->SC_ESP = ctx->SC_EBP + (2 * sizeof (gpointer));
-               /* we substract 1, so that the IP points into the call instruction */
-               new_ctx->SC_EIP = *((guint64 *)ctx->SC_EBP + 1) - 1;
-               new_ctx->SC_EBP = *((guint64 *)ctx->SC_EBP);
+               if (omit_fp) {
+                       /* Pop frame */
+                       new_ctx->rsp += (ji->used_regs >> 16) & (0x7fff);
+                       new_ctx->SC_EIP = *((guint64 *)new_ctx->rsp) - 1;
+                       /* Pop return address */
+                       new_ctx->rsp += 8;
+               }
+               else {
+                       /* Pop EBP and the return address */
+                       new_ctx->SC_ESP = ctx->SC_EBP + (2 * sizeof (gpointer));
+                       /* we substract 1, so that the IP points into the call instruction */
+                       new_ctx->SC_EIP = *((guint64 *)ctx->SC_EBP + 1) - 1;
+                       new_ctx->SC_EBP = *((guint64 *)ctx->SC_EBP);
+               }
 
                /* Pop arguments off the stack */
                {
@@ -559,6 +594,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
 
                new_ctx->SC_RIP = (*lmf)->rip;
                new_ctx->SC_RBP = (*lmf)->ebp;
+               new_ctx->SC_ESP = (*lmf)->rsp;
 
                new_ctx->SC_RBX = (*lmf)->rbx;
                new_ctx->SC_R12 = (*lmf)->r12;
@@ -566,10 +602,6 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                new_ctx->SC_R14 = (*lmf)->r14;
                new_ctx->SC_R15 = (*lmf)->r15;
 
-               /* the lmf is always stored on the stack, so the following
-                * expression points to a stack location which can be used as ESP */
-               new_ctx->SC_ESP = ALIGN_TO ((guint64)&((*lmf)->rip), 16);
-
                *lmf = (*lmf)->previous_lmf;
 
                return ji ? ji : res;