2006-11-27 Jonathan Chambers <joncham@gmail.com>
authorJonathan Chambers <joncham@gmail.com>
Tue, 28 Nov 2006 04:04:55 +0000 (04:04 -0000)
committerJonathan Chambers <joncham@gmail.com>
Tue, 28 Nov 2006 04:04:55 +0000 (04:04 -0000)
        * marshal.c:
                (mono_marshal_emit_managed_wrapper): Level of indirection for
                mono_marshal_get_managed_wrapper so that a wrapper for a managed method
                can be generated without a delegate class.
                (mono_marshal_get_managed_wrapper): Move wrapper logic to mono_marshal_emit_managed_wrapper.

Signed-off-by: Jonathan Chambers <joncham@gmail.com>
svn path=/trunk/mono/; revision=68551

mono/metadata/ChangeLog
mono/metadata/marshal.c

index f339bb2cfea9689ad5c0db01390ce6ee5766a716..f3dd50aeb8c13556417a864a5245d1d23f8172e1 100644 (file)
@@ -1,3 +1,13 @@
+2006-11-27  Jonathan Chambers  <joncham@gmail.com>
+  
+       * marshal.c: 
+               (mono_marshal_emit_managed_wrapper): Level of indirection for 
+               mono_marshal_get_managed_wrapper so that a wrapper for a managed method
+               can be generated without a delegate class.
+               (mono_marshal_get_managed_wrapper): Move wrapper logic to mono_marshal_emit_managed_wrapper.
+       
+       Signed-off-by: Jonathan Chambers <joncham@gmail.com>
+
 2006-11-27 Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * console-io.c: add the 'signal' call removed by mistake. Fixes bug
index e14fea4a8ab7e4f2d41b0300dce47717201694e1..9c2ea12e7ccfb0b42dd5438e8b9fff93a70d034b 100644 (file)
@@ -7752,44 +7752,16 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig
 
        return res;
 }
