GC Bridge: Make merge_cache more aggressive, less exact, faster
[mono.git] / mono / mini / mini-exceptions.c
index 46a12c45677b5339236d4dd1f77893f92cee68fe..d16cee8cee3daa00962ced9e1ed97a12959fc445 100644 (file)
@@ -89,9 +89,6 @@ static gpointer throw_corlib_exception_func;
 static gpointer try_more_restore_tramp = NULL;
 static gpointer restore_stack_protection_tramp = NULL;
 
-static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
-static gpointer unhandled_exception_hook_data = NULL;
-
 static void try_more_restore (void);
 static void restore_stack_protection (void);
 static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data);
@@ -671,6 +668,8 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
 gboolean
 mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = mono_domain_get ();
        MonoArray *ta = ex->trace_ips;
        int len, i;
@@ -1551,6 +1550,8 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
                                        }
                                }
 
+                               MonoError isinst_error;
+                               mono_error_init (&isinst_error);
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (ex_obj, catch_class, &error)) {
                                        setup_stack_trace (mono_ex, dynamic_methods, initial_trace_ips, &trace_ips);
                                        g_slist_free (dynamic_methods);
@@ -1562,7 +1563,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
                                        MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
                                        return TRUE;
                                }
-                               mono_error_cleanup (&error);
+                               mono_error_cleanup (&isinst_error);
                        }
                }
 
@@ -1695,7 +1696,15 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                mono_error_assert_ok (&error);
                        }
                        if (msg == NULL) {
-                               msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
+                               if (message) {
+                                       msg = mono_string_to_utf8_checked ((MonoString *) message, &error);
+                                       if (!is_ok (&error)) {
+                                               mono_error_cleanup (&error);
+                                               msg = g_strdup ("(error while display System.Exception.Message property)");
+                                       }
+                               } else {
+                                       msg = g_strdup ("(System.Exception.Message property not available)");
+                               }
                        }
                        g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)mono_native_thread_id_get (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
                        g_free (msg);
@@ -2475,9 +2484,6 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
 #endif
        GString* text;
        char *name;
-#ifndef HOST_WIN32
-       char *wapi_desc;
-#endif
        GError *error = NULL;
 
        if (!thread)
@@ -2495,11 +2501,9 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
        else
                g_string_append (text, "\n\"<unnamed thread>\"");
 
-#ifndef HOST_WIN32
-       wapi_desc = wapi_current_thread_desc ();
-       g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
-       free (wapi_desc);
-#endif
+       g_string_append_printf (text, " tid=0x%p this=0x%p ", (gpointer)(gsize)thread->tid, thread);
+       mono_thread_info_describe ((MonoThreadInfo*) thread->thread_info, text);
+       g_string_append (text, "\n");
 
 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
        if (start_ctx) {
@@ -2633,7 +2637,6 @@ install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
 
 /*
  * Finds the bottom handler block running and install a block guard if needed.
- * FIXME add full-aot support.
  */
 gboolean
 mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
@@ -2642,9 +2645,10 @@ mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
        MonoJitTlsData *jit_tls = (MonoJitTlsData *)ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
        gpointer resume_ip;
 
-       /* FIXME */
+#ifndef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD_AOT
        if (mono_aot_only)
                return FALSE;
+#endif
 
        /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
          * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
@@ -2812,49 +2816,6 @@ mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpoint
 #endif
 }
 
-void
-mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
-{
-       unhandled_exception_hook = func;
-       unhandled_exception_hook_data = user_data;
-}
-
-void
-mono_invoke_unhandled_exception_hook (MonoObject *exc)
-{
-       if (unhandled_exception_hook) {
-               unhandled_exception_hook (exc, unhandled_exception_hook_data);
-       } else {
-               MonoObject *other = NULL;
-               MonoString *str = mono_object_to_string (exc, &other);
-               char *msg = NULL;
-               
-               if (str)
-                       msg = mono_string_to_utf8 (str);
-               else if (other) {
-                       char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
-                       char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
-
-                       msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
-                               original_backtrace, nested_backtrace);
-
-                       g_free (original_backtrace);
-                       g_free (nested_backtrace);
-               } else {
-                       msg = g_strdup ("Nested exception trying to figure out what went wrong");
-               }
-               mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
-               g_free (msg);
-#if defined(HOST_IOS)
-               g_assertion_message ("Terminating runtime due to unhandled exception");
-#else
-               exit (mono_environment_exitcode_get ());
-#endif
-       }
-
-       g_assert_not_reached ();
-}
-
 /*
  * mono_restore_context:
  *
@@ -2903,6 +2864,8 @@ mono_jinfo_get_epilog_size (MonoJitInfo *ji)
 static void
 throw_exception (MonoObject *ex, gboolean rethrow)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoError error;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoException *mono_ex;
@@ -2911,6 +2874,7 @@ throw_exception (MonoObject *ex, gboolean rethrow)
                mono_error_assert_ok (&error);
                mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
                mono_error_assert_ok (&error);
+               jit_tls->thrown_non_exc = mono_gchandle_new (ex, FALSE);
        }
        else
                mono_ex = (MonoException*)ex;
@@ -2990,7 +2954,7 @@ mono_llvm_resume_exception (void)
 MonoObject *
 mono_llvm_load_exception (void)
 {
-               MonoError error;
+       MonoError error;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
 
        MonoException *mono_ex = (MonoException*)mono_gchandle_get_target (jit_tls->thrown_exc);
@@ -3042,6 +3006,9 @@ mono_llvm_clear_exception (void)
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        mono_gchandle_free (jit_tls->thrown_exc);
        jit_tls->thrown_exc = 0;
+       if (jit_tls->thrown_non_exc)
+               mono_gchandle_free (jit_tls->thrown_non_exc);
+       jit_tls->thrown_non_exc = 0;
 
        mono_memory_barrier ();
 }
@@ -3055,13 +3022,22 @@ mono_llvm_clear_exception (void)
 gint32
 mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
 {
-                       MonoError error;
+       MonoError error;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoObject *exc;
        gint32 index = -1;
 
        g_assert (jit_tls->thrown_exc);
        exc = mono_gchandle_get_target (jit_tls->thrown_exc);
+       if (jit_tls->thrown_non_exc) {
+               /*
+                * Have to unwrap RuntimeWrappedExceptions if the
+                * method's assembly doesn't have a RuntimeCompatibilityAttribute.
+                */
+               if (!wrap_non_exception_throws (jinfo_get_method (jinfo)))
+                       exc = mono_gchandle_get_target (jit_tls->thrown_non_exc);
+       }
+
        for (int i = 0; i < jinfo->num_clauses; i++) {
                MonoJitExceptionInfo *ei = &jinfo->clauses [i];
                MonoClass *catch_class;
@@ -3070,7 +3046,7 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
                        continue;
 
                catch_class = ei->data.catch_class;
-               if (catch_class->byval_arg.type == MONO_TYPE_VAR || catch_class->byval_arg.type == MONO_TYPE_MVAR || catch_class->byval_arg.type == MONO_TYPE_GENERICINST) {
+               if (mono_class_is_open_constructed_type (&catch_class->byval_arg)) {
                        MonoGenericContext context;
                        MonoType *inflated_type;