Merge remote branch 'upstream/master'
[mono.git] / mono / metadata / object.c
index fed23e768275d0903e051b7357199d7be4a8f103..565285f5b14be303b2c164f5abbcdf6e19de70c4 100644 (file)
@@ -1709,8 +1709,12 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                        g_ptr_array_free (sorted, TRUE);
                }
 
+#ifndef __native_client__
+               /* We don't re-use any thunks as there is a lot of overhead */
+               /* to deleting and re-using code in Native Client.          */
                if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
                        invalidate_generic_virtual_thunk (domain, old_thunk);
+#endif
        }
 
        mono_domain_unlock (domain);
@@ -2077,21 +2081,11 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 
        /*FIXME check for OOM*/
        vt->type = mono_type_get_object (domain, &class->byval_arg);
-#if HAVE_SGEN_GC
-       if (mono_object_get_class (vt->type) != mono_defaults.monotype_class) {
-               static void *type_desc = NULL;
-
-               if (!type_desc) {
-                       gsize bmap = 1;
-                       type_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
-               }
-
+       if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
                /* This is unregistered in
                   unregister_vtable_reflection_type() in
                   domain.c. */
-               mono_gc_register_root ((char*)&vt->type, sizeof (gpointer), type_desc);
-       }
-#endif
+               MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
        if (class->contextbound)
                vt->remote = 1;
        else
@@ -2299,6 +2293,25 @@ mono_class_field_is_special_static (MonoClassField *field)
        return FALSE;
 }
 
+/**
+ * mono_class_field_get_special_static_type:
+ * @field: The MonoClassField describing the field.
+ *
+ * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
+ * SPECIAL_STATIC_NONE otherwise.
+ */
+guint32
+mono_class_field_get_special_static_type (MonoClassField *field)
+{
+       if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+               return SPECIAL_STATIC_NONE;
+       if (mono_field_is_deleted (field))
+               return SPECIAL_STATIC_NONE;
+       if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
+               return field_is_special_static (field->parent, field);
+       return SPECIAL_STATIC_NONE;
+}
+
 /**
  * mono_class_has_special_static_fields:
  * 
@@ -2914,7 +2927,11 @@ mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
 
        if (field->offset == -1) {
                /* Special static */
-               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               gpointer addr;
+
+               mono_domain_lock (vt->domain);
+               addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               mono_domain_unlock (vt->domain);
                dest = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
        } else {
                dest = (char*)vt->data + field->offset;
@@ -2937,7 +2954,11 @@ mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field)
        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
                if (field->offset == -1) {
                        /* Special static */
-                       gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+                       gpointer addr;
+
+                       mono_domain_lock (vt->domain);
+                       addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+                       mono_domain_unlock (vt->domain);
                        src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
                } else {
                        src = (guint8*)vt->data + field->offset;
@@ -3179,6 +3200,28 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
        mono_get_constant_value_from_blob (domain, def_type, data, value);
 }
 
+void
+mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value)
+{
+       void *src;
+
+       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
+       
+       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
+               get_default_field_value (vt->domain, field, value);
+               return;
+       }
+
+       if (field->offset == -1) {
+               /* Special static */
+               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+               src = mono_get_special_static_data_for_thread (thread, GPOINTER_TO_UINT (addr));
+       } else {
+               src = (char*)vt->data + field->offset;
+       }
+       set_value (field->type, value, src, TRUE);
+}
+
 /**
  * mono_field_static_get_value:
  * @vt: vtable to the object
@@ -3198,23 +3241,7 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
 void
 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
 {
-       void *src;
-
-       g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
-       
-       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
-               get_default_field_value (vt->domain, field, value);
-               return;
-       }
-
-       if (field->offset == -1) {
-               /* Special static */
-               gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
-               src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
-       } else {
-               src = (char*)vt->data + field->offset;
-       }
-       set_value (field->type, value, src, TRUE);
+       return mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
 }
 
 /**
@@ -4199,6 +4226,29 @@ mono_object_new (MonoDomain *domain, MonoClass *klass)
        return mono_object_new_specific (vtable);
 }
 
+/**
+ * mono_object_new_pinned:
+ *
+ *   Same as mono_object_new, but the returned object will be pinned.
+ * For SGEN, these objects will only be freed at appdomain unload.
+ */
+MonoObject *
+mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
+{
+       MonoVTable *vtable;
+
+       MONO_ARCH_SAVE_REGS;
+       vtable = mono_class_vtable (domain, klass);
+       if (!vtable)
+               return NULL;
+
+#ifdef HAVE_SGEN_GC
+       return mono_gc_alloc_pinned_obj (vtable, mono_class_instance_size (klass));
+#else
+       return mono_object_new_specific (vtable);
+#endif
+}
+
 /**
  * mono_object_new_specific:
  * @vtable: the vtable of the object that we want to create
@@ -5150,8 +5200,10 @@ mono_string_get_pinned (MonoString *str)
        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);
+       if (news) {
+               memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
+               news->length = mono_string_length (str);
+       }
        return news;
 }
 
@@ -5175,7 +5227,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
        }
        if (insert) {
                str = mono_string_get_pinned (str);
-               mono_g_hash_table_insert (ldstr_table, str, str);
+               if (str)
+                       mono_g_hash_table_insert (ldstr_table, str, str);
                ldstr_unlock ();
                return str;
        } else {
@@ -5284,7 +5337,8 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        }
 
        o = mono_string_get_pinned (o);
-       mono_g_hash_table_insert (domain->ldstr_table, o, o);
+       if (o)
+               mono_g_hash_table_insert (domain->ldstr_table, o, o);
        ldstr_unlock ();
 
        return o;
@@ -5810,14 +5864,18 @@ mono_print_unhandled_exception (MonoObject *exc)
        gboolean free_message = FALSE;
        MonoError error;
 
-       str = mono_object_to_string (exc, NULL);
-       if (str) {
-               message = mono_string_to_utf8_checked (str, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_cleanup (&error);
-                       message = (char *) "";
-               } else {
-                       free_message = TRUE;
+       if (exc == (MonoObject*)mono_object_domain (exc)->out_of_memory_ex) {
+               message = g_strdup ("OutOfMemoryException");
+       } else {
+               str = mono_object_to_string (exc, NULL);
+               if (str) {
+                       message = mono_string_to_utf8_checked (str, &error);
+                       if (!mono_error_ok (&error)) {
+                               mono_error_cleanup (&error);
+                               message = (char *) "";
+                       } else {
+                               free_message = TRUE;
+                       }
                }
        }