Add support for z13 processor
[mono.git] / mono / mini / exceptions-x86.c
index 778c5291a9613c53e6643b896a853edb819e67ef..5042fa5efd1629755101e2f9c443cfc48877ef26 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * exceptions-x86.c: exception support for x86
+/**
+ * \file
+ * exception support for x86
  *
  * Authors:
  *   Dietmar Maurer (dietmar@ximian.com)
@@ -23,7 +24,7 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/exception.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/utils/mono-mmap.h>
 
@@ -62,7 +63,7 @@ LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
        }
 #endif
 
-       mono_handle_native_sigsegv (SIGSEGV, NULL, NULL);
+       mono_handle_native_crash ("SIGSEGV", NULL, NULL);
 
        return EXCEPTION_CONTINUE_SEARCH;
 }
@@ -113,7 +114,7 @@ mono_win32_get_handle_stackoverflow (void)
        x86_ret (code);
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -138,7 +139,7 @@ win32_handle_stack_overflow (EXCEPTION_POINTERS* ep, struct sigcontext *sctx)
        DWORD page_size;
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo rji;
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        MonoLMF *lmf = jit_tls->lmf;            
        MonoContext initial_ctx;
        MonoContext ctx;
@@ -194,7 +195,7 @@ LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep)
        EXCEPTION_RECORD* er;
        CONTEXT* ctx;
        LONG res;
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
 
        /* If the thread is not managed by the runtime return early */
        if (!jit_tls)
@@ -348,8 +349,6 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
        /* jump to the saved IP */
        x86_ret (code);
 
-       nacl_global_codeman_validate(&start, 128, &code);
-
        if (info)
                *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
        else {
@@ -361,7 +360,7 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -380,7 +379,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        guint8 *code;
        MonoJumpInfo *ji = NULL;
        GSList *unwind_ops = NULL;
-       guint kMaxCodeSize = NACL_SIZE (64, 128);
+       guint kMaxCodeSize = 64;
 
        /* call_filter (MonoContext *ctx, unsigned long eip) */
        start = code = mono_global_codeman_reserve (kMaxCodeSize);
@@ -428,8 +427,6 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        x86_leave (code);
        x86_ret (code);
 
-       nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-
        if (info)
                *info = mono_tramp_info_create ("call_filter", start, code - start, ji, unwind_ops);
        else {
@@ -441,7 +438,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        g_assert ((code - start) < kMaxCodeSize);
        return start;
@@ -456,6 +453,7 @@ void
 mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, 
                                                  mgreg_t eip, gboolean rethrow)
 {
+       MonoError error;
        MonoContext ctx;
 
        ctx.esp = regs [X86_ESP];
@@ -473,13 +471,14 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
        g_assert ((ctx.esp % MONO_ARCH_FRAME_ALIGNMENT) == 0);
 #endif
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
 
        /* adjust eip so that it point into the call instruction */
        ctx.eip -= 1;
@@ -538,11 +537,11 @@ mono_x86_resume_unwind (mgreg_t *regs, MonoObject *exc,
 static guint8*
 get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, MonoTrampInfo **info, gboolean aot)
 {
-       guint8 *start, *code;
+       guint8 *start, *code, *labels [16];
        int i, stack_size, stack_offset, arg_offsets [5], regs_offset;
        MonoJumpInfo *ji = NULL;
        GSList *unwind_ops = NULL;
-       guint kMaxCodeSize = NACL_SIZE (128, 256);
+       guint kMaxCodeSize = 192;
 
        start = code = mono_global_codeman_reserve (kMaxCodeSize);
 
@@ -564,8 +563,7 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
         * <return addr> <- esp (unaligned on apple)
         */
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       unwind_ops = mono_arch_get_cie_program ();
 
        /* Alloc frame */
        x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size);
@@ -608,6 +606,18 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
        x86_lea_membase (code, X86_EAX, X86_ESP, stack_offset);
        x86_mov_membase_reg (code, X86_ESP, regs_offset + (X86_ESP * 4), X86_EAX, 4);
 
+       /* Clear fp stack */
+       labels [0] = code;
+       x86_fnstsw (code);
+       x86_shift_reg_imm (code, X86_SHR, X86_EAX, 11);
+       x86_alu_reg_imm (code, X86_AND, X86_EAX, 7);
+       x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0);
+       labels [1] = code;
+       x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+       x86_fstp (code, 0);
+       x86_jump_code (code, labels [0]);
+       mono_x86_patch (labels [1], code);
+
        /* Set arg1 == regs */
        x86_lea_membase (code, X86_EAX, X86_ESP, regs_offset);
        x86_mov_membase_reg (code, X86_ESP, arg_offsets [0], X86_EAX, 4);
@@ -653,8 +663,6 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
        }
        x86_breakpoint (code);
 
-       nacl_global_codeman_validate(&start, kMaxCodeSize, &code);
-
        g_assert ((code - start) < kMaxCodeSize);
 
        if (info)
