Merge pull request #2819 from BrzVlad/fix-major-log
[mono.git] / mono / metadata / marshal.c
index 5163e5def96b349d596f82d177e3508b950d1037..a847b0f58624a0587765b4bd6e526bda2787d1d6 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * 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"
@@ -211,11 +212,11 @@ init_safe_handle ()
 }
 
 static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean no_wrapper)
 {
        MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
 
-       mono_register_jit_icall (func, name, sig, save);
+       mono_register_jit_icall (func, name, sig, no_wrapper);
 }
 
 MonoMethodSignature*
@@ -237,6 +238,15 @@ mono_marshal_init_tls (void)
        mono_native_tls_alloc (&load_type_info_tls_id, NULL);
 }
 
+static MonoObject*
+mono_object_isinst_icall (MonoObject *obj, MonoClass *klass)
+{
+       MonoError error;
+       MonoObject *result = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 void
 mono_marshal_init (void)
 {
@@ -284,7 +294,7 @@ mono_marshal_init (void)
                register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE);
                register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE);
                register_icall (g_free, "g_free", "void ptr", FALSE);
-               register_icall (mono_object_isinst, "mono_object_isinst", "object object ptr", FALSE);
+               register_icall (mono_object_isinst_icall, "mono_object_isinst_icall", "object object ptr", FALSE);
                register_icall (mono_struct_delete_old, "mono_struct_delete_old", "void ptr ptr", FALSE);
                register_icall (mono_delegate_begin_invoke, "mono_delegate_begin_invoke", "object object ptr", FALSE);
                register_icall (mono_delegate_end_invoke, "mono_delegate_end_invoke", "object object ptr", FALSE);
@@ -352,7 +362,7 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
        if (delegate->method_is_virtual)
                method = mono_object_get_virtual_method (delegate->target, method);
 
-       if (mono_method_signature (method)->pinvoke) {
+       if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                const char *exc_class, *exc_arg;
                gpointer ftnptr;
 
@@ -519,7 +529,11 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
 
                if (use_aot_wrappers) {
                        wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
-                       this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
+                       this_obj = mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_set_pending_exception (&error);
+                               return NULL;
+                       }
                } else {
                        memset (&piinfo, 0, sizeof (piinfo));
                        parse_unmanaged_function_pointer_attr (klass, &piinfo);
@@ -1843,11 +1857,7 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
        }
                
        default: {
-               char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
-               MonoException *exc = mono_get_exception_not_implemented (msg);
-               g_warning ("%s", msg);
-               g_free (msg);
-               mono_raise_exception (exc);
+               g_error ("marshalling conversion %d not implemented", conv);
        }
        }
 }
@@ -2205,7 +2215,9 @@ mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
                method = mono_get_delegate_invoke (klass);
        g_assert (method);
 
-       return mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params);
+       MonoAsyncResult *result = mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 #ifndef DISABLE_JIT
@@ -2334,7 +2346,7 @@ mono_marshal_get_string_to_ptr_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec
        case MONO_NATIVE_BSTR:
                return MONO_MARSHAL_CONV_STR_BSTR;
        default:
-               return (MonoMarshalConv)-1;
+               return MONO_MARSHAL_CONV_INVALID;
        }
 }
 
@@ -2354,7 +2366,7 @@ mono_marshal_get_stringbuilder_to_ptr_conv (MonoMethodPInvoke *piinfo, MonoMarsh
                return MONO_MARSHAL_CONV_SB_LPTSTR;
                break;
        default:
-               return (MonoMarshalConv)-1;
+               return MONO_MARSHAL_CONV_INVALID;
        }
 }
 
@@ -2377,7 +2389,7 @@ mono_marshal_get_ptr_to_string_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec
        case MONO_NATIVE_BSTR:
                return MONO_MARSHAL_CONV_BSTR_STR;
        default:
-               return (MonoMarshalConv)-1;
+               return MONO_MARSHAL_CONV_INVALID;
        }
 }
 
@@ -2403,7 +2415,7 @@ mono_marshal_get_ptr_to_stringbuilder_conv (MonoMethodPInvoke *piinfo, MonoMarsh
                return MONO_MARSHAL_CONV_LPTSTR_SB;
                break;
        default:
-               return (MonoMarshalConv)-1;
+               return MONO_MARSHAL_CONV_INVALID;
        }
 }
 
@@ -5093,7 +5105,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t,
                        mono_mb_emit_ldarg (mb, argnum);
                }
 
