[runtime] MonoError-ize mono_runtime_delegate_invoke
[mono.git] / mono / metadata / object.c
index 61f8f4866da27f9c5ccb3b2b4f84abdfb4ea66e5..0fe846451ae73f7b16401d9fc1eb7bea2b54d003 100644 (file)
@@ -612,18 +612,34 @@ mono_set_always_build_imt_thunks (gboolean value)
 gpointer 
 mono_compile_method (MonoMethod *method)
 {
-       gpointer res;
        MonoError error;
+       gpointer result = mono_compile_method_checked (method, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_compile_method:
+ * @method: The method to compile.
+ * @error: set on error.
+ *
+ * This JIT-compiles the method, and returns the pointer to the native code
+ * produced.  On failure returns NULL and sets @error.
+ */
+gpointer
+mono_compile_method_checked (MonoMethod *method, MonoError *error)
+{
+       gpointer res;
 
        MONO_REQ_GC_NEUTRAL_MODE
 
+       mono_error_init (error);
+
        if (!callbacks.compile_method) {
                g_error ("compile method called on uninitialized runtime");
                return NULL;
        }
-       res = callbacks.compile_method (method, &error);
-       if (!mono_error_ok (&error))
-               mono_error_raise_exception (&error);
+       res = callbacks.compile_method (method, error);
        return res;
 }
 
@@ -2892,11 +2908,11 @@ do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **ex
        if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
                mono_profiler_method_start_invoke (method);
 
-       MONO_PREPARE_RESET_BLOCKING;
+       MONO_ENTER_GC_UNSAFE;
 
        result = callbacks.runtime_invoke (method, obj, params, exc, error);
 
-       MONO_FINISH_RESET_BLOCKING;
+       MONO_EXIT_GC_UNSAFE;
 
        if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
                mono_profiler_method_end_invoke (method);
@@ -3113,12 +3129,16 @@ mono_method_get_unmanaged_thunk (MonoMethod *method)
        MONO_REQ_GC_NEUTRAL_MODE;
        MONO_REQ_API_ENTRYPOINT;
 
+       MonoError error;
        gpointer res;
 
-       MONO_PREPARE_RESET_BLOCKING;
+       g_assert (!mono_threads_is_coop_enabled ());
+
+       MONO_ENTER_GC_UNSAFE;
        method = mono_marshal_get_thunk_invoke_wrapper (method);
-       res = mono_compile_method (method);
-       MONO_FINISH_RESET_BLOCKING;
+       res = mono_compile_method_checked (method, &error);
+       mono_error_cleanup (&error);
+       MONO_EXIT_GC_UNSAFE;
 
        return res;
 }
@@ -3946,6 +3966,44 @@ mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoError error;
+       if (exc) {
+               MonoObject *result = mono_runtime_delegate_try_invoke (delegate, params, exc, &error);
+               if (*exc) {
+                       mono_error_cleanup (&error);
+                       return NULL;
+               } else {
+                       if (!is_ok (&error))
+                               *exc = (MonoObject*)mono_error_convert_to_exception (&error);
+                       return result;
+               }
+       } else {
+               MonoObject *result = mono_runtime_delegate_invoke_checked (delegate, params, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               return result;
+       }
+}
+
+/**
+ * mono_runtime_delegate_try_invoke:
+ * @delegate: pointer to a delegate object.
+ * @params: parameters for the delegate.
+ * @exc: Pointer to the exception result.
+ * @error: set on error
+ *
+ * Invokes the delegate method @delegate with the parameters provided.
+ *
+ * You can pass NULL as the exc argument if you don't want to
+ * catch exceptions, otherwise, *exc will be set to the exception
+ * thrown, if any.  On failure to execute, @error will be set.
+ * if an exception is thrown, you can't use the
+ * MonoObject* result from the function.
+ */
+MonoObject*
+mono_runtime_delegate_try_invoke (MonoObject *delegate, void **params, MonoObject **exc, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
        MonoMethod *im;
        MonoClass *klass = delegate->vtable->klass;
        MonoObject *o;
@@ -3955,19 +4013,32 @@ mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **
                g_error ("Could not lookup delegate invoke method for delegate %s", mono_type_get_full_name (klass));
 
        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
-                       mono_error_cleanup (&error);
+               o = mono_runtime_try_invoke (im, delegate, params, exc, error);
        } else {
-               o = mono_runtime_invoke_checked (im, delegate, params, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               o = mono_runtime_invoke_checked (im, delegate, params, error);
        }
 
        return o;
 }
 
+/**
+ * mono_runtime_delegate_invoke_checked:
+ * @delegate: pointer to a delegate object.
+ * @params: parameters for the delegate.
+ * @error: set on error
+ *
+ * Invokes the delegate method @delegate with the parameters provided.
+ *
+ * On failure @error will be set and you can't use the MonoObject*
+ * result from the function.
+ */
+MonoObject*
+mono_runtime_delegate_invoke_checked (MonoObject *delegate, void **params, MonoError *error)
+{
+       mono_error_init (error);
+       return mono_runtime_delegate_try_invoke (delegate, params, NULL, error);
+}
+
 static char **main_args = NULL;
 static int num_main_args = 0;
 
@@ -4328,11 +4399,11 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
 
 /* Used in call_unhandled_exception_delegate */
 static MonoObject *
-create_unhandled_exception_eventargs (MonoObject *exc)
+create_unhandled_exception_eventargs (MonoObject *exc, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
+       mono_error_init (error);
        MonoClass *klass;
        gpointer args [2];
        MonoMethod *method = NULL;
@@ -4349,11 +4420,11 @@ create_unhandled_exception_eventargs (MonoObject *exc)
        args [0] = exc;
        args [1] = &is_terminating;
 
-       obj = mono_object_new_checked (mono_domain_get (), klass, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       obj = mono_object_new_checked (mono_domain_get (), klass, error);
+       return_val_if_nok (error, NULL);
 
-       mono_runtime_invoke_checked (method, obj, args, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_runtime_invoke_checked (method, obj, args, error);
+       return_val_if_nok (error, NULL);
 
        return obj;
 }
@@ -4363,6 +4434,7 @@ static void
 call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, MonoObject *exc) {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoObject *e = NULL;
        gpointer pa [2];
        MonoDomain *current_domain = mono_domain_get ();
@@ -4373,7 +4445,6 @@ call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, Mon
        g_assert (domain == mono_object_domain (domain->domain));
 
        if (mono_object_domain (exc) != domain) {
-               MonoError error;
 
                exc = mono_object_xdomain_representation (exc, domain, &error);
                if (!exc) {
@@ -4392,14 +4463,20 @@ call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, Mon
        g_assert (mono_object_domain (exc) == domain);
 
        pa [0] = domain->domain;
-       pa [1] = create_unhandled_exception_eventargs (exc);
-       mono_runtime_delegate_invoke (delegate, pa, &e);
+       pa [1] = create_unhandled_exception_eventargs (exc, &error);
+       mono_error_assert_ok (&error);
+       mono_runtime_delegate_try_invoke (delegate, pa, &e, &error);
+       if (!is_ok (&error)) {
+               if (e == NULL)
+                       e = (MonoObject*)mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+       }
 
        if (domain != current_domain)
                mono_domain_set_internal_with_options (current_domain, FALSE);
 
        if (e) {
-               MonoError error;
                gchar *msg = mono_string_to_utf8_checked (((MonoException *) e)->message, &error);
                if (!mono_error_ok (&error)) {
                        g_warning ("Exception inside UnhandledException handler with invalid message (Invalid characters)\n");
@@ -4470,10 +4547,10 @@ mono_unhandled_exception (MonoObject *exc)
        root_domain = mono_get_root_domain ();
 
        root_appdomain_delegate = mono_field_get_value_object_checked (root_domain, field, (MonoObject*) root_domain->domain, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_assert_ok (&error);
        if (current_domain != root_domain) {
                current_appdomain_delegate = mono_field_get_value_object_checked (current_domain, field, (MonoObject*) current_domain->domain, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_assert_ok (&error);
        }
 
        if (!current_appdomain_delegate && !root_appdomain_delegate) {
@@ -7009,20 +7086,24 @@ mono_wait_handle_get_handle (MonoWaitHandle *handle)
 
 
 static MonoObject*
-mono_runtime_capture_context (MonoDomain *domain)
+mono_runtime_capture_context (MonoDomain *domain, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        RuntimeInvokeFunction runtime_invoke;
 
+       mono_error_init (error);
+
        if (!domain->capture_context_runtime_invoke || !domain->capture_context_method) {
                MonoMethod *method = mono_get_context_capture_method ();
                MonoMethod *wrapper;
                if (!method)
                        return NULL;
                wrapper = mono_marshal_get_runtime_invoke (method, FALSE);
-               domain->capture_context_runtime_invoke = mono_compile_method (wrapper);
-               domain->capture_context_method = mono_compile_method (method);
+               domain->capture_context_runtime_invoke = mono_compile_method_checked (wrapper, error);
+               return_val_if_nok (error, NULL);
+               domain->capture_context_method = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, NULL);
        }
 
        runtime_invoke = (RuntimeInvokeFunction)domain->capture_context_runtime_invoke;
@@ -7048,7 +7129,8 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        MonoError error;
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_defaults.asyncresult_class, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
-       MonoObject *context = mono_runtime_capture_context (domain);
+       MonoObject *context = mono_runtime_capture_context (domain, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        /* we must capture the execution context from the original thread */
        if (context) {
                MONO_OBJECT_SETREF (res, execution_context, context);
@@ -7083,7 +7165,9 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
 
        ac = (MonoAsyncCall*) ares->object_data;
        if (!ac) {
-               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, NULL);
+               res = mono_runtime_delegate_invoke_checked (ares->async_delegate, (void**) &ares->async_state, &error);
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
        } else {
                gpointer wait_event = NULL;
 
@@ -7436,6 +7520,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoDelegate *delegate = (MonoDelegate *)this_obj;
 
        g_assert (this_obj);
@@ -7452,7 +7537,8 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
        if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
                g_assert (method);
                method = mono_marshal_get_remoting_invoke (method);
-               delegate->method_ptr = mono_compile_method (method);
+               delegate->method_ptr = mono_compile_method_checked (method, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
                MONO_OBJECT_SETREF (delegate, target, target);
        } else
 #endif