Merge pull request #4845 from lambdageek/dev-coop-delegates
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 24 May 2017 19:56:38 +0000 (15:56 -0400)
committerGitHub <noreply@github.com>
Wed, 24 May 2017 19:56:38 +0000 (15:56 -0400)
[marshal] Use coop handles for delegates icalls

mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/marshal.c
mono/metadata/marshal.h
mono/metadata/object-internals.h
mono/metadata/object.c
mono/mini/jit-icalls.c

index b8d6b81b1e76643bf7ea75cdcdfba5500dd831d0..51b333dce30ef07cdbf32d762525d9698e32770e 100644 (file)
@@ -207,9 +207,9 @@ ICALL(DECIMAL_13, "ToSingle", mono_decimal_to_float)
 #endif
 
 ICALL_TYPE(DELEGATE, "System.Delegate", DELEGATE_1)
-ICALL(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal)
-ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal)
-ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal)
+HANDLES(ICALL(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal))
+HANDLES(ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal))
+HANDLES(ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal))
 
 ICALL_TYPE(DEBUGR, "System.Diagnostics.Debugger", DEBUGR_1)
 ICALL(DEBUGR_1, "IsAttached_internal", ves_icall_System_Diagnostics_Debugger_IsAttached_internal)
@@ -683,8 +683,8 @@ ICALL(MARSHAL_7, "FreeHGlobal", ves_icall_System_Runtime_InteropServices_Marshal
 ICALL(MARSHAL_44, "GetCCW", ves_icall_System_Runtime_InteropServices_Marshal_GetCCW)
 ICALL(MARSHAL_8, "GetComSlotForMethodInfoInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetComSlotForMethodInfoInternal)
 #endif
-ICALL(MARSHAL_9, "GetDelegateForFunctionPointerInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal)
-ICALL(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal)
+HANDLES(ICALL(MARSHAL_9, "GetDelegateForFunctionPointerInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal))
+HANDLES(ICALL(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal))
 #ifndef DISABLE_COM
 ICALL(MARSHAL_52, "GetHRForException_WinRT", ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT)
 ICALL(MARSHAL_45, "GetIDispatchForObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal)
@@ -697,9 +697,9 @@ ICALL(MARSHAL_47, "GetObjectForCCW", ves_icall_System_Runtime_InteropServices_Ma
 ICALL(MARSHAL_54, "GetRawIUnknownForComObjectNoAddRef", ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef)
 ICALL(MARSHAL_48, "IsComObject", ves_icall_System_Runtime_InteropServices_Marshal_IsComObject)
 #endif
-ICALL(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf)
-ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink)
-ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll)
+HANDLES(ICALL(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf))
+HANDLES(ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink))
+HANDLES(ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll))
 HANDLES(ICALL(MARSHAL_15, "PtrToStringAnsi(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi))
 ICALL(MARSHAL_16, "PtrToStringAnsi(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len)
 ICALL(MARSHAL_17, "PtrToStringBSTR", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR)
@@ -716,7 +716,7 @@ ICALL(MARSHAL_23, "ReAllocHGlobal", ves_icall_System_Runtime_InteropServices_Mar
 ICALL(MARSHAL_49, "ReleaseComObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal)
 ICALL(MARSHAL_29, "ReleaseInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal)
 #endif
-ICALL(MARSHAL_30, "SizeOf", ves_icall_System_Runtime_InteropServices_Marshal_SizeOf)
+HANDLES(ICALL(MARSHAL_30, "SizeOf", ves_icall_System_Runtime_InteropServices_Marshal_SizeOf))
 ICALL(MARSHAL_31, "StringToBSTR", ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR)
 ICALL(MARSHAL_32, "StringToHGlobalAnsi", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi)
 ICALL(MARSHAL_33, "StringToHGlobalUni", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni)
index 67acdcb521040d6570080ebe4d068ba3bae0648e..79329f935382f75dd2d2ba9e3be1e2825d17d45e 100644 (file)
@@ -6170,99 +6170,92 @@ ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoEr
        return mono_type_get_object_handle (domain, &pklass->byval_arg, error);
 }
 
-ICALL_EXPORT MonoObject *
-ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
-                                                  MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
+ICALL_EXPORT MonoObjectHandle
+ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionTypeHandle ref_type, MonoObjectHandle target,
+                                                  MonoReflectionMethodHandle info, MonoBoolean throwOnBindFailure, MonoError *error)
 {
-       MonoError error;
-       MonoClass *delegate_class = mono_class_from_mono_type (type->type);
-       MonoObject *delegate;
+       MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
+       MonoClass *delegate_class = mono_class_from_mono_type (type);
        gpointer func;
-       MonoMethod *method = info->method;
+       MonoMethod *method = MONO_HANDLE_GETVAL (info, method);
        MonoMethodSignature *sig = mono_method_signature(method);
 
-       mono_class_init_checked (delegate_class, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       mono_class_init_checked (delegate_class, error);
+       return_val_if_nok (error, NULL_HANDLE);
 
        if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
                /* FIXME improve this exception message */
-               mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
+               mono_error_set_execution_engine (error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
                                                 __func__,
                                                 "delegate_class->parent == mono_defaults.multicastdelegate_class");
-               mono_error_set_pending_exception (&error);
-               return NULL;
+               return NULL_HANDLE;
        }
 
        if (mono_security_core_clr_enabled ()) {
-               if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
+               MonoError security_error;
+               if (!mono_security_core_clr_ensure_delegate_creation (method, &security_error)) {
                        if (throwOnBindFailure)
-                               mono_error_set_pending_exception (&error);
+                               mono_error_move (error, &security_error);
                        else
-                               mono_error_cleanup (&error);
-                       return NULL;
+                               mono_error_cleanup (&security_error);
+                       return NULL_HANDLE;
                }
        }
 
        if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
                if (!method->is_inflated) {
-                       mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
-                       return NULL;
+                       mono_error_set_argument (error, "method", " Cannot bind to the target method because its signature differs from that of the delegate type");
+                       return NULL_HANDLE;
                }
        }
 
-       delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoObjectHandle delegate = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (MONO_HANDLE_DOMAIN (ref_type), delegate_class, error));
+       return_val_if_nok (error, NULL_HANDLE);
 
        if (method_is_dynamic (method)) {
                /* Creating a trampoline would leak memory */
-               func = mono_compile_method_checked (method, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
+               func = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, NULL_HANDLE);
        } else {
-               if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
-                       method = mono_object_get_virtual_method (target, method);
-               gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
+               if (!MONO_HANDLE_IS_NULL (target) && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_handle_class (target)) {
+                       method = mono_object_handle_get_virtual_method (target, method, error);
+                       return_val_if_nok (error, NULL_HANDLE);
+               }
+               gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, error);
+               return_val_if_nok (error, NULL_HANDLE);
                func = mono_create_ftnptr (mono_domain_get (), trampoline);
        }
 
-       mono_delegate_ctor_with_method (delegate, target, func, method, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       mono_delegate_ctor_with_method (delegate, target, func, method, error);
+       return_val_if_nok (error, NULL_HANDLE);
        return delegate;
 }
 
-ICALL_EXPORT MonoMulticastDelegate *
-ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
+ICALL_EXPORT MonoMulticastDelegateHandle
+ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegateHandle delegate, MonoError *error)
 {
-       MonoError error;
-       MonoMulticastDelegate *ret;
+       error_init (error);
 
-       g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
+       MonoClass *klass = mono_handle_class (delegate);
+       g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
 
-       ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoMulticastDelegateHandle ret = MONO_HANDLE_NEW (MonoMulticastDelegate,  mono_object_new_checked (MONO_HANDLE_DOMAIN (delegate), klass, error));
+       return_val_if_nok (error, MONO_HANDLE_CAST (MonoMulticastDelegate, NULL_HANDLE));
 
-       ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
+       MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoDelegate, ret), invoke_impl, gpointer, mono_runtime_create_delegate_trampoline (klass));
 
        return ret;
 }
 
-ICALL_EXPORT MonoReflectionMethod*
-ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
+ICALL_EXPORT MonoReflectionMethodHandle
+ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegateHandle delegate, MonoError *error)
 {
-       MonoReflectionMethod *ret = NULL;
-       MonoError error;
-       MonoMethod *m;
+       error_init (error);
 
-       m = mono_object_get_virtual_method (delegate->target, delegate->method);
-       ret = mono_method_get_object_checked (mono_domain_get (), m, m->klass, &error);
-       mono_error_set_pending_exception (&error);
-       return ret;
+       MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+       MonoMethod *m = mono_object_handle_get_virtual_method (delegate_target, MONO_HANDLE_GETVAL (delegate, method), error);
+       return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
+       return mono_method_get_object_handle (mono_domain_get (), m, m->klass, error);
 }
 
 /* System.Buffer */
@@ -7508,38 +7501,34 @@ prelink_method (MonoMethod *method, MonoError *error)
                return;
        mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
        if (exc_class) {
-               mono_error_set_exception_instance (error,
-                       mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+               mono_error_set_generic_error (error, "System", exc_class, "%s", exc_arg);
                return;
        }
        /* create the wrapper, too? */
 }
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
+ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethodHandle method, MonoError *error)
 {
-       MonoError error;
+       error_init (error);
 
-       prelink_method (method->method, &error);
-       mono_error_set_pending_exception (&error);
+       prelink_method (MONO_HANDLE_GETVAL (method, method), error);
 }
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
+ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoError error;
-       MonoClass *klass = mono_class_from_mono_type (type->type);
+       error_init (error);
+       MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
        MonoMethod* m;
        gpointer iter = NULL;
 