-               if (conv == -1) {
+               if (conv == MONO_MARSHAL_CONV_INVALID) {
                        char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
                        mono_mb_emit_exception_marshal_directive (mb, msg);
                } else {
@@ -5105,7 +5117,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t,
 
        case MARSHAL_ACTION_CONV_OUT:
                conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
-               if (conv == -1) {
+               if (conv == MONO_MARSHAL_CONV_INVALID) {
                        char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
                        mono_mb_emit_exception_marshal_directive (mb, msg);
                        break;
@@ -5165,7 +5177,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t,
                mono_mb_emit_stloc (mb, 0);
                                
                conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
-               if (conv == -1) {
+               if (conv == MONO_MARSHAL_CONV_INVALID) {
                        char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
                        mono_mb_emit_exception_marshal_directive (mb, msg);
                        break;
@@ -5194,7 +5206,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t,
                }
 
                conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
-               if (conv == -1) {
+               if (conv == MONO_MARSHAL_CONV_INVALID) {
                        char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
                        mono_mb_emit_exception_marshal_directive (mb, msg);
                        break;
@@ -5522,7 +5534,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                        if (t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))
                                break;
 
-                       if (conv == -1) {
+                       if (conv == MONO_MARSHAL_CONV_INVALID) {
                                char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
                                mono_mb_emit_exception_marshal_directive (mb, msg);
                                break;
@@ -6158,9 +6170,9 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
                        }
                        else
-                               conv = (MonoMarshalConv)-1;
+                               conv = MONO_MARSHAL_CONV_INVALID;
 
-                       if (is_string && conv == -1) {
+                       if (is_string && conv == MONO_MARSHAL_CONV_INVALID) {
                                char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
                                mono_mb_emit_exception_marshal_directive (mb, msg);
                                break;
@@ -6332,7 +6344,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                gboolean need_free2;
                                MonoMarshalConv conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2);
 
-                               g_assert (conv != -1);
+                               g_assert (conv != MONO_MARSHAL_CONV_INVALID);
 
                                /* dest */
                                mono_mb_emit_ldarg (mb, argnum);
@@ -6479,7 +6491,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
                }
                else
-                       conv = (MonoMarshalConv)-1;
+                       conv = MONO_MARSHAL_CONV_INVALID;
 
                mono_marshal_load_type_info (eklass);
 
@@ -6574,7 +6586,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
 
                /* Emit marshalling code */
                if (is_string) {
-                       g_assert (conv != -1);
+                       g_assert (conv != MONO_MARSHAL_CONV_INVALID);
 
                        mono_mb_emit_ldloc (mb, conv_arg);
                        mono_mb_emit_ldloc (mb, index_var);
@@ -6642,7 +6654,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
                }
                else
-                       conv = (MonoMarshalConv)-1;
+                       conv = MONO_MARSHAL_CONV_INVALID;
 
                mono_marshal_load_type_info (eklass);
 
@@ -6690,7 +6702,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
 
                /* Emit marshalling code */
                if (is_string) {
-                       g_assert (conv != -1);
+                       g_assert (conv != MONO_MARSHAL_CONV_INVALID);
 
                        /* dest */
                        mono_mb_emit_ldloc (mb, dest_ptr);
@@ -6724,7 +6736,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                MonoClass *eklass;
                guint32 label1, label2, label3;
                int index_var, src, dest, esize;
-               MonoMarshalConv conv = (MonoMarshalConv)-1;
+               MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID;
                gboolean is_string = FALSE;
                
                g_assert (!t->byref);
@@ -6787,7 +6799,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
 
                /* Emit marshalling code */
                if (is_string) {
-                       g_assert (conv != -1);
+                       g_assert (conv != MONO_MARSHAL_CONV_INVALID);
 
                        /* dest */
                        mono_mb_emit_ldloc (mb, dest);
@@ -7298,7 +7310,16 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
                tmp_locals [i] = emit_marshal (&m, i + param_shift, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_CONV_IN);
        }
 
+       // In coop mode need to register blocking state during native call
        if (mono_threads_is_coop_enabled ()) {
+               // Perform an extra, early lookup of the function address, so any exceptions
+               // potentially resulting from the lookup occur before entering blocking mode.
+               if (!func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass) && aot) {
+                       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+                       mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
+                       mono_mb_emit_byte (mb, CEE_POP); // Result not needed yet
+               }
+
                clause->try_offset = mono_mb_get_label (mb);
 
                mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
@@ -8217,7 +8238,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        EmitMarshalContext m;
 
        g_assert (method != NULL);
-       g_assert (!mono_method_signature (method)->pinvoke);
+       g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
 
        /* 
         * FIXME: Should cache the method+delegate type pair, since the same method
@@ -8578,7 +8599,9 @@ mono_marshal_get_castclass_with_cache (void)
 static MonoObject *
 mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache)
 {
-       MonoObject *isinst = mono_object_isinst (obj, klass);
+       MonoError error;
+       MonoObject *isinst = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
 #ifndef DISABLE_REMOTING
        if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
@@ -9481,7 +9504,7 @@ get_virtual_stelemref_wrapper (int kind)
                /*if (mono_object_isinst (value, aklass)) */
                mono_mb_emit_ldarg (mb, 2);
                mono_mb_emit_ldloc (mb, aklass);
-               mono_mb_emit_icall (mb, mono_object_isinst);
+               mono_mb_emit_icall (mb, mono_object_isinst_icall);
                b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
                /* do_store: */
@@ -9595,7 +9618,7 @@ get_virtual_stelemref_wrapper (int kind)
                /*if (mono_object_isinst (value, aklass)) */
                mono_mb_emit_ldarg (mb, 2);
                mono_mb_emit_ldloc (mb, aklass);
-               mono_mb_emit_icall (mb, mono_object_isinst);
+               mono_mb_emit_icall (mb, mono_object_isinst_icall);
                b2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
                /* if (vklass->idepth < aklass->idepth) goto failue */
@@ -9921,7 +9944,7 @@ mono_marshal_get_stelemref (void)
        
        mono_mb_emit_ldarg (mb, 2);
        mono_mb_emit_ldloc (mb, aklass);
-       mono_mb_emit_icall (mb, mono_object_isinst);
+       mono_mb_emit_icall (mb, mono_object_isinst_icall);
        
        b4 = mono_mb_emit_branch (mb, CEE_BRTRUE);
        mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4));