Extract the code to emit a memory barrier. Add a memory_barrier_kind field to MonoIns...
[mono.git] / mono / mini / exceptions-amd64.c
index d6c45d9bb02973068d919c0f3fa60e26b0a60426..a8eb9328a4de6adaf9f2f6748aeaac4ff221841e 100644 (file)
@@ -38,10 +38,12 @@ static MonoW32ExceptionHandler fpe_handler;
 static MonoW32ExceptionHandler ill_handler;
 static MonoW32ExceptionHandler segv_handler;
 
-static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
+LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter;
+guint64 mono_win_chained_exception_filter_result;
+gboolean mono_win_chained_exception_filter_didrun;
 
 #define W32_SEH_HANDLE_EX(_ex) \
-       if (_ex##_handler) _ex##_handler(0, er, sctx)
+       if (_ex##_handler) _ex##_handler(0, ep, sctx)
 
 /*
  * Unhandled Exception Filter
@@ -54,6 +56,7 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep)
        MonoContext* sctx;
        LONG res;
 
+       mono_win_chained_exception_filter_didrun = FALSE;
        res = EXCEPTION_CONTINUE_EXECUTION;
 
        er = ep->ExceptionRecord;
@@ -114,17 +117,20 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep)
 
        g_free (sctx);
 
+       if (mono_win_chained_exception_filter_didrun)
+               res = mono_win_chained_exception_filter_result;
+
        return res;
 }
 
 void win32_seh_init()
 {
-       old_handler = SetUnhandledExceptionFilter(seh_handler);
+       mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_handler);
 }
 
 void win32_seh_cleanup()
 {
-       if (old_handler) SetUnhandledExceptionFilter(old_handler);
+       if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter);
 }
 
 void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)
@@ -197,9 +203,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
        /* jump to the saved IP */
        amd64_jump_reg (code, AMD64_R11);
 
-#if defined(__native_client_codegen__) && defined(__native_client__)
        nacl_global_codeman_validate(&start, 256, &code);
-#endif
 
        mono_arch_flush_icache (start, code - start);
 
@@ -286,9 +290,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < kMaxCodeSize);
 
-#if defined(__native_client_codegen__) && defined(__native_client__)
        nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-#endif
 
        mono_arch_flush_icache (start, code - start);
 
@@ -335,10 +337,9 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin
        }
 
        if (mono_debug_using_mono_debugger ()) {
-               guint8 buf [16], *code;
+               guint8 buf [16];
 
                mono_breakpoint_clean_code (NULL, (gpointer)rip, 8, buf, sizeof (buf));
-               code = buf + 8;
 
                if (buf [3] == 0xe8) {
                        MonoContext ctx_cp = ctx;
@@ -418,13 +419,19 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
        guint8 *code;
        MonoJumpInfo *ji = NULL;
        GSList *unwind_ops = NULL;
-       int i, stack_size, arg_offsets [16], regs_offset;
+       int i, stack_size, arg_offsets [16], regs_offset, dummy_stack_space;
        const guint kMaxCodeSize = NACL_SIZE (256, 512);
 
+#ifdef TARGET_WIN32
+       dummy_stack_space = 6 * sizeof(mgreg_t);        /* Windows expects stack space allocated for all 6 dummy args. */
+#else
+       dummy_stack_space = 0;
+#endif
+
        start = code = mono_global_codeman_reserve (kMaxCodeSize);
 
        /* The stack is unaligned on entry */
-       stack_size = 192 + 8;
+       stack_size = 192 + 8 + dummy_stack_space;
 
        code = start;
 
@@ -441,38 +448,38 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
         * the stack by passing 6 dummy values in registers.
         */
 
-       arg_offsets [0] = 0;
-       arg_offsets [1] = SIZEOF_REGISTER;
-       arg_offsets [2] = SIZEOF_REGISTER * 2;
-       arg_offsets [3] = SIZEOF_REGISTER * 3;
-       regs_offset = SIZEOF_REGISTER * 4;
+       arg_offsets [0] = dummy_stack_space + 0;
+       arg_offsets [1] = dummy_stack_space + sizeof(mgreg_t);
+       arg_offsets [2] = dummy_stack_space + sizeof(mgreg_t) * 2;
+       arg_offsets [3] = dummy_stack_space + sizeof(mgreg_t) * 3;
+       regs_offset = dummy_stack_space + sizeof(mgreg_t) * 4;
 
        /* Save registers */
        for (i = 0; i < AMD64_NREG; ++i)
                if (i != AMD64_RSP)
-                       amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (i * SIZEOF_REGISTER), i, SIZEOF_REGISTER);
+                       amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (i * sizeof(mgreg_t)), i, sizeof(mgreg_t));
        /* Save RSP */
-       amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + SIZEOF_REGISTER);
-       amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * SIZEOF_REGISTER), X86_EAX, SIZEOF_REGISTER);
+       amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, stack_size + sizeof(mgreg_t));
+       amd64_mov_membase_reg (code, AMD64_RSP, regs_offset + (AMD64_RSP * sizeof(mgreg_t)), X86_EAX, sizeof(mgreg_t));
        /* Set arg1 == regs */
        amd64_lea_membase (code, AMD64_RAX, AMD64_RSP, regs_offset);
-       amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [0], AMD64_RAX, SIZEOF_REGISTER);
+       amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [0], AMD64_RAX, sizeof(mgreg_t));
        /* Set arg2 == eip */
        if (llvm_abs)
                amd64_alu_reg_reg (code, X86_XOR, AMD64_RAX, AMD64_RAX);
        else