-       mono_class_init_checked (klass, &error);
-       if (mono_error_set_pending_exception (&error))
-               return;
+       mono_class_init_checked (klass, error);
+       return_if_nok (error);
 
        while ((m = mono_class_get_methods (klass, &iter))) {
-               prelink_method (m, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return;
+               prelink_method (m, error);
+               return_if_nok (error);
        }
 }
 
index cabce432d44f6eda5d7b6c668cbe7d745feefa70..f60de81c46bdd63387cdb457671478449335dcdb 100644 (file)
@@ -89,7 +89,7 @@ static void ftnptr_eh_callback_default (guint32 gchandle);
 static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
 
 static void
-delegate_hash_table_add (MonoDelegate *d);
+delegate_hash_table_add (MonoDelegateHandle d);
 
 static void
 delegate_hash_table_remove (MonoDelegate *d);
@@ -179,9 +179,15 @@ mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size);
 gpointer
 mono_delegate_to_ftnptr (MonoDelegate *delegate);
 
+gpointer
+mono_delegate_handle_to_ftnptr (MonoDelegateHandle delegate, MonoError *error);
+
 MonoDelegate*
 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
 
+MonoDelegateHandle
+mono_ftnptr_to_delegate_handle (MonoClass *klass, gpointer ftn, MonoError *error);
+
 gpointer
 mono_array_to_savearray (MonoArray *array);
 
