Sat Jan 8 19:03:26 CET 2005 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / marshal.c
index f48b361f177e85b1eec7ebc03ebc2d5621c6c847..02e6fb9135b9db48354e56a4795b20f44619dc08 100644 (file)
@@ -89,7 +89,7 @@ static MonoDisHelper marshal_dh = {
 static CRITICAL_SECTION marshal_mutex;
 
 /* Maps wrapper methods to the methods they wrap */
-static MonoGHashTable *wrapper_hash;
+static GHashTable *wrapper_hash;
 
 static guint32 last_error_tls_id;
 
@@ -125,8 +125,7 @@ mono_marshal_init (void)
        if (!module_initialized) {
                module_initialized = TRUE;
                InitializeCriticalSection (&marshal_mutex);
-               MONO_GC_REGISTER_ROOT (wrapper_hash);
-               wrapper_hash = mono_g_hash_table_new (NULL, NULL);
+               wrapper_hash = g_hash_table_new (NULL, NULL);
                last_error_tls_id = TlsAlloc ();
 
                register_icall (mono_marshal_string_to_utf16, "mono_marshal_string_to_utf16", "ptr obj", FALSE);
@@ -629,7 +628,7 @@ mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
        mono_mb_emit_byte (mb, CEE_ADD);
        mono_mb_emit_byte (mb, CEE_LDIND_I);
        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+       mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
        mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
        mono_mb_emit_byte (mb, branch_code);
        pos = mb->pos;
@@ -921,6 +920,12 @@ emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv con
                mono_mb_emit_icall (mb, mono_string_new_wrapper);
                mono_mb_emit_byte (mb, CEE_STIND_I);            
                break;
+       case MONO_MARSHAL_CONV_STR_BYVALWSTR:
+               mono_mb_emit_byte (mb, CEE_LDLOC_1);
+               mono_mb_emit_byte (mb, CEE_LDLOC_0);
+               mono_mb_emit_icall (mb, mono_string_from_utf16);
+               mono_mb_emit_byte (mb, CEE_STIND_I);            
+               break;          
        case MONO_MARSHAL_CONV_STR_LPTSTR:
        case MONO_MARSHAL_CONV_STR_LPSTR:
                mono_mb_emit_byte (mb, CEE_LDLOC_1);
@@ -981,7 +986,6 @@ emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv con
        case MONO_MARSHAL_CONV_STR_ANSIBSTR:
        case MONO_MARSHAL_CONV_STR_TBSTR:
        case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
-       case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
        default:
                g_warning ("marshaling conversion %d not implemented", conv);
                g_assert_not_reached ();
@@ -1228,7 +1232,7 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
                        continue;
 
                ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
-                       
+
                if (last_field) {
                        msize = klass->instance_size - info->fields [i].field->offset;
                        usize = info->native_size - info->fields [i].offset;
@@ -1342,7 +1346,7 @@ emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
        /* Call DestroyStructure */
        /* FIXME: Only do this if needed */
        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+       mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
        mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
        mono_mb_emit_ldloc (mb, struct_var);
        mono_mb_emit_icall (mb, mono_struct_delete_old);
@@ -1655,7 +1659,7 @@ mono_mb_create_and_cache (GHashTable *cache, gpointer key,
                /* This does not acquire any locks */
                res = mono_mb_create_method (mb, sig, max_stack);
                g_hash_table_insert (cache, key, res);
-               mono_g_hash_table_insert (wrapper_hash, res, key);
+               g_hash_table_insert (wrapper_hash, res, key);
        }
        LeaveCriticalSection (&marshal_mutex);
 
@@ -1712,7 +1716,7 @@ mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb,
        if (*res == NULL) {
                /* This does not acquire any locks */
                *res = mono_mb_create_method (mb, sig, max_stack);
-               mono_g_hash_table_insert (wrapper_hash, *res, key);
+               g_hash_table_insert (wrapper_hash, *res, key);
        }
 
        LeaveCriticalSection (&marshal_mutex);
@@ -1729,7 +1733,7 @@ mono_marshal_method_from_wrapper (MonoMethod *wrapper)
                return wrapper;
 
        EnterCriticalSection (&marshal_mutex);
-       res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
+       res = g_hash_table_lookup (wrapper_hash, wrapper);
        LeaveCriticalSection (&marshal_mutex);
        return res;
 }
@@ -2964,7 +2968,7 @@ mono_marshal_get_remoting_invoke_for_target (MonoMethod *method, MonoRemotingTar
                return mono_marshal_get_remoting_invoke (method);
 }
 
-static gpointer
+G_GNUC_UNUSED static gpointer
 mono_marshal_load_remoting_wrapper (MonoRealProxy *rp, MonoMethod *method)
 {
        if (rp->target_domain_id != -1)
@@ -3480,7 +3484,7 @@ handle_enum:
        if (!res) {
                res = mono_mb_create_method (mb, csig, sig->param_count + 16);
                g_hash_table_insert (cache, callsig, res);
-               mono_g_hash_table_insert (wrapper_hash, res, callsig);
+               g_hash_table_insert (wrapper_hash, res, callsig);
        }
 
        LeaveCriticalSection (&marshal_mutex);
@@ -3653,7 +3657,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMars
                        if (klass->delegate) {
                                g_assert (!t->byref);
                                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-                               mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+                               mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
                                mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
                                mono_mb_emit_ldarg (mb, i);
                                mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
@@ -3942,8 +3946,10 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMars
                case MONO_TYPE_VALUETYPE:
                        klass = sig->ret->data.klass;
                        if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                           klass->blittable || klass->enumtype)
+                           klass->blittable || klass->enumtype) {
+                               mono_mb_emit_byte (mb, CEE_STLOC_3);
                                break;
+                       }
                        
                        /* load pointer to returned value type */
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
@@ -5137,7 +5143,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                        g_assert (!t->byref);
                        mono_mb_emit_byte (mb, CEE_STLOC_0);
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-                       mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+                       mono_mb_emit_byte (mb, CEE_MONO_CLASSCONST);
                        mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
                        mono_mb_emit_byte (mb, CEE_LDLOC_0);
                        mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
@@ -6201,6 +6207,8 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
 
        g_assert (klass != NULL);
 
+       mono_marshal_load_type_info (klass);
+
        if (klass->str_to_ptr)
                return klass->str_to_ptr;
 
@@ -6264,6 +6272,8 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
 
        g_assert (klass != NULL);
 
+       mono_marshal_load_type_info (klass);
+
        if (klass->ptr_to_str)
                return klass->ptr_to_str;
 
@@ -6481,6 +6491,7 @@ mono_marshal_get_stelemref ()
        guint32 b1, b2, b3, b4;
        guint32 copy_pos;
        int aklass, vklass;
+       int array_slot_addr;
        
        if (ret)
                return ret;
@@ -6492,16 +6503,17 @@ mono_marshal_get_stelemref ()
 
        /* void stelemref (void* array, int idx, void* value) */
        sig->ret = &mono_defaults.void_class->byval_arg;
-       sig->params [0] = &mono_defaults.int_class->byval_arg;
+       sig->params [0] = &mono_defaults.object_class->byval_arg;
        sig->params [1] = &mono_defaults.int_class->byval_arg; /* this is a natural sized int */
-       sig->params [2] = &mono_defaults.int_class->byval_arg;
+       sig->params [2] = &mono_defaults.object_class->byval_arg;
                
        aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
        vklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       array_slot_addr = mono_mb_add_local (mb, &mono_defaults.object_class->this_arg);
        
        /*
        the method:
-       <check ABC>
+       <ldelema (bound check)>
        if (!value)
                goto store;
        
@@ -6515,7 +6527,7 @@ mono_marshal_get_stelemref ()
                goto long;
        
        store:
-               array [idx] = value;
+               *array_slot_addr = value;
                return;
        
        long:
@@ -6525,12 +6537,12 @@ mono_marshal_get_stelemref ()
                throw new ArrayTypeMismatchException ();
        */
        
-       /* ABC */
+       /* ldelema (implicit bound check) */
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_ldarg (mb, 1);
        mono_mb_emit_byte (mb, CEE_LDELEMA);
-       mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.int_class));
-       mono_mb_emit_byte (mb, CEE_POP);
+       mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.object_class));
+       mono_mb_emit_stloc (mb, array_slot_addr);
                
        /* if (!value) goto do_store */
        mono_mb_emit_ldarg (mb, 2);
@@ -6587,10 +6599,9 @@ mono_marshal_get_stelemref ()
        copy_pos = mb->pos;
        /* do_store */
        mono_mb_patch_addr (mb, b1, mb->pos - (b1 + 4));
-       mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_ldarg (mb, 1);
+       mono_mb_emit_ldloc (mb, array_slot_addr);
        mono_mb_emit_ldarg (mb, 2);
-       mono_mb_emit_byte (mb, CEE_STELEM_I);
+       mono_mb_emit_byte (mb, CEE_STIND_REF);
        
        mono_mb_emit_byte (mb, CEE_RET);
        
@@ -7308,8 +7319,7 @@ mono_marshal_load_type_info (MonoClass* klass)
  */
 gint32
 mono_class_native_size (MonoClass *klass, guint32 *align)
-{
-       
+{      
        if (!klass->marshal_info)
                mono_marshal_load_type_info (klass);