-               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, SIZEOF_REGISTER);
-       amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [1], AMD64_RAX, SIZEOF_REGISTER);
+               amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, stack_size, sizeof(mgreg_t));
+       amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [1], AMD64_RAX, sizeof(mgreg_t));
        /* Set arg3 == exc/ex_token_index */
        if (resume_unwind)
-               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, SIZEOF_REGISTER);
+               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], 0, sizeof(mgreg_t));
        else
-               amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG1, SIZEOF_REGISTER);
+               amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG1, sizeof(mgreg_t));
        /* Set arg4 == rethrow/pc offset */
        if (resume_unwind) {
-               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], 0, SIZEOF_REGISTER);
+               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], 0, sizeof(mgreg_t));
        } else if (corlib) {
-               amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [3], AMD64_ARG_REG2, SIZEOF_REGISTER);
+               amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [3], AMD64_ARG_REG2, sizeof(mgreg_t));
                if (llvm_abs)
                        /* 
                         * The caller is LLVM code which passes the absolute address not a pc offset,
@@ -481,14 +488,14 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
                         */
                        amd64_neg_membase (code, AMD64_RSP, arg_offsets [3]);
        } else {
-               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], rethrow, SIZEOF_REGISTER);
+               amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], rethrow, sizeof(mgreg_t));
        }
 
        if (aot) {
                ji = mono_patch_info_list_prepend (ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, corlib ? "mono_amd64_throw_corlib_exception" : "mono_amd64_throw_exception");
                amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
        } else {
-               amd64_mov_reg_imm (code, AMD64_R11, resume_unwind ? (mono_amd64_resume_unwind) : (corlib ? (gpointer)mono_amd64_throw_corlib_exception : (gpointer)mono_amd64_throw_exception));
+               amd64_mov_reg_imm (code, AMD64_R11, resume_unwind ? ((gpointer)mono_amd64_resume_unwind) : (corlib ? (gpointer)mono_amd64_throw_corlib_exception : (gpointer)mono_amd64_throw_exception));
        }
        amd64_call_reg (code, AMD64_R11);
        amd64_breakpoint (code);
@@ -497,9 +504,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
 
        g_assert ((code - start) < kMaxCodeSize);
 
-#if defined(__native_client_codegen__) && defined(__native_client__)
        nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-#endif
 
        if (info)
                *info = mono_tramp_info_create (g_strdup (tramp_name), start, code - start, ji, unwind_ops);
@@ -554,14 +559,14 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
 gboolean
 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, 
                                                         MonoJitInfo *ji, MonoContext *ctx, 
-                                                        MonoContext *new_ctx, MonoLMF **lmf, 
+                                                        MonoContext *new_ctx, MonoLMF **lmf,
+                                                        mgreg_t **save_locations,
                                                         StackFrameInfo *frame)
 {
        gpointer ip = MONO_CONTEXT_GET_IP (ctx);
 
        memset (frame, 0, sizeof (StackFrameInfo));
        frame->ji = ji;
-       frame->managed = FALSE;
 
        *new_ctx = *ctx;
 
@@ -573,13 +578,13 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
 
                frame->type = FRAME_TYPE_MANAGED;
 
-               if (!ji->method->wrapper_type || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
-                       frame->managed = TRUE;
-
                if (ji->from_aot)
                        unwind_info = mono_aot_get_unwind_info (ji, &unwind_info_len);
                else
                        unwind_info = mono_get_cached_unwind_info (ji->used_regs, &unwind_info_len);
+
+               frame->unwind_info = unwind_info;
+               frame->unwind_info_len = unwind_info_len;
  
                regs [AMD64_RAX] = new_ctx->rax;
                regs [AMD64_RBX] = new_ctx->rbx;
@@ -597,7 +602,8 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
 
                mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start, 
                                                   (guint8*)ji->code_start + ji->code_size,
-                                                  ip, regs, MONO_MAX_IREGS + 1, &cfa);
+                                                  ip, regs, MONO_MAX_IREGS + 1, 
+                                                  save_locations, MONO_MAX_IREGS, &cfa);
 
                new_ctx->rax = regs [AMD64_RAX];
                new_ctx->rbx = regs [AMD64_RBX];
@@ -667,7 +673,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
                         * The rsp field is set just before the call which transitioned to native 
                         * code. Obtain the rip from the stack.
                         */
-                       rip = *(guint64*)((*lmf)->rsp - SIZEOF_REGISTER);
+                       rip = *(guint64*)((*lmf)->rsp - sizeof(mgreg_t));
                }
 
                ji = mini_jit_info_table_find (domain, (gpointer)rip, NULL);
@@ -1088,9 +1094,7 @@ mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean aot)
 
        g_assert ((code - start) < kMaxCodeSize);
 
-#if defined(__native_client_codegen__) && defined(__native_client__)
        nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-#endif
 
        if (info)
                *info = mono_tramp_info_create (g_strdup_printf ("throw_pending_exception"), start, code - start, ji, unwind_ops);
@@ -1479,9 +1483,9 @@ mono_tasklets_arch_restore (void)
        /* state is already in rax */
        amd64_jump_membase (code, cont_reg, G_STRUCT_OFFSET (MonoContinuation, return_ip));
        g_assert ((code - start) <= kMaxCodeSize);
-#if defined(__native_client_codegen__) && defined(__native_client__)
+
        nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-#endif
+
        saved = start;
        return (MonoContinuationRestore)saved;
 }