Merge pull request #3100 from lambdageek/dev/monoerror-exns
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 6 Jun 2016 18:39:05 +0000 (14:39 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 6 Jun 2016 18:39:05 +0000 (14:39 -0400)
[runtime] Pass MonoError to exception creation utilities

1  2 
mono/metadata/appdomain.c
mono/metadata/object.c
mono/mini/jit-icalls.c

index 32f0c9fd7b2a28bdd7c1d0c4059c7246386e8f04,395b09f57c81db217170305de5398fc40a3f1458..eb3f68204036d2f79ab525c3995a8a3a689867e4
@@@ -39,6 -39,7 +39,7 @@@
  #include "mono/metadata/metadata-internals.h"
  #include <mono/metadata/assembly.h>
  #include <mono/metadata/exception.h>
+ #include <mono/metadata/exception-internals.h>
  #include <mono/metadata/threads.h>
  #include <mono/metadata/threadpool-ms.h>
  #include <mono/metadata/socket-io.h>
@@@ -81,7 -82,7 +82,7 @@@
   * Changes which are already detected at runtime, like the addition
   * of icalls, do not require an increment.
   */
 -#define MONO_CORLIB_VERSION 148
 +#define MONO_CORLIB_VERSION 149
  
  typedef struct
  {
@@@ -189,16 -190,19 +190,19 @@@ create_domain_objects (MonoDomain *doma
         * Create an instance early since we can't do it when there is no memory.
         */
        arg = mono_string_new (domain, "Out of memory");
-       domain->out_of_memory_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL);
+       domain->out_of_memory_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL, &error);
+       mono_error_assert_ok (&error);
  
        /* 
         * These two are needed because the signal handlers might be executing on
         * an alternate stack, and Boehm GC can't handle that.
         */
        arg = mono_string_new (domain, "A null value was found where an object instance was required");
-       domain->null_reference_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL);
+       domain->null_reference_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL, &error);
+       mono_error_assert_ok (&error);
        arg = mono_string_new (domain, "The requested operation caused a stack overflow.");
-       domain->stack_overflow_ex = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL);
+       domain->stack_overflow_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL, &error);
+       mono_error_assert_ok (&error);
  
        /*The ephemeron tombstone i*/
        domain->ephemeron_tombstone = mono_object_new_checked (domain, mono_defaults.object_class, &error);
diff --combined mono/metadata/object.c
index b738649f88d7555d00b14a133773ea1bdd411ea8,491f614cbd07f85357b12688f5a3564dc6e127dd..c9ed5ebe1e8572240f3025476c134e47cf805906
@@@ -47,7 -47,6 +47,7 @@@
  #include <mono/utils/mono-memory-model.h>
  #include <mono/utils/checked-build.h>
  #include <mono/utils/mono-threads.h>
 +#include <mono/utils/mono-threads-coop.h>
  #include "cominterop.h"
  
  static void
@@@ -2946,8 -2945,12 +2946,8 @@@ do_runtime_invoke (MonoMethod *method, 
        if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
                mono_profiler_method_start_invoke (method);
  
 -      MONO_ENTER_GC_UNSAFE;
 -
        result = callbacks.runtime_invoke (method, obj, params, exc, error);
  
 -      MONO_EXIT_GC_UNSAFE;
 -
        if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
                mono_profiler_method_end_invoke (method);
  
@@@ -4891,7 -4894,7 +4891,7 @@@ mono_runtime_invoke_array (MonoMethod *
                }
        } else {
                MonoObject *result = mono_runtime_try_invoke_array (method, obj, params, NULL, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
                return result;
        }
  }