@@ -431,25 +437,44 @@ mono_marshal_unlock_internal (void)
 
 /* This is a JIT icall, it sets the pending exception and return NULL on error */
 gpointer
-mono_delegate_to_ftnptr (MonoDelegate *delegate)
+mono_delegate_to_ftnptr (MonoDelegate *delegate_raw)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MONO_HANDLE_DCL (MonoDelegate, delegate);
+       gpointer result = mono_delegate_handle_to_ftnptr (delegate, &error);
+       mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN_VAL (result);
+}
+
+gpointer
+mono_delegate_handle_to_ftnptr (MonoDelegateHandle delegate, MonoError *error)
+{
+       HANDLE_FUNCTION_ENTER ();
+       gpointer result = NULL;
+       error_init (error);
        MonoMethod *method, *wrapper;
        MonoClass *klass;
        uint32_t target_handle = 0;
 
-       if (!delegate)
-               return NULL;
+       if (MONO_HANDLE_IS_NULL (delegate))
+               goto leave;
 
-       if (delegate->delegate_trampoline)
-               return delegate->delegate_trampoline;
+       if (MONO_HANDLE_GETVAL (delegate, delegate_trampoline)) {
+               result = MONO_HANDLE_GETVAL (delegate, delegate_trampoline);
+               goto leave;
+       }
 
-       klass = ((MonoObject *)delegate)->vtable->klass;
+       klass = mono_handle_class (delegate);
        g_assert (klass->delegate);
 
-       method = delegate->method;
-       if (delegate->method_is_virtual)
-               method = mono_object_get_virtual_method (delegate->target, method);
+       method = MONO_HANDLE_GETVAL (delegate, method);
+       if (MONO_HANDLE_GETVAL (delegate, method_is_virtual)) {
+               MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+               method = mono_object_handle_get_virtual_method (delegate_target, method, error);
+               if (!is_ok (error))
+                       goto leave;
+       }
 
        if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                const char *exc_class, *exc_arg;
@@ -458,38 +483,39 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
                ftnptr = mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
                if (!ftnptr) {
                        g_assert (exc_class);
-                       mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
-                       return NULL;
+                       mono_error_set_generic_error (error, "System", exc_class, "%s", exc_arg);
+                       goto leave;
                }
-               return ftnptr;
+               result = ftnptr;
+               goto leave;
        }
 
