Fix for building mono in VS, and implement reading/writing USER/MACHINE level environ...
[mono.git] / mono / metadata / object.c
index dc00f2160d9945f3ed8239b84f1fa292669202aa..e96f043093154f5d5ba5e54c51b5f250a7ff8dcb 100644 (file)
@@ -470,12 +470,17 @@ mono_install_init_vtable (MonoInitVTableFunc func)
 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
 
 static gsize*
-compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set)
+compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
 {
        MonoClassField *field;
        MonoClass *p;
        guint32 pos;
-       int max_size = class->instance_size / sizeof (gpointer);
+       int max_size;
+
+       if (static_fields)
+               max_size = class->class_size / sizeof (gpointer);
+       else
+               max_size = class->instance_size / sizeof (gpointer);
        if (max_size > size) {
                bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
        }
@@ -485,8 +490,13 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                while ((field = mono_class_get_fields (p, &iter))) {
                        MonoType *type;
 
-                       if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
-                               continue;
+                       if (static_fields) {
+                               if (!(field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)))
+                                       continue;
+                       } else {
+                               if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
+                                       continue;
+                       }
                        /* FIXME: should not happen, flag as type load error */
                        if (field->type->byref)
                                break;
@@ -501,6 +511,9 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                        case MONO_TYPE_U:
                        case MONO_TYPE_PTR:
                        case MONO_TYPE_FNPTR:
+#ifdef HAVE_SGEN_GC
+                               break;
+#endif
                        case MONO_TYPE_STRING:
                        case MONO_TYPE_SZARRAY:
                        case MONO_TYPE_CLASS:
@@ -525,7 +538,7 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                                MonoClass *fclass = mono_class_from_mono_type (field->type);
                                if (fclass->has_references) {
                                        /* remove the object header */
-                                       compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set);
+                                       compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set, FALSE);
                                }
                                break;
                        }
@@ -547,6 +560,8 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                                break;
                        }
                }
+               if (static_fields)
+                       break;
        }
        return bitmap;
 }
@@ -604,7 +619,7 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                                class->name_space, class->name);*/
                } else {
                        /* remove the object header */
-                       bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set);
+                       bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
                        class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
                        /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
                                class->name_space, class->name);*/
@@ -616,7 +631,7 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                /*static int count = 0;
                if (count++ > 58)
                        return;*/
-               bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set);
+               bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
 #ifdef HAVE_BOEHM_GC
                /* It seems there are issues when the bitmap doesn't fit: play it safe */
                if (max_set >= 30) {
@@ -712,7 +727,13 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
                return runtime_info->domain_vtables [domain->domain_id];
        }
        if (!class->inited)
-               mono_class_init (class);
+               if (!mono_class_init (class)){
+                       MonoException *exc;
+                       mono_domain_unlock (domain);
+                       exc = mono_class_get_exception_for_failure (class);
+                       g_assert (exc);
+                       mono_raise_exception (exc);
+               }
 
        mono_class_setup_vtable (class);
 
@@ -751,8 +772,18 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
 
        if (class->class_size) {
                if (class->has_static_refs) {
-                       vt->data = mono_gc_alloc_fixed (class->class_size, NULL);
+                       gpointer statics_gc_descr;
+                       int max_set = 0;
+                       gsize default_bitmap [4] = {0};
+                       gsize *bitmap;
+
+                       bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
+                       /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class->class_size);*/
+                       statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set? max_set + 1: 0);
+                       vt->data = mono_gc_alloc_fixed (class->class_size, statics_gc_descr);
                        mono_domain_add_class_static_data (domain, class, vt->data, NULL);
+                       if (bitmap != default_bitmap)
+                               g_free (bitmap);
                } else {
                        vt->data = mono_mempool_alloc0 (domain->mp, class->class_size);
                }
@@ -1100,6 +1131,22 @@ create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
        return key;
 }
 
