[runtime] Switch to mono_runtime_invoke_checked and mono_runtime_try_invoke
authorAleksey Kliger <aleksey@xamarin.com>
Fri, 5 Feb 2016 21:00:19 +0000 (16:00 -0500)
committerAleksey Kliger <aleksey@xamarin.com>
Mon, 8 Feb 2016 15:51:48 +0000 (10:51 -0500)
Mark mono_runtime_invoke external only.
Runtime should use mono_runtime_invoke_checked and mono_runtime_try_invoke.

19 files changed:
mono/metadata/appdomain.c
mono/metadata/attach.c
mono/metadata/cominterop.c
mono/metadata/exception.c
mono/metadata/gc.c
mono/metadata/icall.c
mono/metadata/marshal.c
mono/metadata/mono-security.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/object.h
mono/metadata/reflection.c
mono/metadata/remoting.c
mono/metadata/threadpool-ms.c
mono/mini/debugger-agent.c
mono/mini/driver.c
mono/mini/jit-icalls.c
mono/mini/mini-exceptions.c
mono/mini/mini-runtime.c

index 0d861c86eb047e323a913a34506dd48f9c8453aa..3a939a868ba015bf46b17ec56206705fdf08aea2 100644 (file)
@@ -565,6 +565,8 @@ mono_domain_has_type_resolve (MonoDomain *domain)
 MonoReflectionAssembly *
 mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
 {
+       MonoError error;
+       MonoReflectionAssembly *ret;
        MonoClass *klass;
        void *params [1];
        static MonoMethod *method = NULL;
@@ -586,7 +588,11 @@ mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
                *params = (MonoObject*)mono_string_new (mono_domain_get (), name);
        else
                *params = tb;
-       return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
+
+       ret = (MonoReflectionAssembly *) mono_runtime_invoke_checked (method, domain->domain, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       return ret;
 }
 
 /**
@@ -951,6 +957,7 @@ MonoReflectionAssembly *
 mono_try_assembly_resolve (MonoDomain *domain, MonoString *fname, MonoAssembly *requesting, gboolean refonly)
 {
        MonoError error;
+       MonoReflectionAssembly *ret;
        MonoClass *klass;
        MonoMethod *method;
        MonoBoolean isrefonly;
@@ -979,7 +986,11 @@ mono_try_assembly_resolve (MonoDomain *domain, MonoString *fname, MonoAssembly *
        } else
                params [1] = NULL;
        params [2] = &isrefonly;
-       return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
+
+       ret = (MonoReflectionAssembly *) mono_runtime_invoke_checked (method, domain->domain, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       return ret;
 }
 
 MonoAssembly *
@@ -1093,7 +1104,9 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
        }
 
        *params = ref_assembly;
-       mono_runtime_invoke (assembly_load_method, domain->domain, params, NULL);
+
+       mono_runtime_invoke_checked (assembly_load_method, domain->domain, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 }
 
 /*
@@ -2474,6 +2487,7 @@ guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
 void
 mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
 {
+       MonoError error;
        HANDLE thread_handle;
        MonoAppDomainState prev_state;
        MonoMethod *method;
@@ -2508,7 +2522,9 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
        method = mono_class_get_method_from_name (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1); 
        g_assert (method);
 
-       mono_runtime_invoke (method, domain->domain, NULL, exc);
+       mono_runtime_try_invoke (method, domain->domain, NULL, exc, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
        if (*exc) {
                /* Roll back the state change */
                domain->state = MONO_APPDOMAIN_CREATED;
index e41bbf7d02b175aae8861ad07c2960fe20016e29..45c3da535940aa408e9d54d699273f3e94370fbf 100644 (file)
@@ -311,7 +311,8 @@ mono_attach_load_agent (MonoDomain *domain, char *agent, char *args, MonoObject
        g_free (agent);
 
        pa [0] = main_args;
-       mono_runtime_invoke (method, NULL, pa, exc);
+       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return 0;
 }
index d7402bb5520676e03679acb33723a260144afe12..94a120360888dac2e17c2755809365f6b9fe2391 100644 (file)
@@ -475,11 +475,16 @@ cominterop_com_visible (MonoClass* klass)
 static void cominterop_raise_hr_exception (int hr)
 {
        static MonoMethod* throw_exception_for_hr = NULL;
+       MonoError error;
        MonoException* ex;
        void* params[1] = {&hr};
+
        if (!throw_exception_for_hr)
                throw_exception_for_hr = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetExceptionForHR", 1);
-       ex = (MonoException*)mono_runtime_invoke (throw_exception_for_hr, NULL, params, NULL);
+
+       ex = (MonoException*)mono_runtime_invoke_checked (throw_exception_for_hr, NULL, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
        mono_raise_exception (ex);
 }
 
index a5e3c895ea71a3f7a37868e1a4c9c5ea7ddd2968..93c465582cbf79bdb11f7aa4908cfee2404e863d 100644 (file)
@@ -144,7 +144,10 @@ create_exception_two_strings (MonoClass *klass, MonoString *a1, MonoString *a2)
 
        args [0] = a1;
        args [1] = a2;
-       mono_runtime_invoke (method, o, args, NULL);
+
+       mono_runtime_invoke_checked (method, o, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
        return (MonoException *) o;
 }
 
@@ -602,7 +605,8 @@ mono_get_exception_type_initialization (const gchar *type_name, MonoException *i
 
        exc = mono_object_new_checked (mono_domain_get (), klass, &error);
        mono_error_assert_ok (&error);
-       mono_runtime_invoke (method, exc, args, NULL);
+       mono_runtime_invoke_checked (method, exc, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return (MonoException *) exc;
 }
@@ -777,7 +781,9 @@ mono_get_exception_reflection_type_load (MonoArray *types, MonoArray *exceptions
 
        exc = mono_object_new_checked (mono_domain_get (), klass, &error);
        mono_error_assert_ok (&error);
-       mono_runtime_invoke (method, exc, args, NULL);
+
+       mono_runtime_invoke_checked (method, exc, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return (MonoException *) exc;
 }
@@ -802,7 +808,9 @@ mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception)
        g_assert (method);
 
        params [0] = wrapped_exception;
-       mono_runtime_invoke (method, o, params, NULL);
+
+       mono_runtime_invoke_checked (method, o, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return (MonoException *)o;
 }      
index 7f85c3a0e04b33dee00a398c595a7e1510d138fe..c372266713b7a0cb5474f9262810db4c0ce876ac 100644 (file)
@@ -228,7 +228,7 @@ mono_gc_run_finalize (void *obj, void *data)
        }
 
        /* 
-        * To avoid the locking plus the other overhead of mono_runtime_invoke (),
+        * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (),
         * create and precompile a wrapper which calls the finalize method using
         * a CALLVIRT.
         */
index 2fab647fb8d5df4a104df4cbaa965a54f99f10ff..d60f7f6b93079e25d6a6c1f07a385a771d180d10 100644 (file)
@@ -4584,7 +4584,9 @@ create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build,
        args [3] = &revision;
        result = mono_object_new_checked (domain, System_Version, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
-       mono_runtime_invoke (create_version, result, args, NULL);
+
+       mono_runtime_invoke_checked (create_version, result, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return result;
 }
@@ -4600,6 +4602,7 @@ ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAsse
        static MonoMethod *create_culture = NULL;
        MonoImage *image = assembly->assembly->image;
        MonoTableInfo *t;
+       MonoObject *o;
 
        if (!System_Reflection_AssemblyName)
                System_Reflection_AssemblyName = mono_class_from_name (
@@ -4644,7 +4647,11 @@ ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAsse
                        MonoBoolean assembly_ref = 1;
                        args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
                        args [1] = &assembly_ref;
-                       MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
+
+                       o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
+                       mono_error_raise_exception (&error);
+
+                       MONO_OBJECT_SETREF (aname, cultureInfo, o);
                }
                
                if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
@@ -5120,6 +5127,8 @@ static void
 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
 {
        static MonoMethod *create_culture = NULL;
+       MonoError error;
+       MonoObject *obj;
        gpointer args [2];
        guint32 pkey_len;
        const char *pkey_ptr;
@@ -5180,7 +5189,11 @@ fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *a
        if (name->culture) {
                args [0] = mono_string_new (domain, name->culture);
                args [1] = &assembly_ref;
-               MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
+
+               obj = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+               MONO_OBJECT_SETREF (aname, cultureInfo, obj);
        }
 
        if (name->public_key) {
index 146e282f7df77819d890a2be866191ea487bd6fa..cd99b0d01dcc4b7fc0c9a168e743437715ccb40d 100644 (file)
@@ -710,10 +710,11 @@ mono_array_to_byte_byvalarray (gpointer native_arr, MonoArray *arr, guint32 elnu
 static MonoStringBuilder *
 mono_string_builder_new (int starting_string_length)
 {
-       MonoError error;
        static MonoClass *string_builder_class;
        static MonoMethod *sb_ctor;
        static void *args [1];
+
+       MonoError error;
        int initial_len = starting_string_length;
 
        if (initial_len < 0)
@@ -738,11 +739,12 @@ mono_string_builder_new (int starting_string_length)
        args [0] = &initial_len;
 
        MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new_checked (mono_domain_get (), string_builder_class, &error);
-       MonoObject *exc;
-       g_assert (sb && mono_error_ok (&error)); /* FIXME don't swallow the error */
+       mono_error_assert_ok (&error);
 
-       mono_runtime_invoke (sb_ctor, sb, args, &exc);
-       g_assert (!exc);
+       MonoObject *exc;
+       mono_runtime_try_invoke (sb_ctor, sb, args, &exc, &error);
+       g_assert (exc == NULL);
+       mono_error_assert_ok (&error);
 
        g_assert (sb->chunkChars->max_length >= initial_len);
 
@@ -10343,6 +10345,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
 void
 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
 {
+       MonoError error;
        MonoMethod *method;
        gpointer pa [3];
 
@@ -10355,12 +10358,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj
        pa [1] = &dst;
        pa [2] = &delete_old;
 
-       mono_runtime_invoke (method, NULL, pa, NULL);
+       mono_runtime_invoke_checked (method, NULL, pa, &error);
+       mono_error_raise_exception (&error);
 }
 
 static void
 ptr_to_structure (gpointer src, MonoObject *dst)
 {
+       MonoError error;
        MonoMethod *method;
        gpointer pa [2];
 
@@ -10369,7 +10374,8 @@ ptr_to_structure (gpointer src, MonoObject *dst)
        pa [0] = &src;
        pa [1] = dst;
 
-       mono_runtime_invoke (method, NULL, pa, NULL);
+       mono_runtime_invoke_checked (method, NULL, pa, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 }
 
 void
@@ -11143,7 +11149,8 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
                        pa [1] = &res;
                        pa [2] = &delete_old;
 
-                       mono_runtime_invoke (method, NULL, pa, NULL);
+                       mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                return res;
@@ -11158,6 +11165,7 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
 void
 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding, int param_attrs)
 {
+       MonoError error;
        MonoType *t;
        MonoClass *klass;
 
@@ -11192,7 +11200,8 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e
                        pa [0] = &ptr;
                        pa [1] = o;
 
-                       mono_runtime_invoke (method, NULL, pa, NULL);
+                       mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                if (!((param_attrs & PARAM_ATTRIBUTE_OUT) && !(param_attrs & PARAM_ATTRIBUTE_IN))) {
index 09ab44adc9bd938fc7d14a296337eb8050e51c52..03cc519767a4172a258d86d922e7235213f2b17f 100644 (file)
@@ -941,6 +941,7 @@ ves_icall_System_Security_SecureString_EncryptInternal (MonoArray* data, MonoObj
 
 void invoke_protected_memory_method (MonoArray *data, MonoObject *scope, gboolean encrypt)
 {
+       MonoError error;
        MonoClass *klass;
        MonoMethod *method;
        void *params [2];
@@ -960,5 +961,7 @@ void invoke_protected_memory_method (MonoArray *data, MonoObject *scope, gboolea
        method = mono_class_get_method_from_name (klass, encrypt ? "Protect" : "Unprotect", 2);
        params [0] = data;
        params [1] = scope; /* MemoryProtectionScope.SameProcess */
-       mono_runtime_invoke (method, NULL, params, NULL);
+
+       mono_runtime_invoke_checked (method, NULL, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 }
index 55970de8d291c5e8c9d75c121cb063373b776906..2f883b70007408a63596d9471bbf89e4e2b8dd37 100644 (file)
@@ -618,7 +618,7 @@ typedef struct {
        gboolean (*debug_log_is_enabled) (void);
        gboolean (*tls_key_supported) (MonoTlsKey key);
        void     (*init_delegate) (MonoDelegate *del);
-       MonoObject* (*runtime_invoke) (MonoMethod *method, void *obj, void **params, MonoError *error, MonoObject **exc);
+       MonoObject* (*runtime_invoke) (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error);
        void*    (*compile_method) (MonoMethod *method, MonoError *error);
 } MonoRuntimeCallbacks;
 
@@ -1696,6 +1696,13 @@ mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *merror
 MonoString *
 mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error);
 
+MonoObject*
+mono_runtime_try_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error);
+
+MonoObject*
+mono_runtime_invoke_checked (MonoMethod *method, void *obj, void **params, MonoError *error);
+
+
 #endif /* __MONO_OBJECT_INTERNALS_H__ */
 
 
index 6e69a3d5dabd446ace142aeb763453e5a83c68e0..f938fa41f20b8df803ee4b216cc27400d1ee05da 100644 (file)
@@ -69,6 +69,7 @@ mono_runtime_object_init (MonoObject *this_obj)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoMethod *method = NULL;
        MonoClass *klass = this_obj->vtable->klass;
 
@@ -78,7 +79,9 @@ mono_runtime_object_init (MonoObject *this_obj)
 
        if (method->klass->valuetype)
                this_obj = (MonoObject *)mono_object_unbox (this_obj);
-       mono_runtime_invoke (method, this_obj, NULL, NULL);
+
+       mono_runtime_invoke_checked (method, this_obj, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 }
 
 /* The pseudo algorithm for type initialization from the spec
@@ -277,6 +280,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoException *exc;
        MonoException *exc_to_throw;
        MonoMethod *method = NULL;
@@ -394,7 +398,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        mono_type_initialization_unlock ();
 
        if (do_initialization) {
-               mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+               mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, &error);
+               if (exc == NULL && !mono_error_ok (&error))
+                       exc = mono_error_convert_to_exception (&error);
 
                /* If the initialization failed, mark the class as unusable. */
                /* Avoid infinite loops */
@@ -2840,19 +2846,28 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
 static MonoObject*
 do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *result = NULL;
-       MonoError error;
 
        g_assert (callbacks.runtime_invoke);
-       result = callbacks.runtime_invoke (method, obj, params, &error, exc);
-       if (!mono_error_ok (&error)) {
-               if (exc) {
-                       *exc = (MonoObject*)mono_error_convert_to_exception (&error);
-                       return NULL;
-               } else {
-                       mono_error_raise_exception (&error);
-               }
-       }
+
+       mono_error_init (error);
+       
+       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+               mono_profiler_method_start_invoke (method);
+
+       MONO_PREPARE_RESET_BLOCKING;
+
+       result = callbacks.runtime_invoke (method, obj, params, exc, error);
+
+       MONO_FINISH_RESET_BLOCKING;
+
+       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+               mono_profiler_method_end_invoke (method);
+
+       if (!mono_error_ok (error))
+               return NULL;
 
        return result;
 }
@@ -2893,29 +2908,117 @@ do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **ex
  */
 MonoObject*
 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+{
+       MonoError error;
+       MonoObject *res;
+       if (exc) {
+               res = mono_runtime_try_invoke (method, obj, params, exc, &error);
+               if (*exc == NULL && !mono_error_ok(&error)) {
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               }
+       } else {
+               res = mono_runtime_invoke_checked (method, obj, params, &error);
+               mono_error_raise_exception (&error);
+       }
+       return res;
+}
+
+/**
+ * mono_runtime_try_invoke:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ * @error: set on error
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. 
+ * 
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ * 
+ * For this function, you must not pass NULL as the exc argument if
+ * you don't want to catch exceptions, use
+ * mono_runtime_invoke_checked().  If an exception is thrown, you
+ * can't use the MonoObject* result from the function.
+ * 
+ * If this method cannot be invoked, @error will be set and @exc and
+ * the return value must not be used.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_try_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError* error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
-       MonoObject *result;
+       g_assert (exc != NULL);
 
        if (mono_runtime_get_no_exec ())
                g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
 
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_start_invoke (method);
-
-       MONO_PREPARE_RESET_BLOCKING;
-
-       result = do_runtime_invoke (method, obj, params, exc, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return do_runtime_invoke (method, obj, params, exc, error);
+}
 
-       MONO_FINISH_RESET_BLOCKING;
+/**
+ * mono_runtime_invoke_checked:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @error: set on error
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. 
+ * 
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ * 
+ * If an exception is thrown, you can't use the MonoObject* result
+ * from the function.
+ * 
+ * If this method cannot be invoked, @error will be set.  If the
+ * method throws an exception (and we're in coop mode) the exception
+ * will be set in @error.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_invoke_checked (MonoMethod *method, void *obj, void **params, MonoError* error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
 
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_end_invoke (method);
+       if (mono_runtime_get_no_exec ())
+               g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
 
-       return result;
+       return do_runtime_invoke (method, obj, params, NULL, error);
 }
 
 /**
@@ -3332,7 +3435,10 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                args [1] = mono_type_get_object_checked (mono_domain_get (), type, &error);
                mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-               return mono_runtime_invoke (m, NULL, args, NULL);
+               o = mono_runtime_invoke_checked (m, NULL, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+               return o;
        }
 
        /* boxed value type */
@@ -3485,7 +3591,11 @@ mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 
        MonoError error;
        do_runtime_invoke (prop->set, obj, params, exc, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (exc && *exc == NULL && !mono_error_ok (&error)) {
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
 }
 
 /**
@@ -3512,7 +3622,11 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 
        MonoError error;
        MonoObject *val = do_runtime_invoke (prop->get, obj, params, exc, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       if (exc && *exc == NULL && !mono_error_ok (&error)) {
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
 
        return val;
 }
@@ -3672,14 +3786,25 @@ mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoMethod *im;
        MonoClass *klass = delegate->vtable->klass;
+       MonoObject *o;
 
        im = mono_get_delegate_invoke (klass);
        if (!im)
                g_error ("Could not lookup delegate invoke method for delegate %s", mono_type_get_full_name (klass));
 
-       return mono_runtime_invoke (im, delegate, params, exc);
+       if (exc) {
+               o = mono_runtime_try_invoke (im, delegate, params, exc, &error);
+               if (*exc == NULL && !mono_error_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               o = mono_runtime_invoke_checked (im, delegate, params, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
+
+       return o;
 }
 
 static char **main_args = NULL;
@@ -3867,6 +3992,7 @@ serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
        static MonoMethod *serialize_method;
 
+       MonoError error;
        void *params [1];
        MonoObject *array;
 
@@ -3884,7 +4010,11 @@ serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        params [0] = obj;
        *exc = NULL;
-       array = mono_runtime_invoke (serialize_method, NULL, params, exc);
+
+       array = mono_runtime_try_invoke (serialize_method, NULL, params, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert serialize_object to MonoError */
+
        if (*exc)
                *failure = TRUE;
 
@@ -3898,6 +4028,7 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        static MonoMethod *deserialize_method;
 
+       MonoError error;
        void *params [1];
        MonoObject *result;
 
@@ -3912,7 +4043,11 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        params [0] = obj;
        *exc = NULL;
-       result = mono_runtime_invoke (deserialize_method, NULL, params, exc);
+
+       result = mono_runtime_try_invoke (deserialize_method, NULL, params, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert deserialize_object to MonoError */
+
        if (*exc)
                *failure = TRUE;
 
@@ -3947,7 +4082,10 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
        MONO_OBJECT_SETREF (real_proxy, unwrapped_server, obj);
 
        *exc = NULL;
-       transparent_proxy = (MonoTransparentProxy*) mono_runtime_invoke (get_proxy_method, real_proxy, NULL, exc);
+
+       transparent_proxy = (MonoTransparentProxy*) mono_runtime_try_invoke (get_proxy_method, real_proxy, NULL, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME change make_transparent_proxy outarg to MonoError */
        if (*exc)
                *failure = TRUE;
 
@@ -3977,6 +4115,7 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
        MonoObject *deserialized = NULL;
        gboolean failure = FALSE;
 
+       g_assert (exc != NULL);
        *exc = NULL;
 
 #ifndef DISABLE_REMOTING
@@ -4028,7 +4167,9 @@ create_unhandled_exception_eventargs (MonoObject *exc)
 
        obj = mono_object_new_checked (mono_domain_get (), klass, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
-       mono_runtime_invoke (method, obj, args, NULL);
+
+       mono_runtime_invoke_checked (method, obj, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return obj;
 }
@@ -4198,6 +4339,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoDomain *domain;
        gpointer pa [1];
        int rval;
@@ -4250,7 +4392,15 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
-               res = mono_runtime_invoke (method, NULL, pa, exc);
+               if (exc) {
+                       res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               } else {
+                       res = mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                if (!exc || !*exc)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
@@ -4258,7 +4408,15 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 
                mono_environment_exitcode_set (rval);
        } else {
-               mono_runtime_invoke (method, NULL, pa, exc);
+               if (exc) {
+                       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               } else {
+                       mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                if (!exc || !*exc)
                        rval = 0;
                else {
@@ -4296,7 +4454,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
  * respective reference representation.
  * 
  * From unmanaged code you'll usually use the
- * mono_runtime_invoke() variant.
+ * mono_runtime_invoke_checked() variant.
  *
  * Note that this function doesn't handle virtual methods for
  * you, it will exec the exact method you pass: we still need to
@@ -4441,7 +4599,15 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        obj = mono_value_box (mono_domain_get (), method->klass, obj);
                }
 
-               mono_runtime_invoke (method, o, pa, exc);
+               if (exc) {
+                       mono_runtime_try_invoke (method, o, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               } else {
+                       mono_runtime_invoke_checked (method, o, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                return (MonoObject *)obj;
        } else {
                if (mono_class_is_nullable (method->klass)) {
@@ -4456,7 +4622,14 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                }
 
                /* obj must be already unboxed if needed */
-               res = mono_runtime_invoke (method, obj, pa, exc);
+               if (exc) {
+                       res = mono_runtime_try_invoke (method, obj, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               } else {
+                       res = mono_runtime_invoke_checked (method, obj, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
 
                if (sig->ret->type == MONO_TYPE_PTR) {
                        MonoClass *pointer_class;
@@ -4477,8 +4650,9 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        box_args [1] = mono_type_get_object_checked (mono_domain_get (), sig->ret, &error);
                        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-                       res = mono_runtime_invoke (box_method, NULL, box_args, &box_exc);
-                       g_assert (!box_exc);
+                       res = mono_runtime_try_invoke (box_method, NULL, box_args, &box_exc, &error);
+                       g_assert (box_exc == NULL);
+                       mono_error_assert_ok (&error);
                }
 
                if (has_byref_nullables) {
@@ -4640,8 +4814,12 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error)
                if (!mono_error_ok (error))
                        return NULL;
 
-               o = mono_runtime_invoke (im, NULL, pa, NULL);           
-               if (o != NULL) return o;
+               o = mono_runtime_invoke_checked (im, NULL, pa, error);
+               if (!mono_error_ok (error))
+                       return NULL;
+
+               if (o != NULL)
+                       return o;
        }
 
        return mono_object_new_alloc_specific_checked (vtable, error);
@@ -5713,8 +5891,9 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                mono_error_raise_exception (&error); /* FIXME don't raise here */
                pa [1] = obj;
 
-               res = mono_runtime_invoke (im, rp, pa, NULL);
-       
+               res = mono_runtime_invoke_checked (im, rp, pa, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
                if (*(MonoBoolean *) mono_object_unbox(res)) {
                        /* Update the vtable of the remote type, so it can safely cast to this new type */
                        mono_upgrade_remote_class (domain, obj, klass);
@@ -6328,7 +6507,9 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
                handle_set = mono_class_get_property_from_name (mono_defaults.manualresetevent_class, "Handle")->set;
 
        params [0] = &handle;
-       mono_runtime_invoke (handle_set, res, params, NULL);
+
+       mono_runtime_invoke_checked (handle_set, res, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return res;
 }
@@ -6422,6 +6603,7 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoAsyncCall *ac;
        MonoObject *res;
 
@@ -6450,7 +6632,10 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                if (ac->cb_method) {
                        /* we swallow the excepton as it is the behavior on .NET */
                        MonoObject *exc = NULL;
-                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, &exc);
+                       mono_runtime_try_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, &exc, &error);
+                       if (exc == NULL && !mono_error_ok (&error))
+                               exc = (MonoObject*) mono_error_convert_to_exception (&error);
+
                        if (exc)
                                mono_unhandled_exception (exc);
                }
@@ -6564,6 +6749,8 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoObject *o;
        MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
        gpointer pa [4];
 
@@ -6581,7 +6768,14 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
        pa [2] = exc;
        pa [3] = out_args;
 
-       return mono_runtime_invoke (im, NULL, pa, exc);
+       if (exc) {
+               o = mono_runtime_try_invoke (im, NULL, pa, exc, &error);
+       } else {
+               o = mono_runtime_invoke_checked (im, NULL, pa, &error);
+       }
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       return o;
 }
 #endif
 
@@ -6663,7 +6857,9 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoMethod *to_string = NULL;
+       MonoError error;
        MonoMethod *method;
+       MonoString *s;
        void *target = obj;
 
        g_assert (obj);
@@ -6678,7 +6874,16 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
                target = mono_object_unbox (obj);
        }
 
-       return (MonoString *) mono_runtime_invoke (method, target, NULL, exc);
+       if (exc) {
+               s = (MonoString *) mono_runtime_try_invoke (method, target, NULL, exc, &error);
+               if (*exc == NULL && !mono_error_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               s = (MonoString *) mono_runtime_invoke_checked (method, target, NULL, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
+
+       return s;
 }
 
 /**
index 94a4dbf6c6f9d770165f0994aa0c32d04c666ab9..b19092e81315f25db3a1603ec0e62d95e19e01b5 100644 (file)
@@ -218,6 +218,7 @@ mono_runtime_class_init         (MonoVTable *vtable);
 MONO_API MonoMethod*
 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API MonoObject*
 mono_runtime_invoke        (MonoMethod *method, void *obj, void **params,
                             MonoObject **exc);
index f5ddf99e55cd2c6e20bcbe58a4debfbee0a592cd..7ec207c0413096b575c74d42253c90930912016d 100644 (file)
@@ -8865,7 +8865,9 @@ create_cattr_typed_arg (MonoType *t, MonoObject *val)
        retval = mono_object_new_checked (mono_domain_get (), klass, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
        unboxed = mono_object_unbox (retval);
-       mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+       mono_runtime_invoke_checked (ctor, unboxed, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return retval;
 }
@@ -8889,7 +8891,9 @@ create_cattr_named_arg (void *minfo, MonoObject *typedarg)
        retval = mono_object_new_checked (mono_domain_get (), klass, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
        unboxed = mono_object_unbox (retval);
-       mono_runtime_invoke (ctor, unboxed, params, NULL);
+
+       mono_runtime_invoke_checked (ctor, unboxed, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return retval;
 }
@@ -8994,7 +8998,11 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        if (len == 0) {
                attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
                if (!mono_error_ok (error)) return NULL;
-               mono_runtime_invoke (method, attr, NULL, NULL);
+
+               mono_runtime_invoke_checked (method, attr, NULL, error);
+               if (!mono_error_ok (error))
+                       return NULL;
+
                return attr;
        }
 
@@ -9024,9 +9032,12 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
        if (!mono_error_ok (error)) goto fail;
 
-       mono_runtime_invoke (method, attr, params, &exc);
+       mono_runtime_try_invoke (method, attr, params, &exc, error);
+       if (!mono_error_ok (error))
+               goto fail;
        if (exc)
                goto fail;
+
        num_named = read16 (named);
        named += 2;
        for (j = 0; j < num_named; j++) {
@@ -9388,7 +9399,10 @@ create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
        mono_error_raise_exception (&error); /* FIXME don't raise here */
        params [2] = (gpointer)&cattr->data;
        params [3] = &cattr->data_size;
-       mono_runtime_invoke (ctor, attr, params, NULL);
+
+       mono_runtime_invoke_checked (ctor, attr, params, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
        return attr;
 }
 
@@ -9955,12 +9969,19 @@ static MonoReflectionType*
 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
 {
        static MonoMethod *method_get_underlying_system_type = NULL;
+       MonoError error;
+       MonoReflectionType *rt;
        MonoMethod *usertype_method;
 
        if (!method_get_underlying_system_type)
                method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
+
        usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
-        return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
+
+       rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       return rt;
 }
 
 
@@ -13647,10 +13668,12 @@ mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
        params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-       res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
-       if (exc)
+       res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
+
+       if (exc || !mono_error_ok (&error)) {
+               mono_error_cleanup (&error);
                return FALSE;
-       else
+       else
                return *(MonoBoolean*)mono_object_unbox (res);
 }
 
index 8b602e7e1ca746772a07f5bf6d36b4b7b81a3c8d..8cd7a6ef1b107310850dd10c91047a7877012154 100644 (file)
@@ -340,6 +340,7 @@ mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
 static MonoObject *
 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
 {
+       MonoError error;
        MonoMethodMessage *msg;
        MonoTransparentProxy *this_obj;
        MonoObject *res, *exc;
@@ -377,7 +378,10 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params)
                        }
                }
 
-               return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this_obj): this_obj, mparams, NULL);
+               res = mono_runtime_invoke_checked (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this_obj): this_obj, mparams, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+               return res;
        }
 
        msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
index 2d68656fe0fb96b84aebb051f56f4aed3226f369..7d9657c2fcc61f229b54dca8a45e1af6388ad667 100644 (file)
@@ -349,6 +349,7 @@ mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item)
 {
        static MonoClass *threadpool_class = NULL;
        static MonoMethod *unsafe_queue_custom_work_item_method = NULL;
+       MonoError error;
        MonoDomain *current_domain;
        MonoBoolean f;
        gpointer args [2];
@@ -370,11 +371,13 @@ mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item)
 
        current_domain = mono_domain_get ();
        if (current_domain == domain) {
-               mono_runtime_invoke (unsafe_queue_custom_work_item_method, NULL, args, NULL);
+               mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
        } else {
                mono_thread_push_appdomain_ref (domain);
                if (mono_domain_set (domain, FALSE)) {
-                       mono_runtime_invoke (unsafe_queue_custom_work_item_method, NULL, args, NULL);
+                       mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                        mono_domain_set (current_domain, TRUE);
                }
                mono_thread_pop_appdomain_ref ();
@@ -572,6 +575,7 @@ worker_kill (ThreadPoolWorkingThread *thread)
 static void
 worker_thread (gpointer data)
 {
+       MonoError error;
        MonoInternalThread *thread;
        ThreadPoolDomain *tpdomain, *previous_tpdomain;
        ThreadPoolCounter counter;
@@ -643,11 +647,16 @@ worker_thread (gpointer data)
 
                mono_thread_push_appdomain_ref (tpdomain->domain);
                if (mono_domain_set (tpdomain->domain, FALSE)) {
-                       MonoObject *exc = NULL;
-                       MonoObject *res = mono_runtime_invoke (mono_defaults.threadpool_perform_wait_callback_method, NULL, NULL, &exc);
-                       if (exc)
+                       MonoObject *exc = NULL, *res;
+
+                       res = mono_runtime_try_invoke (mono_defaults.threadpool_perform_wait_callback_method, NULL, NULL, &exc, &error);
+                       if (exc || !mono_error_ok(&error)) {
+                               if (exc == NULL)
+                                       exc = (MonoObject *) mono_error_convert_to_exception (&error);
+                               else
+                                       mono_error_cleanup (&error);
                                mono_thread_internal_unhandled_exception (exc);
-                       else if (res && *(MonoBoolean*) mono_object_unbox (res) == FALSE)
+                       else if (res && *(MonoBoolean*) mono_object_unbox (res) == FALSE)
                                retire = TRUE;
 
                        mono_thread_clr_state (thread, (MonoThreadState)~ThreadState_Background);
index 869fc084de7c3e67ce122a26f2d31ae4d8126aeb..263a1498455d51ac48ee67f956a3def52de22eea 100644 (file)
@@ -230,7 +230,7 @@ typedef struct {
        gboolean abort_requested;
 
        /*
-        * The current mono_runtime_invoke invocation.
+        * The current mono_runtime_invoke_checked invocation.
         */
        InvokeData *invoke;
 
@@ -6461,6 +6461,7 @@ add_thread (gpointer key, gpointer value, gpointer user_data)
 static ErrorCode
 do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 *p, guint8 **endp)
 {
+       MonoError error;
        guint8 *end = invoke->endp;
        MonoMethod *m;
        int i, nargs;
@@ -6482,7 +6483,10 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
                 */
                this_arg = NULL;
                DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer) (gsize) mono_native_thread_id_get (), mono_method_full_name (invoke->method, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
-               mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
+
+               mono_runtime_try_invoke (invoke->method, NULL, invoke->args, &exc, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
                g_assert_not_reached ();
        }
 
@@ -6630,10 +6634,12 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
 #endif
 
        mono_stopwatch_start (&watch);
-       if (m->klass->valuetype)
-               res = mono_runtime_invoke (m, this_buf, args, &exc);
-       else
-               res = mono_runtime_invoke (m, this_arg, args, &exc);
+       res = mono_runtime_try_invoke (m, m->klass->valuetype ? (gpointer) this_buf : (gpointer) this_arg, args, &exc, &error);
+       if (exc == NULL && !mono_error_ok (&error)) {
+               exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               mono_error_cleanup (&error); /* FIXME report error */
+       }
        mono_stopwatch_stop (&watch);
        DEBUG_PRINTF (1, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer) (gsize) mono_native_thread_id_get (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch));
        if (exc) {
@@ -6789,7 +6795,7 @@ invoke_method (void)
         * Take the loader lock to avoid race conditions with CMD_VM_ABORT_INVOKE:
         *
         * It is possible that ves_icall_System_Threading_Thread_Abort () was called
-        * after the mono_runtime_invoke() already returned, but it doesn't matter
+        * after the mono_runtime_invoke_checked() already returned, but it doesn't matter
         * because we reset the abort here.
         */
 
@@ -7084,7 +7090,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
                }
 
                /*
-                * Check whether we're still inside the mono_runtime_invoke() and that it's
+                * Check whether we're still inside the mono_runtime_invoke_checked() and that it's
                 * actually the correct invocation.
                 *
                 * Careful, we do not stop the thread that's doing the invocation, so we can't
index 963ceccb560316d30a58444f635c48f1ef8f1ede..dada64022d8d4245e015258627a8a358e0459784 100644 (file)
@@ -1158,7 +1158,8 @@ load_agent (MonoDomain *domain, char *desc)
 
        pa [0] = main_args;
        /* Pass NULL as 'exc' so unhandled exceptions abort the runtime */
-       mono_runtime_invoke (method, NULL, pa, NULL);
+       mono_runtime_invoke_checked (method, NULL, pa, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return 0;
 }
index d36172c2eaf11053a586cbe19565ee298225813c..3d169f251bd03e8cce4e310bd1e6af953a5b0203 100644 (file)
@@ -1327,12 +1327,13 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
  * mono_gsharedvt_constrained_call:
  *
  *   Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
- * the arguments to the method in the format used by mono_runtime_invoke ().
+ * the arguments to the method in the format used by mono_runtime_invoke_checked ().
  */
 MonoObject*
 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
 {
        MonoError error;
+       MonoObject *o;
        MonoMethod *m;
        gpointer this_arg;
        gpointer new_args [16];
@@ -1355,7 +1356,14 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl
                args [0] = this_arg;
                this_arg = NULL;
        }
-       return mono_runtime_invoke (m, this_arg, args, NULL);
+
+       o = mono_runtime_invoke_checked (m, this_arg, args, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return o;
 }
 
 void
index f83bcf91b4e8e823a991afad8ea133a6733c8fb4..c59c9ca2a5b0c060caa3f6d14a0e12a63ebf9d01 100644 (file)
@@ -62,6 +62,8 @@
 #include <mono/metadata/mono-mlist.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/mono-error.h>
+#include <mono/utils/mono-error-internals.h>
 
 #include "mini.h"
 #include "trace.h"
@@ -1548,6 +1550,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
 static gboolean
 mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resume, MonoJitInfo **out_ji)
 {
+       MonoError error;
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji, *prev_ji;
        static int (*call_filter) (MonoContext *, gpointer) = NULL;
@@ -1646,15 +1649,16 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        MonoObject *message;
                        const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
                        char *msg = NULL;
-                       MonoObject *exc = NULL;
                        if (get_message == NULL) {
                                message = NULL;
                        } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
                                message = NULL;
                                msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
                        } else {
-                               message = mono_runtime_invoke (get_message, obj, NULL, &exc);
-                               
+                               MonoObject *exc = NULL;
+                               message = mono_runtime_try_invoke (get_message, obj, NULL, &exc, &error);
+                               g_assert (exc == NULL);
+                               mono_error_assert_ok (&error);
                        }
                        if (msg == NULL) {
                                msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
@@ -1688,7 +1692,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        gboolean unhandled = FALSE;
 
                        /*
-                        * The exceptions caught by the mono_runtime_invoke () calls
+                        * The exceptions caught by the mono_runtime_invoke_checked () calls
                         * in the threadpool needs to be treated as unhandled (#669836).
                         *
                         * FIXME: The check below is hackish, but its hard to distinguish
index 0e15359455d9e8ac399b7bf1182010ad11314ddf..40d57bf24307cf0930d92f9e42c0c7e1fb0689cb 100644 (file)
@@ -2393,6 +2393,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void
        runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
 
        runtime_invoke (NULL, args, exc, info->compiled_method);
+       if (exc && *exc)
+               mono_error_set_exception_instance (error, (MonoException*) *exc);
 
        if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
                return mono_value_box (domain, info->ret_box_class, retval);
@@ -2405,8 +2407,10 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void
  * @method: the method to invoke
  * @obj: this pointer
  * @params: array of parameter values.
- * @error: error
- * @exc: used to catch exceptions objects
+ * @exc: Set to the exception raised in the managed method.  If NULL, error is thrown instead.
+ *       If coop is enabled, this argument is ignored - all exceptoins are caught and propagated
+ *       through @error
+ * @error: error or caught exception object
  */
 static MonoObject*
 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
@@ -2438,10 +2442,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                         */
                        mono_class_setup_vtable (method->klass);
                        if (method->klass->exception_type != MONO_EXCEPTION_NONE) {
+                               MonoException *fail_exc = mono_class_get_exception_for_failure (method->klass);
                                if (exc)
-                                       *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
-                               else
-                                       mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
+                                       *exc = (MonoObject*)fail_exc;
+                               mono_error_set_exception_instance (error, fail_exc);
                                return NULL;
                        }
                }
@@ -2506,14 +2510,25 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
         * We need this here because mono_marshal_get_runtime_invoke can place
         * the helper method in System.Object and not the target class.
         */
-       if (exc) {
+       if (exc)
+       {
                *exc = (MonoObject*)mono_runtime_class_init_full (info->vtable, FALSE);
-               if (*exc)
+               if (*exc) {
+                       mono_error_set_exception_instance (error, (MonoException*) *exc);
                        return NULL;
+               }
        } else {
                mono_runtime_class_init (info->vtable);
        }
 
+       /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
+          we always catch the exception and propagate it through the MonoError */
+       gboolean catchExcInMonoError =
+               (exc == NULL) && mono_threads_is_coop_enabled ();
+       MonoObject *invoke_exc = NULL;
+       if (catchExcInMonoError)
+               exc = &invoke_exc;
+
        /* The wrappers expect this to be initialized to NULL */
        if (exc)
                *exc = NULL;
@@ -2556,6 +2571,8 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
 
                dyn_runtime_invoke (buf, exc, info->compiled_method);
+               if (exc && *exc)
+                       mono_error_set_exception_instance (error, (MonoException*) *exc);
 
                mono_arch_finish_dyn_call (info->dyn_call_info, buf);
 
@@ -2571,7 +2588,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
 
        runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
 
-       return runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+       MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+       if (catchExcInMonoError && *exc != NULL)
+               mono_error_set_exception_instance (error, (MonoException*) *exc);
+       return result;
 }
 
 typedef struct {