-       if (delegate->target) {
+       MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+       if (!MONO_HANDLE_IS_NULL (delegate_target)) {
                /* Produce a location which can be embedded in JITted code */
-               target_handle = mono_gchandle_new_weakref (delegate->target, FALSE);
+               target_handle = mono_gchandle_new_weakref (MONO_HANDLE_RAW (delegate_target), FALSE); /* FIXME: a version of mono_gchandle_new_weakref that takes a coop handle */
        }
 
-       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, &error);
-       if (!is_ok (&error))
-               goto fail;
+       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, error);
+       if (!is_ok (error))
+               goto leave;
 
-       delegate->delegate_trampoline = mono_compile_method_checked (wrapper, &error);
-       if (!is_ok (&error))
-               goto fail;
+       MONO_HANDLE_SETVAL (delegate, delegate_trampoline, gpointer, mono_compile_method_checked (wrapper, error));
+       if (!is_ok (error))
+               goto leave;
 
        // Add the delegate to the delegate hash table
        delegate_hash_table_add (delegate);
 
        /* when the object is collected, collect the dynamic method, too */
-       mono_object_register_finalizer ((MonoObject*)delegate);
+       mono_object_register_finalizer ((MonoObject*) MONO_HANDLE_RAW (delegate));
 
-       return delegate->delegate_trampoline;
+       result = MONO_HANDLE_GETVAL (delegate, delegate_trampoline);
 
-fail:
-       if (target_handle != 0)
+leave:
+       if (!is_ok (error) && target_handle != 0)
                mono_gchandle_free (target_handle);
-       mono_error_set_pending_exception (&error);
-       return NULL;
+       HANDLE_FUNCTION_RETURN_VAL (result);
 }
 
 /* 
@@ -521,7 +547,7 @@ delegate_hash_table_remove (MonoDelegate *d)
 }
 
 static void
-delegate_hash_table_add (MonoDelegate *d)
+delegate_hash_table_add (MonoDelegateHandle d)
 {
        guint32 gchandle;
        guint32 old_gchandle;
@@ -529,14 +555,15 @@ delegate_hash_table_add (MonoDelegate *d)
        mono_marshal_lock ();
        if (delegate_hash_table == NULL)
                delegate_hash_table = delegate_hash_table_new ();
+       gpointer delegate_trampoline = MONO_HANDLE_GETVAL (d, delegate_trampoline);
        if (mono_gc_is_moving ()) {
-               gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE);
-               old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
-               g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle));
+               gchandle = mono_gchandle_new_weakref ((MonoObject*) MONO_HANDLE_RAW (d), FALSE);
+               old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, delegate_trampoline));
+               g_hash_table_insert (delegate_hash_table, delegate_trampoline, GUINT_TO_POINTER (gchandle));
                if (old_gchandle)
                        mono_gchandle_free (old_gchandle);
        } else {
-               g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d);
+               g_hash_table_insert (delegate_hash_table, delegate_trampoline, MONO_HANDLE_RAW (d));
        }
        mono_marshal_unlock ();
 }
@@ -590,12 +617,23 @@ parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piin
 MonoDelegate*
 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MonoDelegateHandle result = mono_ftnptr_to_delegate_handle (klass, ftn, &error);
+       mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
+}
+
+MonoDelegateHandle
+mono_ftnptr_to_delegate_handle (MonoClass *klass, gpointer ftn, MonoError *error)
+{
+       HANDLE_FUNCTION_ENTER ();
+       error_init (error);
        guint32 gchandle;
-       MonoDelegate *d;
+       MonoDelegateHandle d = MONO_HANDLE_NEW (MonoDelegate, NULL);
 
        if (ftn == NULL)
-               return NULL;
+               goto leave;
 
        mono_marshal_lock ();
        if (delegate_hash_table == NULL)
@@ -605,30 +643,26 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, ftn));
                mono_marshal_unlock ();
                if (gchandle)
-                       d = (MonoDelegate*)mono_gchandle_get_target (gchandle);
-               else
-                       d = NULL;
+                       MONO_HANDLE_ASSIGN (d, MONO_HANDLE_CAST (MonoDelegate, mono_gchandle_get_target_handle (gchandle)));
        } else {
-               d = (MonoDelegate *)g_hash_table_lookup (delegate_hash_table, ftn);
+               MONO_HANDLE_ASSIGN (d, MONO_HANDLE_NEW (MonoDelegate, g_hash_table_lookup (delegate_hash_table, ftn)));
                mono_marshal_unlock ();
        }
-       if (d == NULL) {
+       if (MONO_HANDLE_IS_NULL (d)) {
                /* This is a native function, so construct a delegate for it */
                MonoMethodSignature *sig;
                MonoMethod *wrapper;
                MonoMarshalSpec **mspecs;
                MonoMethod *invoke = mono_get_delegate_invoke (klass);
                MonoMethodPInvoke piinfo;
