[remoting] Coop handles for proxy objects (#4208)
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 11 Jan 2017 15:38:49 +0000 (10:38 -0500)
committerGitHub <noreply@github.com>
Wed, 11 Jan 2017 15:38:49 +0000 (10:38 -0500)
* [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
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/remoting.c

index efb4c62874f58d543fbfcf3988b1d93064004d77..7a1456cbb76c1f763f071c5f840c35fbc00e155c 100644 (file)
@@ -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)
index 81820330ccba8bda79c5d23df6a2f59d0cb28c83..9e69287c7a2216296ae5566e190afa98ffa9eeb2 100644 (file)
@@ -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))
index 3c81b3bc80737f0924064a5545cd23b4703513be..0e6c3077c5837ae7161a58089aa4f3e87013dd30 100644 (file)
@@ -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;
 }
 
index 4031b3245a3fcb70b0ae5f3aa5cd04d6660450ee..8fd79559632bdfe787e542e98286ea9fcc68961c 100644 (file)
@@ -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);
index 0a6df1231eab5944092ad99a6335625ad51c0ac4..422b9a21a27866b418777cc1f748800d3fcc0ac5 100644 (file)
@@ -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 {
index a29cf91a1cc2fb23cdd1dc9400203e7107d8ac36..cd8bf2078cdaf0b4e55fa5e19d75ba86b81d9ced 100644 (file)
@@ -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 */