+/**
+ * copy_remote_class_key:
+ *
+ *   Make a copy of KEY in the mempool MP and return the copy.
+ */
+static gpointer*
+copy_remote_class_key (MonoMemPool *mp, gpointer *key)
+{
+       int key_size = (GPOINTER_TO_UINT (key [0]) + 1) * sizeof (gpointer);
+       gpointer *mp_key = mono_mempool_alloc (mp, key_size);
+
+       memcpy (mp_key, key, key_size);
+
+       return mp_key;
+}
+
 /**
  * mono_remote_class:
  * @domain: the application domain
@@ -1112,7 +1159,7 @@ MonoRemoteClass*
 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
 {
        MonoRemoteClass *rc;
-       gpointer* key;
+       gpointer* key, *mp_key;
        
        key = create_remote_class_key (NULL, proxy_class);
        
@@ -1125,6 +1172,10 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
                return rc;
        }
 
+       mp_key = copy_remote_class_key (domain->mp, key);
+       g_free (key);
+       key = mp_key;
+
        if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
                rc->interface_count = 1;
@@ -1138,7 +1189,7 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
        
        rc->default_vtable = NULL;
        rc->xdomain_vtable = NULL;
-       rc->proxy_class_name = mono_string_to_utf8 (class_name);
+       rc->proxy_class_name = mono_string_to_utf8_mp (domain->mp, class_name);
 
        g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
 
@@ -1154,7 +1205,7 @@ static MonoRemoteClass*
 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
 {
        MonoRemoteClass *rc;
-       gpointer* key;
+       gpointer* key, *mp_key;
        
        key = create_remote_class_key (remote_class, extra_class);
        rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
@@ -1163,6 +1214,10 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
                return rc;
        }
 
+       mp_key = copy_remote_class_key (domain->mp, key);
+       g_free (key);
+       key = mp_key;
+
        if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                int i,j;
                rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
@@ -1414,6 +1469,9 @@ handle_enum:
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY:
+               mono_gc_wbarrier_generic_store (dest, deref_pointer? *(gpointer*)value: value);
+               return;
+       case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR: {
                gpointer *p = (gpointer*)dest;
                *p = deref_pointer? *(gpointer*)value: value;
@@ -1734,10 +1792,17 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 
 /*
  * mono_nullable_init:
+ * @buf: The nullable structure to initialize.
+ * @value: the value to initialize from
+ * @klass: the type for the object
  *
- *   Initialize the nullable structure pointed to by @buf from @value which
- * should be a boxed value type. Since Nullables have variable structure, we 
- * can't define a C structure for them.
+ * Initialize the nullable structure pointed to by @buf from @value which
+ * should be a boxed value type.   The size of @buf should be able to hold
+ * as much data as the @klass->instance_size (which is the number of bytes
+ * that will be copies).
+ *
+ * Since Nullables have variable structure, we can not define a C
+ * structure for them.
  */
 void
 mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
@@ -1756,8 +1821,10 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
 
 /**
  * mono_nullable_box:
+ * @buf: The buffer representing the data to be boxed
+ * @klass: the type to box it as.
  *
- *   Creates a boxed vtype or NULL from the Nullable structure pointed to by
+ * Creates a boxed vtype or NULL from the Nullable structure pointed to by
  * @buf.
  */
 MonoObject*
@@ -1890,6 +1957,8 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        gchar *utf8_fullpath;
        int result;
 
+       g_assert (method != NULL);
+       
        mono_thread_set_main (mono_thread_current ());
 
        main_args = g_new0 (char*, argc);
@@ -2963,6 +3032,7 @@ void
 mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
 {
        int size = mono_class_value_size (klass, NULL);
+       mono_gc_wbarrier_value_copy (dest, src, 1, klass);
        memcpy (dest, src, size);
 }
 
@@ -2982,6 +3052,7 @@ mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
 {
        int size = mono_array_element_size (dest->obj.vtable->klass);
        char *d = mono_array_addr_with_size (dest, size, dest_idx);
+       mono_gc_wbarrier_value_copy (d, src, count, mono_object_class (dest)->element_class);
        memmove (d, src, size * count);
 }
 