-               MonoObject *this_obj;
+               MonoObjectHandle  this_obj;
                int i;
 
                if (use_aot_wrappers) {
                        wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
-                       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;
-                       }
+                       this_obj = MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, error));
+                       if (!is_ok (error))
+                               goto leave;
                } else {
                        memset (&piinfo, 0, sizeof (piinfo));
                        parse_unmanaged_function_pointer_attr (klass, &piinfo);
@@ -640,7 +674,7 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                        sig->hasthis = 0;
 
                        wrapper = mono_marshal_get_native_func_wrapper (klass->image, sig, &piinfo, mspecs, ftn);
-                       this_obj = NULL;
+                       this_obj = MONO_HANDLE_NEW (MonoObject, NULL);
 
                        for (i = mono_method_signature (invoke)->param_count; i >= 0; i--)
                                if (mspecs [i])
@@ -649,25 +683,24 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                        g_free (sig);
                }
 
-               d = (MonoDelegate*)mono_object_new_checked (mono_domain_get (), klass, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return NULL;
-               }
-               gpointer compiled_ptr = mono_compile_method_checked (wrapper, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
-               mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, compiled_ptr, wrapper, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
-       }
+               MONO_HANDLE_ASSIGN (d, MONO_HANDLE_NEW (MonoDelegate, mono_object_new_checked (mono_domain_get (), klass, error)));
+               if (!is_ok (error))
+                       goto leave;
+               gpointer compiled_ptr = mono_compile_method_checked (wrapper, error);
+               if (!is_ok (error))
+                       goto leave;
 
-       if (d->object.vtable->domain != mono_domain_get ()) {
-               mono_set_pending_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain"));
-               return NULL;
+               mono_delegate_ctor_with_method (MONO_HANDLE_CAST (MonoObject, d), this_obj, compiled_ptr, wrapper, error);
+               if (!is_ok (error))
+                       goto leave;
        }
 
-       return d;
+       g_assert (!MONO_HANDLE_IS_NULL (d));
+       if (MONO_HANDLE_DOMAIN (d) != mono_domain_get ())
+               mono_error_set_not_supported (error, "Delegates cannot be marshalled from native code into a domain other than their home domain");
+
+leave:
+       HANDLE_FUNCTION_RETURN_REF (MonoDelegate, d);
 }
 
 void
@@ -11025,18 +11058,23 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
 }
 
 guint32 
-ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
+ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionTypeHandle rtype, MonoError *error)
 {
        MonoClass *klass;
        MonoType *type;
        guint32 layout;
 
-       MONO_CHECK_ARG_NULL (rtype, 0);
+       error_init (error);
+
+       if (MONO_HANDLE_IS_NULL (rtype)) {
+               mono_error_set_argument_null (error, "type", "");
+               return 0;
+       }
 
-       type = rtype->type;
+       type = MONO_HANDLE_GETVAL (rtype, type);
        klass = mono_class_from_mono_type (type);
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return 0;
        }
 
