Make nested type loading lazier.
[mono.git] / mono / metadata / marshal.c
index 5c26ede4e0873ef449215dc6dd819aa388334eff..2b66637c2bf6c5368ed6039407034fd3a918e68b 100644 (file)
@@ -571,10 +571,10 @@ mono_array_to_lparray (MonoArray *array)
        case MONO_TYPE_R4:
        case MONO_TYPE_R8:
        case MONO_TYPE_VALUETYPE:
+       case MONO_TYPE_PTR:
                /* nothing to do */
                break;
        case MONO_TYPE_GENERICINST:
-       case MONO_TYPE_PTR:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY: 
        case MONO_TYPE_SZARRAY:
@@ -2422,14 +2422,25 @@ MonoMethod *
 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
 {
        gpointer res;
+       int wrapper_type = wrapper->wrapper_type;
 
-       if (wrapper->wrapper_type == MONO_WRAPPER_NONE || wrapper->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
+       if (wrapper_type == MONO_WRAPPER_NONE || wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
                return wrapper;
 
-       res = mono_method_get_wrapper_data (wrapper, 1);
-       if (res == NULL)
-               return wrapper;
-       return res;
+       switch (wrapper_type) {
+       case MONO_WRAPPER_REMOTING_INVOKE:
+       case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
+       case MONO_WRAPPER_XDOMAIN_INVOKE:
+       case MONO_WRAPPER_SYNCHRONIZED:
+       case MONO_WRAPPER_MANAGED_TO_NATIVE:
+       case MONO_WRAPPER_RUNTIME_INVOKE:
+               res = mono_method_get_wrapper_data (wrapper, 1);
+               if (res == NULL)
+                       return wrapper;
+               return res;
+       default:
+               return NULL;
+       }
 }
 
 /*
@@ -3754,6 +3765,7 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
        MonoMethod *target_method = NULL;
        MonoClass *target_class = NULL;
        gboolean callvirt = FALSE;
+       gboolean closed_over_null = FALSE;
 
        /*
         * If the delegate target is null, and the target method is not static, a virtual 
@@ -3780,6 +3792,9 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
                
        sig = mono_signature_no_pinvoke (method);
 
+       if (callvirt)
+               closed_over_null = sig->param_count == mono_method_signature (del->method)->param_count;
+
        if (callvirt) {
                /* We need to cache the signature+method pair */
                mono_marshal_lock ();
@@ -3877,11 +3892,18 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
        mono_mb_patch_branch (mb, pos0);
 
        if (callvirt) {
-               mono_mb_emit_ldarg (mb, 1);
-               mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
-               for (i = 1; i < sig->param_count; ++i)
-                       mono_mb_emit_ldarg (mb, i + 1);
-               mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+               if (!closed_over_null) {
+                       mono_mb_emit_ldarg (mb, 1);
+                       mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
+                       for (i = 1; i < sig->param_count; ++i)
+                               mono_mb_emit_ldarg (mb, i + 1);
+                       mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+               } else {
+                       mono_mb_emit_byte (mb, CEE_LDNULL);
+                       for (i = 0; i < sig->param_count; ++i)
+                               mono_mb_emit_ldarg (mb, i + 1);
+                       mono_mb_emit_op (mb, CEE_CALL, target_method);
+               }
        } else {
                for (i = 0; i < sig->param_count; ++i)
                        mono_mb_emit_ldarg (mb, i + 1);
@@ -4231,14 +4253,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        /* allocate local 1 (object) exc */
        mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
 
-       /* cond set *exc to null */
-       mono_mb_emit_byte (mb, CEE_LDARG_2);
-       mono_mb_emit_byte (mb, CEE_BRFALSE_S);
-       mono_mb_emit_byte (mb, 3);      
-       mono_mb_emit_byte (mb, CEE_LDARG_2);
-       mono_mb_emit_byte (mb, CEE_LDNULL);
-       mono_mb_emit_byte (mb, CEE_STIND_REF);
-
        emit_thread_force_interrupt_checkpoint (mb);
 
        if (virtual) {
@@ -10702,7 +10716,7 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
        case MONO_TYPE_STRING:
                switch (string_encoding) {
                case MONO_NATIVE_LPWSTR:
-                       return mono_string_to_utf16 ((MonoString*)o);
+                       return mono_marshal_string_to_utf16_copy ((MonoString*)o);
                        break;
                case MONO_NATIVE_LPSTR:
                        return mono_string_to_lpstr ((MonoString*)o);