@@ -3018,13 +3089,20 @@ guint
 mono_object_get_size (MonoObject* o)
 {
        MonoClass* klass = mono_object_class (o);
-       
-       if (klass == mono_defaults.string_class)
+       if (klass == mono_defaults.string_class) {
                return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
-       else if (klass->parent == mono_defaults.array_class)
-               return sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length ((MonoArray*) o);
-       else
+       } else if (o->vtable->rank) {
+               MonoArray *array = (MonoArray*)o;
+               size_t size = sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length (array);
+               if (array->bounds) {
+                       size += 3;
+                       size &= ~3;
+                       size += sizeof (MonoArrayBounds) * o->vtable->rank;
+               }
+               return size;
+       } else {
                return mono_class_instance_size (klass);
+       }
 }
 
 /**
@@ -3154,6 +3232,24 @@ str_lookup (MonoDomain *domain, gpointer user_data)
        info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
 }
 
+#ifdef HAVE_SGEN_GC
+
+static MonoString*
+mono_string_get_pinned (MonoString *str)
+{
+       int size;
+       MonoString *news;
+       size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
+       news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
+       memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
+       news->length = mono_string_length (str);
+       return news;
+}
+
+#else
+#define mono_string_get_pinned(str) (str)
+#endif
+
 static MonoString*
 mono_string_is_interned_lookup (MonoString *str, int insert)
 {
@@ -3169,6 +3265,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
                return res;
        }
        if (insert) {
+               str = mono_string_get_pinned (str);
                mono_g_hash_table_insert (ldstr_table, str, str);
                ldstr_unlock ();
                return str;
@@ -3273,6 +3370,7 @@ mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
                return interned;
        }
 
+       o = mono_string_get_pinned (o);
        mono_g_hash_table_insert (domain->ldstr_table, o, o);
        ldstr_unlock ();
 
@@ -3359,6 +3457,31 @@ mono_string_from_utf16 (gunichar2 *data)
        return mono_string_new_utf16 (domain, data, len);
 }
 
+/**
+ * mono_string_to_utf8_mp:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8, but allocate the string from a mempool.
+ */
+char *
+mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s)
+{
+       char *r = mono_string_to_utf8 (s);
+       char *mp_s;
+       int len;
+
+       if (!r)
+               return NULL;
+
+       len = strlen (r) + 1;
+       mp_s = mono_mempool_alloc (mp, len);
+       memcpy (mp_s, r, len);
+
+       g_free (r);
+
+       return mp_s;
+}
+
 static void
 default_ex_handler (MonoException *ex)
 {
@@ -3435,7 +3558,7 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
  *
  */
 MonoAsyncResult *
-mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
+mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
 {
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
        MonoMethod *method = mono_get_context_capture_method ();
@@ -3447,6 +3570,7 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        }
 
        res->data = data;
+       MONO_OBJECT_SETREF (res, object_data, object_data);
        MONO_OBJECT_SETREF (res, async_state, state);
        if (handle != NULL)
                MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
@@ -3832,12 +3956,10 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
-       gpointer tmp;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
-
-       if (!res)
-               res = &tmp;
+       g_assert (res != NULL);
 
        if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
                mono_field_get_value (tp->rp->unwrapped_server, field, res);
@@ -3855,8 +3977,10 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
        out_args = mono_array_new (domain, mono_defaults.object_class, 1);
        mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -3891,6 +4015,7 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc, *res;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -3918,8 +4043,10 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
 
        mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -3955,6 +4082,7 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
        MonoArray *out_args;
        MonoObject *exc;
        MonoObject *arg;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -3980,9 +4108,11 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
        mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
        mono_array_setref (msg->args, 2, arg);
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -4008,6 +4138,7 @@ mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -4027,9 +4158,11 @@ mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
        mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
        mono_array_setref (msg->args, 2, arg);
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);