Merge pull request #2810 from kumpera/fix_hazard_free
[mono.git] / mono / mini / mini-exceptions.c
index c59c9ca2a5b0c060caa3f6d14a0e12a63ebf9d01..479aed2f41ab71ae43f465101c120d87934a2162 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc.
  * Copyright 2003-2008 Novell, Inc.
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -52,6 +53,7 @@
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/exception.h>
+#include <mono/metadata/exception-internals.h>
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/reflection-internals.h>
 #include <mono/metadata/gc-internals.h>
 #include "mini-llvm-cpp.h"
 #endif
 
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/mini/mini-exceptions.c"
-#endif
-
 #ifndef MONO_ARCH_CONTEXT_DEF
 #define MONO_ARCH_CONTEXT_DEF
 #endif
@@ -721,7 +719,10 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
        for (i = skip; i < len; i++) {
                MonoJitInfo *ji;
                MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
-               mono_error_raise_exception (&error);
+               if (!mono_error_ok (&error)) {
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               }
                gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
                gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
                MonoMethod *method;
@@ -750,7 +751,10 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
                }
                else {
                        MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, &error);
-                       mono_error_raise_exception (&error);
+                       if (!mono_error_ok (&error)) {
+                               mono_error_set_pending_exception (&error);
+                               return NULL;
+                       }
                        MONO_OBJECT_SETREF (sf, method, rm);
                }
 
@@ -1078,7 +1082,10 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
        }
 
        MonoReflectionMethod *rm = mono_method_get_object_checked (domain, actual_method, NULL, &error);
-       mono_error_raise_exception (&error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return FALSE;
+       }
        mono_gc_wbarrier_generic_store (method, (MonoObject*) rm);
 
        location = mono_debug_lookup_source_location (jmethod, *native_offset, domain);
@@ -1106,6 +1113,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
 static MonoClass*
 get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
 {
+       MonoError error;
        MonoClass *catch_class = ei->data.catch_class;
        MonoType *inflated_type;
        MonoGenericContext context;
@@ -1124,7 +1132,9 @@ get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContex
           when the exception is actually thrown, so as not to
           waste space for exception clauses which might never
           be encountered. */
-       inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
+       inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
+       mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
        catch_class = mono_class_from_mono_type (inflated_type);
        mono_metadata_free_type (inflated_type);
 
@@ -1189,6 +1199,9 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
        return mini_jit_info_table_find_ext (domain, addr, FALSE, out_domain);
 }
 
+/* Class lazy loading functions */
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_compat_attr, System.Runtime.CompilerServices, RuntimeCompatibilityAttribute)
+
 /*
  * wrap_non_exception_throws:
  *
@@ -1198,9 +1211,10 @@ mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domai
 static gboolean
 wrap_non_exception_throws (MonoMethod *m)
 {
+       MonoError error;
        MonoAssembly *ass = m->klass->image->assembly;
        MonoCustomAttrInfo* attrs;
-       static MonoClass *klass;
+       MonoClass *klass;
        int i;
        gboolean val = FALSE;
 
@@ -1208,9 +1222,10 @@ wrap_non_exception_throws (MonoMethod *m)
        if (ass->wrap_non_exception_throws_inited)
                return ass->wrap_non_exception_throws;
 
-       klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
+       klass = mono_class_get_runtime_compat_attr_class ();
 
-       attrs = mono_custom_attrs_from_assembly (ass);
+       attrs = mono_custom_attrs_from_assembly_checked (ass, &error);
+       mono_error_cleanup (&error); /* FIXME don't swallow the error */
        if (attrs) {
                for (i = 0; i < attrs->num_attrs; ++i) {
                        MonoCustomAttrEntry *attr = &attrs->attrs [i];
@@ -1330,6 +1345,7 @@ setup_stack_trace (MonoException *mono_ex, GSList *dynamic_methods, MonoArray *i
 static gboolean
 mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception)
 {
+       MonoError error;
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji = NULL;
        static int (*call_filter) (MonoContext *, gpointer) = NULL;
@@ -1355,10 +1371,11 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
        mono_ex = (MonoException*)obj;
        initial_trace_ips = mono_ex->trace_ips;
 
-       if (mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
                mono_ex = (MonoException*)obj;
                initial_trace_ips = mono_ex->trace_ips;
        } else {
+               mono_error_assert_ok (&error);
                mono_ex = NULL;
        }
 
@@ -1521,7 +1538,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
                                        }
                                }
 
-                               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
+                               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);
 