@@ -11045,13 +11083,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
        if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
                return sizeof (gpointer);
        } else if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
-               gchar *msg;
-               MonoException *exc;
-
-               msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
-               exc = mono_get_exception_argument ("t", msg);
-               g_free (msg);
-               mono_set_pending_exception (exc);
+               mono_error_set_argument (error, "t", "Type %s cannot be marshaled as an unmanaged structure.", klass->name);
                return 0;
        }
 
@@ -11157,26 +11189,29 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s
 }
 
 int
-ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
+ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHandle ref_type, MonoStringHandle field_name, MonoError *error)
 {
-       MonoError error;
-       MonoMarshalType *info;
-       MonoClass *klass;
-       char *fname;
-       int match_index = -1;
-       
-       MONO_CHECK_ARG_NULL (type, 0);
-       MONO_CHECK_ARG_NULL (field_name, 0);
-
-       fname = mono_string_to_utf8_checked (field_name, &error);
-       if (mono_error_set_pending_exception (&error))
+       error_init (error);
+       if (MONO_HANDLE_IS_NULL (ref_type)) {
+               mono_error_set_argument_null (error, "type", "");
                return 0;
-       klass = mono_class_from_mono_type (type->type);
+       }
+       if (MONO_HANDLE_IS_NULL (field_name)) {
+               mono_error_set_argument_null (error, "fieldName", "");
+               return 0;
+       }
+
+       char *fname = mono_string_handle_to_utf8 (field_name, error);
+       return_val_if_nok (error, 0);
+
+       MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
+       MonoClass *klass = mono_class_from_mono_type (type);
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return 0;
        }
 
+       int match_index = -1;
        while (klass && match_index == -1) {
                MonoClassField* field;
                int i = 0;
@@ -11198,21 +11233,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
        g_free (fname);
 
        if(match_index == -1) {
-               MonoException* exc;
-               gchar *tmp;
-
                /* Get back original class instance */
-               klass = mono_class_from_mono_type (type->type);
+               klass = mono_class_from_mono_type (type);
 
-               tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
-               exc = mono_get_exception_argument ("fieldName", tmp);
-               g_free (tmp);
-               mono_set_pending_exception ((MonoException*)exc);
+               mono_error_set_argument (error, "fieldName", "Field passed in is not a marshaled member of the type %s", klass->name);
                return 0;
        }
 
-       info = mono_marshal_load_type_info (klass);     
+       MonoMarshalType *info = mono_marshal_load_type_info (klass);
        return info->fields [match_index].offset;
 }
 
@@ -11438,22 +11466,24 @@ ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
        return mono_array_addr_with_size_fast (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
 }
 
-MonoDelegate*
-ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type)
+MonoDelegateHandle
+ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoClass *klass = mono_type_get_class (type->type);
+       error_init (error);
+       MonoClass *klass = mono_type_get_class (MONO_HANDLE_GETVAL (type, type));
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
-       return mono_ftnptr_to_delegate (klass, ftn);
+       return mono_ftnptr_to_delegate_handle (klass, ftn, error);
 }
 
 gpointer
-ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate)
+ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegateHandle delegate, MonoError *error)
 {
-       return mono_delegate_to_ftnptr (delegate);
+       error_init (error);
+       return mono_delegate_handle_to_ftnptr (delegate, error);
 }
 
 /**
index 57018b828d41dbe1d0ee050ce98a27161586be3e..657193859061b252a75605813143c38043dd4af0 100644 (file)
@@ -458,7 +458,7 @@ guint32
 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void);
 
 guint32 
-ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype);
+ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionTypeHandle rtype, MonoError *error);
 
 void
 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old);
@@ -470,7 +470,7 @@ MonoObject *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type);
 
 int
-ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name);
+ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHandle type, MonoStringHandle field_name, MonoError *error);
 
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString *string);
@@ -514,11 +514,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (void *ptr);
 void*
 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index);
 
-MonoDelegate*
-ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type);
+MonoDelegateHandle
+ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionTypeHandle type, MonoError *error);
 
 gpointer
-ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate);
+ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegateHandle delegate, MonoError *error);
 
 int
 ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (gpointer pUnk);
index 59b1cc558995810ce60a38bd480b4515d0c5ccbc..7af56df2a72e2c59963beca822adaea5cf906cdd 100644 (file)
@@ -655,10 +655,10 @@ void
 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args, MonoError *error);
 
 gboolean
-mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error);
+mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error);
 
 gboolean
-mono_delegate_ctor         (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error);
+mono_delegate_ctor         (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error);
 
 void*
 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words);
@@ -768,12 +768,18 @@ struct _MonoDelegate {
        MonoBoolean method_is_virtual;
 };
 
+/* Safely access System.Delegate from native code */
+TYPED_HANDLE_DECL (MonoDelegate);
+
 typedef struct _MonoMulticastDelegate MonoMulticastDelegate;
 struct _MonoMulticastDelegate {
        MonoDelegate delegate;
        MonoArray *delegates;
 };
 
