From a61c283115bfab05a5c6958dc5616821015d4b2d Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Wed, 10 May 2017 18:18:44 -0400 Subject: [PATCH] [runtime] Use coop handles in mono_delegate_ctor_with_method Use coop handles in icall System.Delegate.CreateDelegate_internal TODO: change callsites fo mono_delegate_ctor_with_method_fixme to use handles --- mono/metadata/icall-def.h | 2 +- mono/metadata/icall.c | 62 +++++++++++++++----------------- mono/metadata/marshal.c | 2 +- mono/metadata/object-internals.h | 11 +++++- mono/metadata/object.c | 38 +++++++++++++------- 5 files changed, 66 insertions(+), 49 deletions(-) diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index f4bb94d2ea6..df017b5f794 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -208,7 +208,7 @@ ICALL(DECIMAL_13, "ToSingle", mono_decimal_to_float) 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) +HANDLES(ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal)) ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal) ICALL_TYPE(DEBUGR, "System.Diagnostics.Debugger", DEBUGR_1) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 32f78c27c26..176b754f1bd 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -6170,68 +6170,64 @@ 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; } diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 0886efa1ec5..9b0f090eea5 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -653,7 +653,7 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn) 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); + mono_delegate_ctor_with_method_fixme ((MonoObject*)d, this_obj, compiled_ptr, wrapper, &error); if (mono_error_set_pending_exception (&error)) return NULL; } diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 59b1cc55899..933adf218ff 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -655,7 +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_with_method_fixme (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error); gboolean mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error); @@ -768,12 +771,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; diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 92aa723f20a..e0712a91b24 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -7803,6 +7803,17 @@ mono_print_unhandled_exception (MonoObject *exc) g_free (message); } +gboolean +mono_delegate_ctor_with_method_fixme (MonoObject *this_obj_raw, MonoObject *target_raw, gpointer addr, MonoMethod *method, MonoError *error) +{ + HANDLE_FUNCTION_ENTER (); + error_init (error); + MONO_HANDLE_DCL (MonoObject, this_obj); + MONO_HANDLE_DCL (MonoObject, target); + gboolean res = mono_delegate_ctor_with_method (this_obj, target, addr, method, error); + HANDLE_FUNCTION_RETURN_VAL (res); +} + /** * mono_delegate_ctor_with_method: * \param this pointer to an uninitialized delegate object @@ -7817,43 +7828,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; } @@ -7887,7 +7899,7 @@ mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, Mon g_assert (!mono_class_is_gtd (method->klass)); } - return mono_delegate_ctor_with_method (this_obj, target, addr, method, error); + return mono_delegate_ctor_with_method_fixme (this_obj, target, addr, method, error); } /** -- 2.25.1