@@ -1532,6 +1549,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);
                        }
                }
 
@@ -1587,9 +1605,11 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                obj = (MonoObject *)mono_get_exception_null_reference ();
        }
 
-       if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
+               mono_error_assert_ok (&error);
                non_exception = obj;
-               obj = (MonoObject *)mono_get_exception_runtime_wrapped (obj);
+               obj = (MonoObject *)mono_get_exception_runtime_wrapped_checked (obj, &error);
+               mono_error_assert_ok (&error);
        }
 
        mono_ex = (MonoException*)obj;
@@ -1600,9 +1620,10 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        ;
        }
 
-       if (mono_object_isinst (obj, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (obj, mono_defaults.exception_class, &error)) {
                mono_ex = (MonoException*)obj;
        } else {
+               mono_error_assert_ok (&error);
                mono_ex = NULL;
        }
 
@@ -1813,8 +1834,9 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        filter_idx ++;
                                }
 
+                               mono_error_init (&error);
                                if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE && 
-                                        mono_object_isinst (ex_obj, catch_class)) || filtered) {
+                                    mono_object_isinst_checked (ex_obj, catch_class, &error)) || filtered) {
                                        /*
                                         * This guards against the situation that we abort a thread that is executing a finally clause
                                         * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
@@ -1865,6 +1887,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
 
                                        return 0;
                                }
+                               mono_error_cleanup (&error);
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
                                        if (mono_trace_is_enabled () && mono_trace_eval (method))
                                                g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (method, TRUE));
@@ -2374,8 +2397,8 @@ mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *i
        }
 #endif
  }
-#elif defined (ENABLE_EXTENSION_MODULE)
-       mono_extension_handle_native_sigsegv (ctx, info);
+#else
+       mono_exception_native_unwind (ctx, info);
 #endif
 
        /*
@@ -2859,11 +2882,15 @@ mono_jinfo_get_epilog_size (MonoJitInfo *ji)
 static void
 throw_exception (MonoObject *ex, gboolean rethrow)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoException *mono_ex;
 
-       if (!mono_object_isinst (ex, mono_defaults.exception_class))
-               mono_ex = mono_get_exception_runtime_wrapped (ex);
+       if (!mono_object_isinst_checked (ex, mono_defaults.exception_class, &error)) {
+               mono_error_assert_ok (&error);
+               mono_ex = mono_get_exception_runtime_wrapped_checked (ex, &error);
+               mono_error_assert_ok (&error);
+       }
        else
                mono_ex = (MonoException*)ex;
 
@@ -3000,6 +3027,7 @@ 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;
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoObject *exc;
        gint32 index = -1;
@@ -3020,16 +3048,21 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
 
                        g_assert (rgctx || this_obj);
                        context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
-                       inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
+                       inflated_type = mono_class_inflate_generic_type_checked (&catch_class->byval_arg, &context, &error);
+                       mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
                        catch_class = mono_class_from_mono_type (inflated_type);
                        mono_metadata_free_type (inflated_type);
                }
 
                // FIXME: Handle edge cases handled in get_exception_catch_class
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, catch_class)) {
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst_checked (exc, catch_class, &error)) {
                        index = ei->clause_index;
                        break;
-               } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+               } else
+                       mono_error_assert_ok (&error);
+               
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                        g_assert_not_reached ();
                }
        }