* reflection.c (inflate_mono_method): Reuse method instantiation
[mono.git] / mono / metadata / marshal.c
index d84d93f5d0609ef1dfce9ae4d22cede4bfab670a..e6b9b6628bc5326608872431e9d34d2799defef4 100644 (file)
@@ -2957,6 +2957,12 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
        ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
        g_assert (ares);
 
+       if (ares->async_delegate != delegate && mono_get_runtime_info ()->framework_version [0] >= '2') {
+               mono_raise_exception (mono_get_exception_invalid_operation (
+                       "The IAsyncResult object provided does not match this delegate."));
+               return NULL;
+       }
+
        if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
                MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
                msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
@@ -4272,14 +4278,14 @@ mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
        if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
                return method;
 
-       sig = signature_no_pinvoke (method);
-       
        /* we cant remote methods without this pointer */
-       g_assert (sig->hasthis);
+       g_assert (mono_method_signature (method)->hasthis);
 
        if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)))
                return res;
 
+       sig = signature_no_pinvoke (method);
+       
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
 
        for (i = 0; i <= sig->param_count; i++)
@@ -4479,8 +4485,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
 
        g_assert (method);
 
-       target_klass = method->klass;
-       
        mono_marshal_lock ();
 
        if (method->string_ctor) {
@@ -4515,7 +4519,22 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
                }
        }
 
-       cache = method->klass->image->runtime_invoke_cache;
+       target_klass = mono_defaults.object_class;
+       /* 
+        * if types in the signature belong to non-mscorlib, we cache only
+        * in the method image
+        */
+       if (mono_class_from_mono_type (callsig->ret)->image != mono_defaults.corlib) {
+               target_klass = method->klass;
+       } else {
+               for (i = 0; i < callsig->param_count; i++) {
+                       if (mono_class_from_mono_type (callsig->params [i])->image != mono_defaults.corlib) {
+                               target_klass = method->klass;
+                               break;
+                       }
+               }
+       }
+       cache = target_klass->image->runtime_invoke_cache;
 
        /* from mono_marshal_find_in_cache */
        res = g_hash_table_lookup (cache, callsig);
@@ -4531,8 +4550,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
                dealy_abort_sig->pinvoke = 0;
        }
        
-       target_klass = mono_defaults.object_class;
-
        /* to make it work with our special string constructors */
        if (!string_dummy) {
                MONO_GC_REGISTER_ROOT (string_dummy);
@@ -6772,17 +6789,28 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
                     MarshalAction action)
 {
        MonoMethodBuilder *mb = m->mb;
+       static MonoMethod *get_object_for_native_variant = NULL;
+       static MonoMethod *get_native_variant_for_object = NULL;
+       
+       if (!get_object_for_native_variant)
+               get_object_for_native_variant = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1);
+       g_assert (get_object_for_native_variant);
+
+       if (!get_native_variant_for_object)
+               get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2);
+       g_assert (get_native_variant_for_object);
 
        switch (action) {
        case MARSHAL_ACTION_CONV_IN: {
-               static MonoMethod *get_native_variant_for_object = NULL;
-
-               if (!get_native_variant_for_object)
-                       get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2);
-               g_assert (get_native_variant_for_object);
-
-               *conv_arg_type = &mono_defaults.variant_class->byval_arg;
                conv_arg = mono_mb_add_local (mb, &mono_defaults.variant_class->byval_arg);
+               
+               if (t->byref)
+                       *conv_arg_type = &mono_defaults.variant_class->this_arg;
+               else
+                       *conv_arg_type = &mono_defaults.variant_class->byval_arg;
+
+               if (t->byref && t->attrs & PARAM_ATTRIBUTE_OUT)
+                       break;
 
                mono_mb_emit_ldarg (mb, argnum);
                if (t->byref)
@@ -6794,15 +6822,11 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
 
        case MARSHAL_ACTION_CONV_OUT: {
                static MonoMethod *variant_clear = NULL;
-               static MonoMethod *get_object_for_native_variant = NULL;
 
                if (!variant_clear)
                        variant_clear = mono_class_get_method_from_name (mono_defaults.variant_class, "Clear", 0);
                g_assert (variant_clear);
 
-               if (!get_object_for_native_variant)
-                       get_object_for_native_variant = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1);
-               g_assert (get_object_for_native_variant);
 
                if (t->byref) {
                        mono_mb_emit_ldarg (mb, argnum);
@@ -6824,25 +6848,42 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_CONV_RESULT: {
-               char *msg = g_strdup ("Marshalling of VARIANT not supported.");
+               char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
                mono_mb_emit_exception_marshal_directive (mb, msg);
                break;
        }
 
        case MARSHAL_ACTION_MANAGED_CONV_IN: {
-               char *msg = g_strdup ("Marshalling of VARIANT not supported.");
-               mono_mb_emit_exception_marshal_directive (mb, msg);
+               conv_arg = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+
+               if (t->byref)
+                       *conv_arg_type = &mono_defaults.variant_class->this_arg;
+               else
+                       *conv_arg_type = &mono_defaults.variant_class->byval_arg;
+
+               if (t->byref && t->attrs & PARAM_ATTRIBUTE_OUT)
+                       break;
+
+               if (t->byref)
+                       mono_mb_emit_ldarg (mb, argnum);
+               else
+                       mono_mb_emit_ldarg_addr (mb, argnum);
+               mono_mb_emit_managed_call (mb, get_object_for_native_variant, NULL);
+               mono_mb_emit_stloc (mb, conv_arg);
                break;
        }
 
        case MARSHAL_ACTION_MANAGED_CONV_OUT: {
-               char *msg = g_strdup ("Marshalling of VARIANT not supported.");
-               mono_mb_emit_exception_marshal_directive (mb, msg);
+               if (t->byref) {
+                       mono_mb_emit_ldloc (mb, conv_arg);
+                       mono_mb_emit_ldarg (mb, argnum);
+                       mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL);
+               }
                break;
        }
 
        case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
-               char *msg = g_strdup ("Marshalling of VARIANT not supported.");
+               char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
                mono_mb_emit_exception_marshal_directive (mb, msg);
                break;
        }
@@ -8259,6 +8300,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
                        switch (t->type) {
                        case MONO_TYPE_CLASS:
                        case MONO_TYPE_VALUETYPE:
+                       case MONO_TYPE_OBJECT:
                                emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
                        }
@@ -9996,6 +10038,18 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
 #endif
 }
 
+gpointer
+ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, int size)
+{
+       MONO_ARCH_SAVE_REGS;
+
+#ifdef PLATFORM_WIN32
+       return CoTaskMemRealloc (ptr, size);
+#else
+       return g_try_realloc (ptr, (gulong)size);
+#endif
+}
+
 void*
 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
 {