From bf862b420622b19ec6611646942eff1cee710619 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Wed, 11 Jan 2017 10:38:49 -0500 Subject: [PATCH] [remoting] Coop handles for proxy objects (#4208) * [remoting] Use coop handles in several functions - icall System.Runtime.Remoting.Proxies.RealProxy.InternalGetTransparentProxy - mono_remote_class - mono_remote_class_vtable - mono_upgrade_remote_class - mono_object_handle_get_virtual_method - mono_object_handle_isinst - mono_object_handle_isinst_mbyref * [reflection] Use handles in System.RuntimeTypeHandle.IsInstanceOfType * [runtime] Rewrite mono_object_castclass_mbyref in terms of mono_object_handle_isinst_mbyref. This is an external API function that isn't used inside the runtime. * [runtime] Remove mono_object_isinst_mbyref_checked It was a runtime internal funciton. All of its former callers have been converted to use mono_object_handle_isinst_mbyref. --- mono/metadata/class-internals.h | 3 - mono/metadata/icall-def.h | 4 +- mono/metadata/icall.c | 76 +++++----- mono/metadata/object-internals.h | 20 ++- mono/metadata/object.c | 235 ++++++++++++++++++++----------- mono/metadata/remoting.c | 15 +- 6 files changed, 216 insertions(+), 137 deletions(-) diff --git a/mono/metadata/class-internals.h b/mono/metadata/class-internals.h index efb4c62874f..7a1456cbb76 100644 --- a/mono/metadata/class-internals.h +++ b/mono/metadata/class-internals.h @@ -1119,9 +1119,6 @@ typedef struct { #define mono_class_is_real_proxy(klass) (FALSE) #define mono_object_is_transparent_proxy(object) (FALSE) #else -MonoRemoteClass* -mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class, MonoError *error); - #define mono_class_is_transparent_proxy(klass) ((klass) == mono_defaults.transparent_proxy_class) #define mono_class_is_real_proxy(klass) ((klass) == mono_defaults.real_proxy_class) #define mono_object_is_transparent_proxy(object) (((MonoObject*)object)->vtable->klass == mono_defaults.transparent_proxy_class) diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 81820330ccb..9e69287c7a2 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -750,7 +750,7 @@ ICALL(ARES_1, "Invoke", ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_ #ifndef DISABLE_REMOTING ICALL_TYPE(REALP, "System.Runtime.Remoting.Proxies.RealProxy", REALP_1) ICALL(REALP_1, "InternalGetProxyType", ves_icall_Remoting_RealProxy_InternalGetProxyType) -ICALL(REALP_2, "InternalGetTransparentProxy", ves_icall_Remoting_RealProxy_GetTransparentProxy) +HANDLES(ICALL(REALP_2, "InternalGetTransparentProxy", ves_icall_Remoting_RealProxy_GetTransparentProxy)) ICALL_TYPE(REMSER, "System.Runtime.Remoting.RemotingServices", REMSER_0) ICALL(REMSER_0, "GetVirtualMethod", ves_icall_Remoting_RemotingServices_GetVirtualMethod) @@ -813,7 +813,7 @@ HANDLES(ICALL(RTH_11, "IsByRef", ves_icall_RuntimeTypeHandle_IsByRef)) HANDLES(ICALL(RTH_12, "IsComObject", ves_icall_RuntimeTypeHandle_IsComObject)) HANDLES(ICALL(RTH_13, "IsGenericTypeDefinition", ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition)) HANDLES(ICALL(RTH_14, "IsGenericVariable", ves_icall_RuntimeTypeHandle_IsGenericVariable)) -ICALL(RTH_15, "IsInstanceOfType", ves_icall_RuntimeTypeHandle_IsInstanceOfType) +HANDLES(ICALL(RTH_15, "IsInstanceOfType", ves_icall_RuntimeTypeHandle_IsInstanceOfType)) HANDLES(ICALL(RTH_16, "IsPointer", ves_icall_RuntimeTypeHandle_IsPointer)) HANDLES(ICALL(RTH_17, "IsPrimitive", ves_icall_RuntimeTypeHandle_IsPrimitive)) HANDLES(ICALL(RTH_18, "type_is_assignable_from", ves_icall_RuntimeTypeHandle_type_is_assignable_from)) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 3c81b3bc807..0e6c3077c58 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -1647,18 +1647,16 @@ ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle re } ICALL_EXPORT guint32 -ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj) +ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionTypeHandle ref_type, MonoObjectHandle obj, MonoError *error) { - MonoError error; - MonoClass *klass = mono_class_from_mono_type (type->type); - mono_class_init_checked (klass, &error); - if (!is_ok (&error)) { - mono_error_set_pending_exception (&error); - return FALSE; - } - guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL); - mono_error_set_pending_exception (&error); - return result; + mono_error_init (error); + MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); + MonoClass *klass = mono_class_from_mono_type (type); + mono_class_init_checked (klass, error); + return_val_if_nok (error, FALSE); + MonoObjectHandle inst = mono_object_handle_isinst (obj, klass, error); + return_val_if_nok (error, FALSE); + return !MONO_HANDLE_IS_NULL (inst); } ICALL_EXPORT guint32 @@ -6336,44 +6334,46 @@ ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, Mo } #ifndef DISABLE_REMOTING -ICALL_EXPORT MonoObject * -ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name) +ICALL_EXPORT MonoObjectHandle +ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObjectHandle this_obj, MonoStringHandle class_name, MonoError *error) { - MonoError error; - MonoDomain *domain = mono_object_domain (this_obj); - MonoObject *res; - MonoRealProxy *rp = ((MonoRealProxy *)this_obj); - MonoTransparentProxy *tp; - MonoType *type; - MonoClass *klass; + mono_error_init (error); + MonoDomain *domain = MONO_HANDLE_DOMAIN (this_obj); + MonoRealProxyHandle rp = MONO_HANDLE_CAST (MonoRealProxy, this_obj); - res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + MonoObjectHandle res = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, error)); + if (!is_ok (error)) + return NULL_HANDLE; - tp = (MonoTransparentProxy*) res; + MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, res); - MONO_OBJECT_SETREF (tp, rp, rp); - type = ((MonoReflectionType *)rp->class_to_proxy)->type; - klass = mono_class_from_mono_type (type); + MONO_HANDLE_SET (tp, rp, rp); + + MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL); + MONO_HANDLE_GET (reftype, rp, class_to_proxy); + MonoType *type = MONO_HANDLE_GETVAL (reftype, type); + MonoClass *klass = mono_class_from_mono_type (type); // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early mono_class_setup_vtable (klass); if (mono_class_has_failure (klass)) { - mono_set_pending_exception (mono_class_get_exception_for_failure (klass)); - return NULL; + mono_error_set_for_class_failure (error, klass); + return NULL_HANDLE; } - tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL); - if (mono_error_set_pending_exception (&error)) - return NULL; - tp->remote_class = mono_remote_class (domain, class_name, klass, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + MonoObjectHandle remoting_obj = mono_object_handle_isinst (this_obj, mono_defaults.iremotingtypeinfo_class, error); + if (!is_ok (error)) + return NULL_HANDLE; + MONO_HANDLE_SETVAL (tp, custom_type_info, MonoBoolean, !MONO_HANDLE_IS_NULL (remoting_obj)); - res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error); - if (mono_error_set_pending_exception (&error)) - return NULL; + MonoRemoteClass *remote_class = mono_remote_class (domain, class_name, klass, error); + if (!is_ok (error)) + return NULL_HANDLE; + MONO_HANDLE_SETVAL (tp, remote_class, MonoRemoteClass*, remote_class); + + MONO_HANDLE_SETVAL (res, vtable, MonoVTable*, mono_remote_class_vtable (domain, remote_class, rp, error)); + if (!is_ok (error)) + return NULL_HANDLE; return res; } diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index 4031b3245a3..8fd79559632 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -286,6 +286,9 @@ typedef struct { MonoObject *stub_data; } MonoRealProxy; +/* Safely access System.Runtime.Remoting.Proxies.RealProxy from native code */ +TYPED_HANDLE_DECL (MonoRealProxy); + typedef struct { MonoMarshalByRefObject object; gpointer iunknown; @@ -1490,14 +1493,17 @@ MonoArray* ves_icall_array_new_specific (MonoVTable *vtable, uintptr_t n); #ifndef DISABLE_REMOTING +MonoRemoteClass* +mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *proxy_class, MonoError *error); + MonoObject * mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args, MonoError *error); gpointer -mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *real_proxy, MonoError *error); +mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxyHandle real_proxy, MonoError *error); gboolean -mono_upgrade_remote_class (MonoDomain *domain, MonoObject *tproxy, MonoClass *klass, MonoError *error); +mono_upgrade_remote_class (MonoDomain *domain, MonoObjectHandle tproxy, MonoClass *klass, MonoError *error); void* mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void **res, MonoError *error); @@ -1650,6 +1656,9 @@ mono_field_static_get_value_checked (MonoVTable *vt, MonoClassField *field, void void mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value, MonoError *error); +MonoMethod* +mono_object_handle_get_virtual_method (MonoObjectHandle obj, MonoMethod *method, MonoError *error); + /* exported, used by the debugger */ MONO_API void * mono_vtable_get_static_field_data (MonoVTable *vt); @@ -1723,8 +1732,11 @@ mono_object_clone_checked (MonoObject *obj, MonoError *error); MonoObject * mono_object_isinst_checked (MonoObject *obj, MonoClass *klass, MonoError *error); -MonoObject * -mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError *error); +MonoObjectHandle +mono_object_handle_isinst (MonoObjectHandle obj, MonoClass *klass, MonoError *error); + +MonoObjectHandle +mono_object_handle_isinst_mbyref (MonoObjectHandle obj, MonoClass *klass, MonoError *error); MonoString * mono_string_new_size_checked (MonoDomain *domain, gint32 len, MonoError *error); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 0a6df1231ea..422b9a21a27 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -64,6 +64,9 @@ free_main_args (void); static char * mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error); +static MonoMethod* +class_get_virtual_method (MonoClass *klass, MonoMethod *method, gboolean is_proxy, MonoError *error); + /* Class lazy loading functions */ static GENERATE_GET_CLASS_WITH_CACHE (pointer, System.Reflection, Pointer) static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, System.Runtime.Remoting, RemotingServices) @@ -2485,7 +2488,7 @@ copy_remote_class_key (MonoDomain *domain, gpointer *key) * On failure returns NULL and sets @error */ MonoRemoteClass* -mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class, MonoError *error) +mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *proxy_class, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; @@ -2506,7 +2509,7 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_ return rc; } - name = mono_string_to_utf8_mp (domain->mp, class_name, error); + name = mono_string_to_utf8_mp (domain->mp, MONO_HANDLE_RAW (class_name), error); if (!is_ok (error)) { g_free (key); mono_domain_unlock (domain); @@ -2532,7 +2535,7 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_ rc->xdomain_vtable = NULL; rc->proxy_class_name = name; #ifndef DISABLE_PERFCOUNTERS - mono_perfcounters->loader_bytes += mono_string_length (class_name) + 1; + mono_perfcounters->loader_bytes += mono_string_length (MONO_HANDLE_RAW (class_name)) + 1; #endif g_hash_table_insert (domain->proxy_vtable_hash, key, rc); @@ -2598,7 +2601,7 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass } gpointer -mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp, MonoError *error) +mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxyHandle rp, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; @@ -2606,7 +2609,8 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon mono_loader_lock (); /*FIXME mono_class_from_mono_type and mono_class_proxy_vtable take it*/ mono_domain_lock (domain); - if (rp->target_domain_id != -1) { + gint32 target_domain_id = MONO_HANDLE_GETVAL (rp, target_domain_id); + if (target_domain_id != -1) { if (remote_class->xdomain_vtable == NULL) remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN, error); mono_domain_unlock (domain); @@ -2615,10 +2619,11 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon return remote_class->xdomain_vtable; } if (remote_class->default_vtable == NULL) { - MonoType *type; - MonoClass *klass; - type = ((MonoReflectionType *)rp->class_to_proxy)->type; - klass = mono_class_from_mono_type (type); + MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL); + MONO_HANDLE_GET (reftype, rp, class_to_proxy); + + MonoType *type = MONO_HANDLE_GETVAL (reftype, type); + MonoClass *klass = mono_class_from_mono_type (type); #ifndef DISABLE_COM if ((mono_class_is_com_object (klass) || (mono_class_get_com_object_class () && klass == mono_class_get_com_object_class ())) && !mono_vtable_is_remote (mono_class_vtable (mono_domain_get (), klass))) remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP, error); @@ -2650,21 +2655,16 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon * class or an interface. On success returns TRUE, on failure returns FALSE and sets @error. */ gboolean -mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass, MonoError *error) +mono_upgrade_remote_class (MonoDomain *domain, MonoObjectHandle proxy_object, MonoClass *klass, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - MonoTransparentProxy *tproxy; - MonoRemoteClass *remote_class; - gboolean redo_vtable; - mono_error_init (error); - mono_loader_lock (); /*FIXME mono_remote_class_vtable requires it.*/ - mono_domain_lock (domain); - tproxy = (MonoTransparentProxy*) proxy_object; - remote_class = tproxy->remote_class; + MonoTransparentProxyHandle tproxy = MONO_HANDLE_CAST (MonoTransparentProxy, proxy_object); + MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (tproxy, remote_class); + gboolean redo_vtable; if (mono_class_is_interface (klass)) { int i; redo_vtable = TRUE; @@ -2676,9 +2676,14 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla redo_vtable = (remote_class->proxy_class != klass); } + mono_loader_lock (); /*FIXME mono_remote_class_vtable requires it.*/ + mono_domain_lock (domain); if (redo_vtable) { - tproxy->remote_class = clone_remote_class (domain, remote_class, klass); - proxy_object->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp, error); + MonoRemoteClass *fresh_remote_class = clone_remote_class (domain, remote_class, klass); + MONO_HANDLE_SETVAL (tproxy, remote_class, MonoRemoteClass*, fresh_remote_class); + MonoRealProxyHandle real_proxy = MONO_HANDLE_NEW (MonoRealProxy, NULL); + MONO_HANDLE_GET (real_proxy, tproxy, rp); + MONO_HANDLE_SETVAL (proxy_object, vtable, MonoVTable*, mono_remote_class_vtable (domain, fresh_remote_class, real_proxy, error)); if (!is_ok (error)) goto leave; } @@ -2700,28 +2705,53 @@ leave: * the instance of a callvirt of method. */ MonoMethod* -mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) +mono_object_get_virtual_method (MonoObject *obj_raw, MonoMethod *method) { MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); + MonoError error; + MONO_HANDLE_DCL (MonoObject, obj); + MonoMethod *result = mono_object_handle_get_virtual_method (obj, method, &error); + mono_error_assert_ok (&error); + HANDLE_FUNCTION_RETURN_VAL (result); +} - MonoClass *klass; - MonoMethod **vtable; - gboolean is_proxy = FALSE; - MonoMethod *res = NULL; +/** + * mono_object_get_virtual_method: + * @obj: object to operate on. + * @method: method + * + * Retrieves the MonoMethod that would be called on obj if obj is passed as + * the instance of a callvirt of method. + */ +MonoMethod* +mono_object_handle_get_virtual_method (MonoObjectHandle obj, MonoMethod *method, MonoError *error) +{ + mono_error_init (error); - klass = mono_object_class (obj); + gboolean is_proxy = FALSE; + MonoClass *klass = mono_handle_class (obj); #ifndef DISABLE_REMOTING if (klass == mono_defaults.transparent_proxy_class) { - klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class; + MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoTransparentProxy, obj), remote_class); + klass = remote_class->proxy_class; is_proxy = TRUE; } #endif + return class_get_virtual_method (klass, method, is_proxy, error); +} + +static MonoMethod* +class_get_virtual_method (MonoClass *klass, MonoMethod *method, gboolean is_proxy, MonoError *error) +{ + mono_error_init (error); + if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL))) return method; mono_class_setup_vtable (klass); - vtable = klass->vtable; + MonoMethod **vtable = klass->vtable; if (method->slot == -1) { /* method->slot might not be set for instances of generic methods */ @@ -2734,6 +2764,7 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) } } + MonoMethod *res = NULL; /* check method->slot is a valid index: perform isinstance? */ if (method->slot != -1) { if (mono_class_is_interface (method->klass)) { @@ -2769,15 +2800,11 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) #endif { if (method->is_inflated) { - MonoError error; /* Have to inflate the result */ - res = mono_class_inflate_generic_method_checked (res, &((MonoMethodInflated*)method)->context, &error); - g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */ + res = mono_class_inflate_generic_method_checked (res, &((MonoMethodInflated*)method)->context, error); } } - g_assert (res); - return res; } @@ -6449,14 +6476,16 @@ mono_object_unbox (MonoObject *obj) * Returns: @obj if @obj is derived from @klass or NULL otherwise. */ MonoObject * -mono_object_isinst (MonoObject *obj, MonoClass *klass) +mono_object_isinst (MonoObject *obj_raw, MonoClass *klass) { MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); + MONO_HANDLE_DCL (MonoObject, obj); MonoError error; - MonoObject *result = mono_object_isinst_checked (obj, klass, &error); + MonoObjectHandle result = mono_object_handle_isinst (obj, klass, &error); mono_error_cleanup (&error); - return result; + HANDLE_FUNCTION_RETURN_OBJ (result); } @@ -6470,82 +6499,111 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass) * On failure returns NULL and sets @error. */ MonoObject * -mono_object_isinst_checked (MonoObject *obj, MonoClass *klass, MonoError *error) +mono_object_isinst_checked (MonoObject *obj_raw, MonoClass *klass, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); mono_error_init (error); - - MonoObject *result = NULL; + MONO_HANDLE_DCL (MonoObject, obj); + MonoObjectHandle result = mono_object_handle_isinst (obj, klass, error); + HANDLE_FUNCTION_RETURN_OBJ (result); +} +/** + * mono_object_handle_isinst: + * @obj: an object + * @klass: a pointer to a class + * @error: set on error + * + * Returns: @obj if @obj is derived from @klass or NULL if it isn't. + * On failure returns NULL and sets @error. + */ +MonoObjectHandle +mono_object_handle_isinst (MonoObjectHandle obj, MonoClass *klass, MonoError *error) +{ + mono_error_init (error); + if (!klass->inited) mono_class_init (klass); if (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass)) { - result = mono_object_isinst_mbyref_checked (obj, klass, error); - return result; + return mono_object_handle_isinst_mbyref (obj, klass, error); } - if (!obj) - return NULL; + MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL); - return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL; + if (!MONO_HANDLE_IS_NULL (obj) && mono_class_is_assignable_from (klass, mono_handle_class (obj))) + MONO_HANDLE_ASSIGN (result, obj); + return result; } MonoObject * -mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass) +mono_object_isinst_mbyref (MonoObject *obj_raw, MonoClass *klass) { MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); MonoError error; - MonoObject *result = mono_object_isinst_mbyref_checked (obj, klass, &error); + MONO_HANDLE_DCL (MonoObject, obj); + MonoObjectHandle result = mono_object_handle_isinst_mbyref (obj, klass, &error); mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */ - return result; + HANDLE_FUNCTION_RETURN_OBJ (result); } -MonoObject * -mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError *error) +MonoObjectHandle +mono_object_handle_isinst_mbyref (MonoObjectHandle obj, MonoClass *klass, MonoError *error) { - MONO_REQ_GC_UNSAFE_MODE; - - MonoVTable *vt; - mono_error_init (error); - if (!obj) - return NULL; + MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL); + + if (MONO_HANDLE_IS_NULL (obj)) + goto leave; - vt = obj->vtable; + MonoVTable *vt = MONO_HANDLE_GETVAL (obj, vtable); if (mono_class_is_interface (klass)) { if (MONO_VTABLE_IMPLEMENTS_INTERFACE (vt, klass->interface_id)) { - return obj; + MONO_HANDLE_ASSIGN (result, obj); + goto leave; } /* casting an array one of the invariant interfaces that must act as such */ if (klass->is_array_special_interface) { - if (mono_class_is_assignable_from (klass, vt->klass)) - return obj; + if (mono_class_is_assignable_from (klass, vt->klass)) { + MONO_HANDLE_ASSIGN (result, obj); + goto leave; + } } /*If the above check fails we are in the slow path of possibly raising an exception. So it's ok to it this way.*/ - else if (mono_class_has_variant_generic_params (klass) && mono_class_is_assignable_from (klass, obj->vtable->klass)) - return obj; + else if (mono_class_has_variant_generic_params (klass) && mono_class_is_assignable_from (klass, mono_handle_class (obj))) { + MONO_HANDLE_ASSIGN (result, obj); + goto leave; + } } else { MonoClass *oklass = vt->klass; - if (mono_class_is_transparent_proxy (oklass)) - oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class; + if (mono_class_is_transparent_proxy (oklass)){ + MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoTransparentProxy, obj), remote_class); + oklass = remote_class->proxy_class; + } mono_class_setup_supertypes (klass); - if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass)) - return obj; + if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass)) { + MONO_HANDLE_ASSIGN (result, obj); + goto leave; + } } #ifndef DISABLE_REMOTING - if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info) + if (vt->klass == mono_defaults.transparent_proxy_class) { + MonoBoolean custom_type_info = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoTransparentProxy, obj), custom_type_info); + if (!custom_type_info) + goto leave; MonoDomain *domain = mono_domain_get (); - MonoObject *res; - MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp; + MonoObjectHandle rp = MONO_HANDLE_NEW (MonoObject, NULL); + MONO_HANDLE_GET (rp, MONO_HANDLE_CAST (MonoTransparentProxy, obj), rp); MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class; MonoMethod *im = NULL; gpointer pa [2]; @@ -6553,27 +6611,34 @@ mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1); if (!im) { mono_error_set_not_supported (error, "Linked away."); - return NULL; + goto leave; } - im = mono_object_get_virtual_method (rp, im); + im = mono_object_handle_get_virtual_method (rp, im, error); + if (!is_ok (error)) + goto leave; g_assert (im); - pa [0] = mono_type_get_object_checked (domain, &klass->byval_arg, error); - return_val_if_nok (error, NULL); - pa [1] = obj; + MonoReflectionTypeHandle reftype = mono_type_get_object_handle (domain, &klass->byval_arg, error); + if (!is_ok (error)) + goto leave; - res = mono_runtime_invoke_checked (im, rp, pa, error); - return_val_if_nok (error, NULL); + pa [0] = MONO_HANDLE_RAW (reftype); + pa [1] = MONO_HANDLE_RAW (obj); + MonoObject *res = mono_runtime_invoke_checked (im, rp, pa, error); + if (!is_ok (error)) + goto leave; 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, error); - return_val_if_nok (error, NULL); - return obj; + if (!is_ok (error)) + goto leave; + MONO_HANDLE_ASSIGN (result, obj); } } #endif /* DISABLE_REMOTING */ - return NULL; +leave: + return result; } /** @@ -6584,15 +6649,19 @@ mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError * Returns: @obj if @obj is derived from @klass, returns NULL otherwise. */ MonoObject * -mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass) +mono_object_castclass_mbyref (MonoObject *obj_raw, MonoClass *klass) { MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); MonoError error; - - if (!obj) return NULL; - if (mono_object_isinst_mbyref_checked (obj, klass, &error)) return obj; + MONO_HANDLE_DCL (MonoObject, obj); + MonoObjectHandle result = MONO_HANDLE_NEW (MonoObject, NULL); + if (MONO_HANDLE_IS_NULL (obj)) + goto leave; + MONO_HANDLE_ASSIGN (result, mono_object_handle_isinst_mbyref (obj, klass, &error)); mono_error_cleanup (&error); - return NULL; +leave: + HANDLE_FUNCTION_RETURN_OBJ (result); } typedef struct { diff --git a/mono/metadata/remoting.c b/mono/metadata/remoting.c index a29cf91a1cc..cd8bf2078cd 100644 --- a/mono/metadata/remoting.c +++ b/mono/metadata/remoting.c @@ -1852,14 +1852,15 @@ mono_marshal_get_proxy_cancast (MonoClass *klass) } void -mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy) +mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype_raw, MonoTransparentProxy *tproxy_raw) { - MonoError error; - MonoClass *klass; - MonoDomain *domain = ((MonoObject*)tproxy)->vtable->domain; - klass = mono_class_from_mono_type (rtype->type); - mono_upgrade_remote_class (domain, (MonoObject*)tproxy, klass, &error); - mono_error_set_pending_exception (&error); + ICALL_ENTRY (); + MONO_HANDLE_DCL (MonoReflectionType, rtype); + MONO_HANDLE_DCL (MonoTransparentProxy, tproxy); + MonoDomain *domain = MONO_HANDLE_DOMAIN (tproxy); + MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (rtype, type)); + mono_upgrade_remote_class (domain, MONO_HANDLE_CAST (MonoObject, tproxy), klass, &error); + ICALL_RETURN (); } #else /* DISABLE_REMOTING */ -- 2.25.1