-                            
-/*
- * generates IL code to call managed methods from unmanaged code 
- */
-MonoMethod *
-mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject *this)
+                           
+/* FIXME: moving GC */
+static void
+mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoObject* this)
 {
-       static MonoClass *UnmanagedFunctionPointerAttribute;
-       MonoMethodSignature *sig, *csig, *invoke_sig;
-       MonoMethodBuilder *mb;
-       MonoMethod *res, *invoke;
-       MonoMarshalSpec **mspecs;
-       MonoMethodPInvoke piinfo;
-       GHashTable *cache;
+       MonoMethodSignature *sig, *csig;
        int i, *tmp_locals;
-       EmitMarshalContext m;
 
-       g_assert (method != NULL);
-       g_assert (!mono_method_signature (method)->pinvoke);
-
-       /* 
-        * FIXME: Should cache the method+delegate type pair, since the same method
-        * could be called with different delegates, thus different marshalling
-        * options.
-        */
-       cache = method->klass->image->managed_wrapper_cache;
-       if (!this && (res = mono_marshal_find_in_cache (cache, method)))
-               return res;
-
-       invoke = mono_class_get_method_from_name (delegate_klass, "Invoke", mono_method_signature (method)->param_count);
-       invoke_sig = mono_method_signature (invoke);
-
-       mspecs = g_new0 (MonoMarshalSpec*, mono_method_signature (invoke)->param_count + 1);
-       mono_method_get_marshal_info (invoke, mspecs);
-
-       sig = mono_method_signature (method);
-
-       mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+       sig = m->sig;
+       csig = m->csig;
 
        /* allocate local 0 (pointer) src_ptr */
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
@@ -7806,73 +7778,6 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        mono_mb_emit_icon (mb, 0);
        mono_mb_emit_stloc (mb, 2);
 
-       /* we copy the signature, so that we can modify it */
-       csig = signature_dup (method->klass->image, sig);
-       csig->hasthis = 0;
-       csig->pinvoke = 1;
-
-       m.mb = mb;
-       m.sig = sig;
-       m.piinfo = NULL;
-       m.retobj_var = 0;
-       m.csig = csig;
-       m.image = method->klass->image;
-
-#ifdef PLATFORM_WIN32
-       /* 
-        * Under windows, delegates passed to native code must use the STDCALL
-        * calling convention.
-        */
-       csig->call_convention = MONO_CALL_STDCALL;
-#endif
-
-       /* Change default calling convention if needed */
-       /* Why is this a modopt ? */
-       if (invoke_sig->ret && invoke_sig->ret->num_mods) {
-               for (i = 0; i < invoke_sig->ret->num_mods; ++i) {
-                       MonoClass *cmod_class = mono_class_get (delegate_klass->image, invoke_sig->ret->modifiers [i].token);
-                       g_assert (cmod_class);
-                       if ((cmod_class->image == mono_defaults.corlib) && !strcmp (cmod_class->name_space, "System.Runtime.CompilerServices")) {
-                               if (!strcmp (cmod_class->name, "CallConvCdecl"))
-                                       csig->call_convention = MONO_CALL_C;
-                               else if (!strcmp (cmod_class->name, "CallConvStdcall"))
-                                       csig->call_convention = MONO_CALL_STDCALL;
-                               else if (!strcmp (cmod_class->name, "CallConvFastcall"))
-                                       csig->call_convention = MONO_CALL_FASTCALL;
-                               else if (!strcmp (cmod_class->name, "CallConvThiscall"))
-                                       csig->call_convention = MONO_CALL_THISCALL;
-                       }
-               }
-       }
-
-       /* Handle the UnmanagedFunctionPointerAttribute */
-       if (!UnmanagedFunctionPointerAttribute)
-               UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
-
-       /* The attribute is only available in Net 2.0 */
-       if (UnmanagedFunctionPointerAttribute) {
-               MonoReflectionUnmanagedFunctionPointerAttribute *attr;
-               MonoCustomAttrInfo *cinfo;
-
-               /* 
-                * The pinvoke attributes are stored in a real custom attribute so we have to
-                * construct it.
-                */
-               cinfo = mono_custom_attrs_from_class (delegate_klass);
-               if (cinfo) {
-                       attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr (cinfo, UnmanagedFunctionPointerAttribute);
-                       if (attr) {
-                               memset (&piinfo, 0, sizeof (piinfo));
-                               m.piinfo = &piinfo;
-                               piinfo.piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
-
-                               csig->call_convention = attr->call_conv - 1;
-                       }
-                       if (!cinfo->cached)
-                               mono_custom_attrs_free (cinfo);
-               }
-       }
-
        /* fixme: howto handle this ? */
        if (sig->hasthis) {
                if (this) {
@@ -7896,7 +7801,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                case MONO_TYPE_ARRAY:
                case MONO_TYPE_SZARRAY:
                case MONO_TYPE_STRING:
-                       tmp_locals [i] = emit_marshal (&m, i, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
+                       tmp_locals [i] = emit_marshal (m, i, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
 
                        break;
                default:
@@ -7923,7 +7828,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
        mono_mb_emit_managed_call (mb, method, NULL);
 
        if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
-               emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+               emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
        }
        else
        if (!sig->ret->byref) { 
@@ -7949,12 +7854,12 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                        break;
                case MONO_TYPE_STRING:
                        csig->ret = &mono_defaults.int_class->byval_arg;
-                       emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+                       emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
                        break;
                case MONO_TYPE_VALUETYPE:
                case MONO_TYPE_CLASS:
                case MONO_TYPE_SZARRAY:
-                       emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+                       emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
                        break;
                default:
                        g_warning ("return type 0x%02x unknown", sig->ret->type);       
@@ -7970,13 +7875,13 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                MonoMarshalSpec *spec = mspecs [i + 1];
 
                if (spec && spec->native == MONO_NATIVE_CUSTOM) {
-                       emit_marshal (&m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+                       emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                }
                else if (t->byref) {
                        switch (t->type) {
                        case MONO_TYPE_CLASS:
                        case MONO_TYPE_VALUETYPE:
-                               emit_marshal (&m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+                               emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
                        }
                }
@@ -7986,7 +7891,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                        case MONO_TYPE_SZARRAY:
                        case MONO_TYPE_CLASS:
                        case MONO_TYPE_VALUETYPE:
-                               emit_marshal (&m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+                               emit_marshal (m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
                        default:
                                g_assert_not_reached ();
@@ -7994,16 +7899,126 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
                }
        }
 
-       if (m.retobj_var) {
-               mono_mb_emit_ldloc (mb, m.retobj_var);
+       if (m->retobj_var) {
+               mono_mb_emit_ldloc (mb, m->retobj_var);
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-               mono_mb_emit_op (mb, CEE_MONO_RETOBJ, m.retobj_class);
+               mono_mb_emit_op (mb, CEE_MONO_RETOBJ, m->retobj_class);
        }
        else {
                if (!MONO_TYPE_IS_VOID(sig->ret))
                        mono_mb_emit_ldloc (mb, 3);
                mono_mb_emit_byte (mb, CEE_RET);
        }
+}
+
+
+/*
+ * generates IL code to call managed methods from unmanaged code 
+ */
+MonoMethod *
+mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject *this)
+{
+       static MonoClass *UnmanagedFunctionPointerAttribute;
+       MonoMethodSignature *sig, *csig, *invoke_sig;
+       MonoMethodBuilder *mb;
+       MonoMethod *res, *invoke;
+       MonoMarshalSpec **mspecs;
+       MonoMethodPInvoke piinfo;
+       GHashTable *cache;
+       int i;
+       EmitMarshalContext m;
+
+       g_assert (method != NULL);
+       g_assert (!mono_method_signature (method)->pinvoke);
+
+       /* 
+        * FIXME: Should cache the method+delegate type pair, since the same method
+        * could be called with different delegates, thus different marshalling
+        * options.
+        */
+       cache = method->klass->image->managed_wrapper_cache;
+       if (!this && (res = mono_marshal_find_in_cache (cache, method)))
+               return res;
+
+       invoke = mono_class_get_method_from_name (delegate_klass, "Invoke", mono_method_signature (method)->param_count);
+       invoke_sig = mono_method_signature (invoke);
+
+       mspecs = g_new0 (MonoMarshalSpec*, mono_method_signature (invoke)->param_count + 1);
+       mono_method_get_marshal_info (invoke, mspecs);
+
+       sig = mono_method_signature (method);
+
+       mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+
+
+       /* we copy the signature, so that we can modify it */
+       csig = signature_dup (method->klass->image, sig);
+       csig->hasthis = 0;
+       csig->pinvoke = 1;
+
+       m.mb = mb;
+       m.sig = sig;
+       m.piinfo = NULL;
+       m.retobj_var = 0;
+       m.csig = csig;
+       m.image = method->klass->image;
+
+#ifdef PLATFORM_WIN32
+       /* 
+        * Under windows, delegates passed to native code must use the STDCALL
+        * calling convention.
+        */
+       csig->call_convention = MONO_CALL_STDCALL;
+#endif
+
+       /* Change default calling convention if needed */
+       /* Why is this a modopt ? */
+       if (invoke_sig->ret && invoke_sig->ret->num_mods) {
+               for (i = 0; i < invoke_sig->ret->num_mods; ++i) {
+                       MonoClass *cmod_class = mono_class_get (delegate_klass->image, invoke_sig->ret->modifiers [i].token);
+                       g_assert (cmod_class);
+                       if ((cmod_class->image == mono_defaults.corlib) && !strcmp (cmod_class->name_space, "System.Runtime.CompilerServices")) {
+                               if (!strcmp (cmod_class->name, "CallConvCdecl"))
+                                       csig->call_convention = MONO_CALL_C;
+                               else if (!strcmp (cmod_class->name, "CallConvStdcall"))
+                                       csig->call_convention = MONO_CALL_STDCALL;
+                               else if (!strcmp (cmod_class->name, "CallConvFastcall"))
+                                       csig->call_convention = MONO_CALL_FASTCALL;
+                               else if (!strcmp (cmod_class->name, "CallConvThiscall"))
+                                       csig->call_convention = MONO_CALL_THISCALL;
+                       }
+               }
+       }
+
+       /* Handle the UnmanagedFunctionPointerAttribute */
+       if (!UnmanagedFunctionPointerAttribute)
+               UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
+
+       /* The attribute is only available in Net 2.0 */
+       if (UnmanagedFunctionPointerAttribute) {
+               MonoReflectionUnmanagedFunctionPointerAttribute *attr;
+               MonoCustomAttrInfo *cinfo;
+
+               /* 
+                * The pinvoke attributes are stored in a real custom attribute so we have to
+                * construct it.
+                */
+               cinfo = mono_custom_attrs_from_class (delegate_klass);
+               if (cinfo) {
+                       attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr (cinfo, UnmanagedFunctionPointerAttribute);
+                       if (attr) {
+                               memset (&piinfo, 0, sizeof (piinfo));
+                               m.piinfo = &piinfo;
+                               piinfo.piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
+
+                               csig->call_convention = attr->call_conv - 1;
+                       }
+                       if (!cinfo->cached)
+                               mono_custom_attrs_free (cinfo);
+               }
+       }
+
+       mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, this);
 
        if (!this)
                res = mono_mb_create_and_cache (cache, method,