+/* Safely access System.MulticastDelegate from native code */
+TYPED_HANDLE_DECL (MonoMulticastDelegate);
+
 struct _MonoReflectionField {
        MonoObject object;
        MonoClass *klass;
index 92aa723f20a73f61c7ffec75631e46b6ee77ec94..d30f0413ac22f999432912235b52810720881244 100644 (file)
@@ -7817,43 +7817,44 @@ mono_print_unhandled_exception (MonoObject *exc)
  * On failure returns FALSE and sets \p error.
  */
 gboolean
-mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error)
+mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        error_init (error);
-       MonoDelegate *delegate = (MonoDelegate *)this_obj;
+       MonoDelegateHandle delegate = MONO_HANDLE_CAST (MonoDelegate, this_obj);
 
-       g_assert (this_obj);
+       g_assert (!MONO_HANDLE_IS_NULL (this_obj));
        g_assert (addr);
 
-       g_assert (mono_class_has_parent (mono_object_class (this_obj), mono_defaults.multicastdelegate_class));
+       MonoClass *klass = mono_handle_class (this_obj);
+       g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
 
        if (method)
-               delegate->method = method;
+               MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method);
 
        mono_stats.delegate_creations++;
 
 #ifndef DISABLE_REMOTING
-       if (target && mono_object_is_transparent_proxy (target)) {
+       if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) {
                g_assert (method);
                method = mono_marshal_get_remoting_invoke (method);
 #ifdef ENABLE_INTERPRETER
                //g_error ("need RuntimeMethod in method_ptr when using interpreter");
 #endif
-               delegate->method_ptr = mono_compile_method_checked (method, error);
+               MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, mono_compile_method_checked (method, error));
                return_val_if_nok (error, FALSE);
-               MONO_OBJECT_SETREF (delegate, target, target);
+               MONO_HANDLE_SET (delegate, target, target);
        } else
 #endif
        {
-               delegate->method_ptr = addr;
-               MONO_OBJECT_SETREF (delegate, target, target);
+               MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr);
+               MONO_HANDLE_SET (delegate, target, target);
        }
 
-       delegate->invoke_impl = callbacks.create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass);
+       MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, callbacks.create_delegate_trampoline (MONO_HANDLE_DOMAIN (delegate), mono_handle_class (delegate)));
        if (callbacks.init_delegate)
-               callbacks.init_delegate (delegate);
+               callbacks.init_delegate (MONO_HANDLE_RAW (delegate)); /* FIXME: update init_delegate callback to take a MonoDelegateHandle */
        return TRUE;
 }
 
@@ -7867,7 +7868,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
  * On failure returns FALSE and sets \p error.
  */
 gboolean
-mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error)
+mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
index 401ac247e2a0569fb100aa530f9df08cb1682c03..648e69cf18cc49cff4c27e6ee517637df2d83a68 100644 (file)
@@ -1458,11 +1458,15 @@ mono_generic_class_init (MonoVTable *vtable)
 }
 
 void
-ves_icall_mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
+ves_icall_mono_delegate_ctor (MonoObject *this_obj_raw, MonoObject *target_raw, gpointer addr)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MONO_HANDLE_DCL (MonoObject, this_obj);
+       MONO_HANDLE_DCL (MonoObject, target);
        mono_delegate_ctor (this_obj, target, addr, &error);
        mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN ();
 }
 
 gpointer