@@ -668,15 +676,14 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
 
 /**
  * mono_arch_get_throw_exception:
- *
- * Returns a function pointer which can be used to raise 
+ * \returns a function pointer which can be used to raise 
  * exceptions. The returned function has the following 
  * signature: void (*func) (MonoException *exc); 
  * For example to raise an arithmetic exception you can use:
@@ -699,8 +706,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
 
 /**
  * mono_arch_get_throw_corlib_exception:
- *
- * Returns a function pointer which can be used to raise 
+ * \returns a function pointer which can be used to raise 
  * corlib exceptions. The returned function has the following 
  * signature: void (*func) (guint32 ex_token, guint32 offset); 
  * Here, offset is the offset which needs to be substracted from the caller IP 
@@ -717,6 +723,7 @@ void
 mono_arch_exceptions_init (void)
 {
        guint8 *tramp;
+       MonoTrampInfo *tinfo;
 
 /* 
  * If we're running WoW64, we need to set the usermode exception policy 
@@ -745,22 +752,28 @@ mono_arch_exceptions_init (void)
        }
 
        /* LLVM needs different throw trampolines */
-       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_rethrow_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, NULL, FALSE);
+       tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE);
        mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE);
+       mono_tramp_info_register (tinfo, NULL);
 
-       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (NULL, FALSE);
+       signal_exception_trampoline = mono_x86_get_signal_exception_trampoline (&tinfo, FALSE);
+       mono_tramp_info_register (tinfo, NULL);
 }
 
 /*
@@ -788,7 +801,10 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
@@ -884,7 +900,7 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
 gpointer
 mono_arch_ip_from_context (void *sigctx)
 {
-#if defined(__native_client__)
+#if defined(HOST_WATCHOS)
        printf("WARNING: mono_arch_ip_from_context() called!\n");
        return (NULL);
 #elif defined(MONO_ARCH_USE_SIGACTION)
@@ -906,7 +922,7 @@ mono_arch_ip_from_context (void *sigctx)
 static void
 handle_signal_exception (gpointer obj)
 {
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        MonoContext ctx;
 
        memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
@@ -931,11 +947,12 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
 
        start = code = mono_global_codeman_reserve (128);
 
+       /* FIXME no unwind before we push ip */
        /* Caller ip */
        x86_push_reg (code, X86_ECX);
 
-       mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
-       mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
+       mono_add_unwind_op_def_cfa (unwind_ops, code, start, X86_ESP, 4);
+       mono_add_unwind_op_offset (unwind_ops, code, start, X86_NREG, -4);
 
        /* Fix the alignment to be what apple expects */
        stack_size = 12;
@@ -961,7 +978,7 @@ mono_x86_get_signal_exception_trampoline (MonoTrampInfo **info, gboolean aot)
        }
 
        mono_arch_flush_icache (start, code - start);
-       mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
+       MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
 
        return start;
 }
@@ -997,7 +1014,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
         * 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);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
 
        /* Pass the ctx parameter in TLS */
        mono_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
@@ -1009,7 +1026,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
        return TRUE;
 #elif defined (TARGET_WIN32)
        MonoContext mctx;
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        struct sigcontext *ctx = (struct sigcontext *)sigctx;
 
        mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
@@ -1035,7 +1052,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj)
 static void
 restore_soft_guard_pages (void)
 {
-       MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+       MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
        if (jit_tls->stack_ovf_guard_base)
                mono_mprotect (jit_tls->stack_ovf_guard_base, jit_tls->stack_ovf_guard_size, MONO_MMAP_NONE);
 }
@@ -1094,7 +1111,7 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s
        if (stack_ovf)
                exc = mono_domain_get ()->stack_overflow_ex;
        if (!ji)
-               mono_handle_native_sigsegv (SIGSEGV, sigctx, siginfo);
+               mono_handle_native_crash ("SIGSEGV", sigctx, siginfo);
        /* setup a call frame on the real stack so that control is returned there
         * and exception handling can continue.
         * If this was a stack overflow the caller already ensured the stack pages
@@ -1133,17 +1150,16 @@ mono_tasklets_arch_restore (void)
        static guint8* saved = NULL;
        guint8 *code, *start;
 
-#ifdef __native_client_codegen__
-       g_print("mono_tasklets_arch_restore needs to be aligned for Native Client\n");
-#endif
        if (saved)
                return (MonoContinuationRestore)saved;
        code = start = mono_global_codeman_reserve (48);
        /* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */
        /* put cont in edx */
        x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4);
-        /* state in eax, so it's setup as the return value */
-        x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
+       /* state in eax, so it's setup as the return value */
+       x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
+       /* lmf_addr in ebx */
+       x86_mov_reg_membase(code, X86_EBX, X86_ESP, 0x0C, 4);
 
        /* setup the copy of the stack */
        x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4);
@@ -1156,10 +1172,8 @@ mono_tasklets_arch_restore (void)
 
        /* now restore the registers from the LMF */
        x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 4);
-       x86_mov_reg_membase (code, X86_EBX, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebx), 4);
        x86_mov_reg_membase (code, X86_EBP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebp), 4);
-       x86_mov_reg_membase (code, X86_ESI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esi), 4);
-       x86_mov_reg_membase (code, X86_EDI, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, edi), 4);
+       x86_mov_reg_membase (code, X86_ESP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esp), 4);
 
        /* restore the lmf chain */
        /*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4);