@@@ -6813,48 -6816,6 +6813,48 @@@ mono_ldstr_metadata_sig (MonoDomain *do
        return interned;
  }
  
 +/*
 + * mono_ldstr_utf8:
 + *
 + *   Same as mono_ldstr, but return a NULL terminated utf8 string instead
 + * of an object.
 + */
 +char*
 +mono_ldstr_utf8 (MonoImage *image, guint32 idx, MonoError *error)
 +{
 +      const char *str;
 +      size_t len2;
 +      long written = 0;
 +      char *as;
 +      GError *gerror = NULL;
 +
 +      mono_error_init (error);
 +
 +      if (!mono_verifier_verify_string_signature (image, idx, NULL))
 +              return NULL; /*FIXME we should probably be raising an exception here*/
 +      str = mono_metadata_user_string (image, idx);
 +
 +      len2 = mono_metadata_decode_blob_size (str, &str);
 +      len2 >>= 1;
 +
 +      as = g_utf16_to_utf8 ((guint16*)str, len2, NULL, &written, &gerror);
 +      if (gerror) {
 +              mono_error_set_argument (error, "string", "%s", gerror->message);
 +              g_error_free (gerror);
 +              return NULL;
 +      }
 +      /* g_utf16_to_utf8  may not be able to complete the convertion (e.g. NULL values were found, #335488) */
 +      if (len2 > written) {
 +              /* allocate the total length and copy the part of the string that has been converted */
 +              char *as2 = (char *)g_malloc0 (len2);
 +              memcpy (as2, as, written);
 +              g_free (as);
 +              as = as2;
 +      }
 +
 +      return as;
 +}
 +
  /**
   * mono_string_to_utf8:
   * @s: a System.String
diff --combined mono/mini/jit-icalls.c
index e648c4128ce088a982b7ed81bd18c3557be1efe0,1735b3cc979f4fb9388e866b40d3695282076d08..8651aa25ec497c574a6d492e6ae6e9b324be8e14
@@@ -19,6 -19,7 +19,7 @@@
  
  #include "jit-icalls.h"
  #include <mono/utils/mono-error-internals.h>
+ #include <mono/metadata/exception-internals.h>
  #include <mono/metadata/threads-types.h>
  #include <mono/metadata/reflection-internals.h>
  
@@@ -1189,13 -1190,21 +1190,21 @@@ mono_create_corlib_exception_0 (guint3
  MonoException *
  mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
  {
-       return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
+       MonoError error;
+       MonoException *ret = mono_exception_from_token_two_strings_checked (
+               mono_defaults.corlib, token, arg, NULL, &error);
+       mono_error_set_pending_exception (&error);
+       return ret;
  }
  
  MonoException *
  mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
  {
-       return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
+       MonoError error;
+       MonoException *ret = mono_exception_from_token_two_strings_checked (
+               mono_defaults.corlib, token, arg1, arg2, &error);
+       mono_error_set_pending_exception (&error);
+       return ret;
  }
  
  MonoObject*
@@@ -1487,15 -1496,15 +1496,15 @@@ mono_fill_method_rgctx (MonoMethodRunti
   * out parameter.
   */
  static gpointer
 -resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt)
 +resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt, MonoError *error)
  {
 -      MonoError error;
        MonoVTable *vt;
        gpointer *imt, *vtable_slot;
        MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
        gpointer addr, compiled_method, aot_addr;
        gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
  
 +      mono_error_init (error);
        if (!this_obj)
                /* The caller will handle it */
                return NULL;
        vt = this_obj->vtable;
        imt = (gpointer*)vt - MONO_IMT_SIZE;
  
 -      vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface);
 +      vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface, error);
 +      return_val_if_nok (error, NULL);
  
        // FIXME: This can throw exceptions
 -      addr = compiled_method = mono_compile_method_checked (impl_method, &error);
 -      mono_error_assert_ok (&error);
 +      addr = compiled_method = mono_compile_method_checked (impl_method, error);
 +      mono_error_assert_ok (error);
        g_assert (addr);
  
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
  gpointer
  mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
  {
 -      return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE);
 +      MonoError error;
 +      gpointer res = resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE, &error);
 +      if (!is_ok (&error)) {
 +              MonoException *ex = mono_error_convert_to_exception (&error);
 +              mono_llvm_throw_exception ((MonoObject*)ex);
 +      }
 +      return res;
  }
  
  static gboolean
@@@ -1573,18 -1575,18 +1582,18 @@@ is_generic_method_definition (MonoMetho
   * out parameter.
   */
  static gpointer
 -resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt)
 +resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt, MonoError *error)
  {
 -      MonoError error;
        MonoMethod *m, *generic_virtual = NULL;
        gpointer addr, compiled_method;
        gboolean need_unbox_tramp = FALSE;
  
 +      mono_error_init (error);
        /* Same as in common_call_trampoline () */
  
        /* Avoid loading metadata or creating a generic vtable if possible */
 -      addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, &error);
 -      mono_error_raise_exception (&error); // FIXME: Don't raise here
 +      addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, error);
 +      return_val_if_nok (error, NULL);
        if (addr && !vt->klass->valuetype)
                return mono_create_ftnptr (mono_domain_get (), addr);
  
                g_assert (generic_virtual->is_inflated);
                context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
  
 -              m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
 -              mono_error_assert_ok (&error); /* FIXME don't swallow the error */
 +              m = mono_class_inflate_generic_method_checked (declaring, &context, error);
 +              mono_error_assert_ok (error); /* FIXME don't swallow the error */
        }
  
        if (generic_virtual) {
        }
  
        // FIXME: This can throw exceptions
 -      addr = compiled_method = mono_compile_method_checked (m, &error);
 -      mono_error_assert_ok (&error);
 +      addr = compiled_method = mono_compile_method_checked (m, error);
 +      mono_error_assert_ok (error);
        g_assert (addr);
  
        addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
@@@ -1645,13 -1647,7 +1654,13 @@@ mono_resolve_vcall_gsharedvt (MonoObjec
  {
        g_assert (this_obj);
  
 -      return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE);
 +      MonoError error;
 +      gpointer result = resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE, &error);
 +      if (!is_ok (&error)) {
 +              MonoException *ex = mono_error_convert_to_exception (&error);
 +              mono_llvm_throw_exception ((MonoObject*)ex);
 +      }
 +      return result;
  }
  
  /*
@@@ -1733,11 -1729,7 +1742,11 @@@ mono_resolve_generic_virtual_iface_cal
  
        imt = (gpointer*)vt - MONO_IMT_SIZE;
  
 -      mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface);
 +      mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface, &error);
 +      if (!is_ok (&error)) {
 +              MonoException *ex = mono_error_convert_to_exception (&error);
 +              mono_llvm_throw_exception ((MonoObject*)ex);
 +      }
  
        if (vt->klass->valuetype)
                need_unbox_tramp = TRUE;
  gpointer
  mono_init_vtable_slot (MonoVTable *vtable, int slot)
  {
 +      MonoError error;
        gpointer arg = NULL;
        gpointer addr;
        gpointer *ftnptr;
  
 -      addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE);
 +      addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE, &error);
 +      if (mono_error_set_pending_exception (&error))
 +              return NULL;
        ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
        ftnptr [0] = addr;
        ftnptr [1] = arg;