2007-11-12 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Mon, 12 Nov 2007 22:06:02 +0000 (22:06 -0000)
committerZoltan Varga <vargaz@gmail.com>
Mon, 12 Nov 2007 22:06:02 +0000 (22:06 -0000)
* marshal.c (mono_marshal_get_runtime_invoke): Create a non-shared wrapper for
the array Get/Set/Address methods, since the JIT inlines them.

* metadata-internals.h (MonoImage): Add 'runtime_invoke_direct_cache'.

* image.c (mono_image_close): Free runtime_invoke_direct_cache.
(mono_image_init): Initialize runtime_invoke_direct_cache.

svn path=/trunk/mono/; revision=89495

mono/metadata/ChangeLog
mono/metadata/image.c
mono/metadata/marshal.c
mono/metadata/metadata-internals.h

index 8c43d5a18b10f86de0a02cffe46edd790dde88f2..af7b81ab6806833c36ed903813c1f08e74831ec0 100644 (file)
@@ -1,5 +1,13 @@
 2007-11-12  Zoltan Varga  <vargaz@gmail.com>
 
+       * marshal.c (mono_marshal_get_runtime_invoke): Create a non-shared wrapper for
+       the array Get/Set/Address methods, since the JIT inlines them.
+
+       * metadata-internals.h (MonoImage): Add 'runtime_invoke_direct_cache'.
+
+       * image.c (mono_image_close): Free runtime_invoke_direct_cache.
+       (mono_image_init): Initialize runtime_invoke_direct_cache.      
+
        * icall.c (ves_icall_System_Delegate_SetMulticastInvoke): Update after
        mono_marshal_get_delegate_invoke signature change.
 
index f0223a25c7d86498065ae6ddc8b817967eb54ace..6d8e73bb534969e1def215955ca81dca7ab0605a 100644 (file)
@@ -599,6 +599,7 @@ mono_image_init (MonoImage *image)
                g_hash_table_new ((GHashFunc)mono_signature_hash, 
                                  (GCompareFunc)mono_metadata_signature_equal);
        
+       image->runtime_invoke_direct_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
        image->managed_wrapper_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
        image->native_wrapper_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
        image->remoting_invoke_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -1276,6 +1277,7 @@ mono_image_close (MonoImage *image)
        g_hash_table_foreach (image->remoting_invoke_cache, free_remoting_wrappers, NULL);
        g_hash_table_destroy (image->remoting_invoke_cache);
        g_hash_table_destroy (image->runtime_invoke_cache);
+       g_hash_table_destroy (image->runtime_invoke_direct_cache);
        g_hash_table_destroy (image->synchronized_cache);
        g_hash_table_destroy (image->unbox_wrapper_cache);
        g_hash_table_destroy (image->cominterop_invoke_cache);
index 9d488be69c0d30782e3a78b302e0bf697159071f..33693ee555c0bd19c42a46a910f022e21eb5235c 100644 (file)
@@ -4952,9 +4952,19 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
        static MonoMethodSignature *dealy_abort_sig = NULL;
        int i, pos, posna;
        char *name;
+       gboolean need_direct_wrapper = FALSE;
 
        g_assert (method);
 
+       if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
+               (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
+               /* 
+                * Array Get/Set/Address methods. The JIT implements them using inline code
+                * so we need to create an invoke wrapper which calls the method directly.
+                */
+               need_direct_wrapper = TRUE;
+       }
+
        if (method->string_ctor) {
                callsig = lookup_string_ctor_signature (mono_method_signature (method));
                if (!callsig)
@@ -4993,12 +5003,17 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
                }
        }
 #endif
-       cache = target_klass->image->runtime_invoke_cache;
+       if (need_direct_wrapper) {
+               cache = target_klass->image->runtime_invoke_direct_cache;
+               res = mono_marshal_find_in_cache (cache, method);
+       } else {
+               cache = target_klass->image->runtime_invoke_cache;
 
-       /* from mono_marshal_find_in_cache */
-       mono_marshal_lock ();
-       res = g_hash_table_lookup (cache, callsig);
-       mono_marshal_unlock ();
+               /* from mono_marshal_find_in_cache */
+               mono_marshal_lock ();
+               res = g_hash_table_lookup (cache, callsig);
+               mono_marshal_unlock ();
+       }
 
        if (res) {
                return res;
@@ -5065,10 +5080,11 @@ mono_marshal_get_runtime_invoke (MonoMethod *method)
                        mono_mb_emit_icon (mb, sizeof (gpointer) * i);
                        mono_mb_emit_byte (mb, CEE_ADD);
                }
-               mono_mb_emit_byte (mb, CEE_LDIND_I);
 
-               if (t->byref)
+               if (t->byref) {
+                       mono_mb_emit_byte (mb, CEE_LDIND_I);
                        continue;
+               }
 
                type = sig->params [i]->type;
 handle_enum:
@@ -5087,6 +5103,7 @@ handle_enum:
                case MONO_TYPE_R8:
                case MONO_TYPE_I8:
                case MONO_TYPE_U8:
+                       mono_mb_emit_byte (mb, CEE_LDIND_I);
                        mono_mb_emit_byte (mb, mono_type_to_ldind (sig->params [i]));
                        break;
                case MONO_TYPE_STRING:
@@ -5095,11 +5112,11 @@ handle_enum:
                case MONO_TYPE_PTR:
                case MONO_TYPE_SZARRAY:
                case MONO_TYPE_OBJECT:
-                       /* do nothing */
+                       mono_mb_emit_byte (mb, mono_type_to_ldind (sig->params [i]));
                        break;
                case MONO_TYPE_GENERICINST:
                        if (!mono_type_generic_inst_is_valuetype (sig->params [i])) {
-                               /* do nothing */
+                               mono_mb_emit_byte (mb, CEE_LDIND_I);
                                break;
                        }
 
@@ -5109,6 +5126,7 @@ handle_enum:
                                type = t->data.klass->enum_basetype->type;
                                goto handle_enum;
                        }
+                       mono_mb_emit_byte (mb, CEE_LDIND_I);
                        if (mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
                                /* Need to convert a boxed vtype to an mp to a Nullable struct */
                                mono_mb_emit_op (mb, CEE_UNBOX, mono_class_from_mono_type (sig->params [i]));
@@ -5122,8 +5140,12 @@ handle_enum:
                }               
        }
        
-       mono_mb_emit_ldarg (mb, 3);
-       mono_mb_emit_calli (mb, callsig);
+       if (need_direct_wrapper) {
+               mono_mb_emit_op (mb, CEE_CALL, method);
+       } else {
+               mono_mb_emit_ldarg (mb, 3);
+               mono_mb_emit_calli (mb, callsig);
+       }
 
        if (sig->ret->byref) {
                /* fixme: */
@@ -5220,29 +5242,33 @@ handle_enum:
        mono_mb_emit_ldloc (mb, 0);
        mono_mb_emit_byte (mb, CEE_RET);
 
-       /* taken from mono_mb_create_and_cache */
-       mono_marshal_lock ();
-       res = g_hash_table_lookup (cache, callsig);
-       mono_marshal_unlock ();
-
-       /* Somebody may have created it before us */
-       if (!res) {
-               MonoMethod *newm;
-               newm = mono_mb_create_method (mb, csig, sig->param_count + 16);
-
+       if (need_direct_wrapper) {
+               res = mono_mb_create_and_cache (cache, method, mb, csig, sig->param_count + 16);
+       } else {
+               /* taken from mono_mb_create_and_cache */
                mono_marshal_lock ();
                res = g_hash_table_lookup (cache, callsig);
+               mono_marshal_unlock ();
+
+               /* Somebody may have created it before us */
                if (!res) {
-                       res = newm;
-                       g_hash_table_insert (cache, callsig, res);
-                       g_hash_table_insert (wrapper_hash, res, callsig);
-               } else {
-                       mono_free_method (newm);
+                       MonoMethod *newm;
+                       newm = mono_mb_create_method (mb, csig, sig->param_count + 16);
+
+                       mono_marshal_lock ();
+                       res = g_hash_table_lookup (cache, callsig);
+                       if (!res) {
+                               res = newm;
+                               g_hash_table_insert (cache, callsig, res);
+                               g_hash_table_insert (wrapper_hash, res, callsig);
+                       } else {
+                               mono_free_method (newm);
+                       }
+                       mono_marshal_unlock ();
                }
-               mono_marshal_unlock ();
-       }
 
-       /* end mono_mb_create_and_cache */
+               /* end mono_mb_create_and_cache */
+       }
 
        mono_mb_free (mb);
 
index 8d8d2237a435665ce3fb76a5e7cc9402f75f1b3c..b11e3ac77ed98bc072c95c377ddd17c09a425cd0 100644 (file)
@@ -170,6 +170,7 @@ struct _MonoImage {
        GHashTable *delegate_begin_invoke_cache;
        GHashTable *delegate_end_invoke_cache;
        GHashTable *delegate_invoke_cache;
+       GHashTable *runtime_invoke_cache;
 
        /*
         * indexed by SignatureMethodPair
@@ -179,7 +180,7 @@ struct _MonoImage {
        /*
         * indexed by MonoMethod pointers 
         */
-       GHashTable *runtime_invoke_cache;
+       GHashTable *runtime_invoke_direct_cache;
        GHashTable *managed_wrapper_cache;
        GHashTable *native_wrapper_cache;
        GHashTable *remoting_invoke_cache;