Added MonoString<->UTF-32 conversion helper functions.
[mono.git] / mono / metadata / object.c
index a9a86706f234a79c35762e85c190bd477cc81fc4..349e956661c6d9127fb4af5a8ae1153e248bd1e3 100644 (file)
@@ -88,9 +88,9 @@ static char *
 mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
 
 
-#define ldstr_lock() EnterCriticalSection (&ldstr_section)
-#define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
-static CRITICAL_SECTION ldstr_section;
+#define ldstr_lock() mono_mutex_lock (&ldstr_section)
+#define ldstr_unlock() mono_mutex_unlock (&ldstr_section)
+static mono_mutex_t ldstr_section;
 
 static gboolean profile_allocs = TRUE;
 
@@ -137,13 +137,13 @@ typedef struct
        guint32 initializing_tid;
        guint32 waiting_count;
        gboolean done;
-       CRITICAL_SECTION initialization_section;
+       mono_mutex_t initialization_section;
 } TypeInitializationLock;
 
 /* for locking access to type_initialization_hash and blocked_thread_hash */
-#define mono_type_initialization_lock() EnterCriticalSection (&type_initialization_section)
-#define mono_type_initialization_unlock() LeaveCriticalSection (&type_initialization_section)
-static CRITICAL_SECTION type_initialization_section;
+#define mono_type_initialization_lock() mono_mutex_lock (&type_initialization_section)
+#define mono_type_initialization_unlock() mono_mutex_unlock (&type_initialization_section)
+static mono_mutex_t type_initialization_section;
 
 /* from vtable to lock */
 static GHashTable *type_initialization_hash;
@@ -188,10 +188,10 @@ mono_thread_get_main (void)
 void
 mono_type_initialization_init (void)
 {
-       InitializeCriticalSection (&type_initialization_section);
+       mono_mutex_init_recursive (&type_initialization_section);
        type_initialization_hash = g_hash_table_new (NULL, NULL);
        blocked_thread_hash = g_hash_table_new (NULL, NULL);
-       InitializeCriticalSection (&ldstr_section);
+       mono_mutex_init_recursive (&ldstr_section);
 }
 
 void
@@ -201,11 +201,11 @@ mono_type_initialization_cleanup (void)
        /* This is causing race conditions with
         * mono_release_type_locks
         */
-       DeleteCriticalSection (&type_initialization_section);
+       mono_mutex_destroy (&type_initialization_section);
        g_hash_table_destroy (type_initialization_hash);
        type_initialization_hash = NULL;
 #endif
-       DeleteCriticalSection (&ldstr_section);
+       mono_mutex_destroy (&ldstr_section);
        g_hash_table_destroy (blocked_thread_hash);
        blocked_thread_hash = NULL;
 
@@ -334,12 +334,12 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                                }
                        }
                        lock = g_malloc (sizeof(TypeInitializationLock));
-                       InitializeCriticalSection (&lock->initialization_section);
+                       mono_mutex_init_recursive (&lock->initialization_section);
                        lock->initializing_tid = tid;
                        lock->waiting_count = 1;
                        lock->done = FALSE;
                        /* grab the vtable lock while this thread still owns type_initialization_section */
-                       EnterCriticalSection (&lock->initialization_section);
+                       mono_mutex_lock (&lock->initialization_section);
                        g_hash_table_insert (type_initialization_hash, vtable, lock);
                        do_initialization = 1;
                } else {
@@ -404,11 +404,11 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        if (last_domain)
                                mono_domain_set (last_domain, TRUE);
                        lock->done = TRUE;
-                       LeaveCriticalSection (&lock->initialization_section);
+                       mono_mutex_unlock (&lock->initialization_section);
                } else {
                        /* this just blocks until the initializing thread is done */
-                       EnterCriticalSection (&lock->initialization_section);
-                       LeaveCriticalSection (&lock->initialization_section);
+                       mono_mutex_lock (&lock->initialization_section);
+                       mono_mutex_unlock (&lock->initialization_section);
                }
 
                mono_type_initialization_lock ();
@@ -416,7 +416,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
                --lock->waiting_count;
                if (lock->waiting_count == 0) {
-                       DeleteCriticalSection (&lock->initialization_section);
+                       mono_mutex_destroy (&lock->initialization_section);
                        g_hash_table_remove (type_initialization_hash, vtable);
                        g_free (lock);
                }
@@ -452,10 +452,10 @@ gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
                 * and get_type_init_exception_for_class () needs to be aware of this.
                 */
                vtable->init_failed = 1;
-               LeaveCriticalSection (&lock->initialization_section);
+               mono_mutex_unlock (&lock->initialization_section);
                --lock->waiting_count;
                if (lock->waiting_count == 0) {
-                       DeleteCriticalSection (&lock->initialization_section);
+                       mono_mutex_destroy (&lock->initialization_section);
                        g_free (lock);
                        return TRUE;
                }
@@ -1350,6 +1350,9 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                        int method_slot_in_interface;
                        for (method_slot_in_interface = 0; method_slot_in_interface < iface->method.count; method_slot_in_interface++) {
                                MonoMethod *method = mono_class_get_method_by_index (iface, method_slot_in_interface);
+
+                               if (method->is_generic)
+                                       has_generic_virtual = TRUE;
                                add_imt_builder_entry (imt_builder, method, &imt_collisions_bitmap, interface_offset + method_slot_in_interface, slot_num);
                        }
                        interface_offset += iface->method.count;
@@ -3342,7 +3345,7 @@ mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *
 void
 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
 {
-       return mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
+       mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
 }
 
 /**
@@ -4977,6 +4980,39 @@ mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
        return s;
 }
 
+/**
+ * mono_string_new_utf32:
+ * @text: a pointer to an utf32 string
+ * @len: the length of the string
+ *
+ * Returns: A newly created string object which contains @text.
+ */
+MonoString *
+mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len)
+{
+       MonoString *s;
+       mono_unichar2 *utf16_output = NULL;
+       gint32 utf16_len = 0;
+       GError *error = NULL;
+       glong items_written;
+       
+       utf16_output = g_ucs4_to_utf16 (text, len, NULL, &items_written, &error);
+       
+       if (error)
+               g_error_free (error);
+
+       while (utf16_output [utf16_len]) utf16_len++;
+       
+       s = mono_string_new_size (domain, utf16_len);
+       g_assert (s != NULL);
+
+       memcpy (mono_string_chars (s), utf16_output, utf16_len * 2);
+
+       g_free (utf16_output);
+       
+       return s;
+}
+
 /**
  * mono_string_new_size:
  * @text: a pointer to an utf16 string
@@ -5685,6 +5721,31 @@ mono_string_to_utf16 (MonoString *s)
        return (gunichar2 *)(as);
 }
 
+/**
+ * mono_string_to_utf32:
+ * @s: a MonoString
+ *
+ * Return an null-terminated array of the UTF-32 (UCS-4) chars
+ * contained in @s. The result must be freed with g_free().
+ */
+mono_unichar4*
+mono_string_to_utf32 (MonoString *s)
+{
+       mono_unichar4 *utf32_output = NULL; 
+       GError *error = NULL;
+       glong items_written;
+       
+       if (s == NULL)
+               return NULL;
+               
+       utf32_output = g_utf16_to_ucs4 (s->chars, s->length, NULL, &items_written, &error);
+       
+       if (error)
+               g_error_free (error);
+
+       return utf32_output;
+}
+
 /**
  * mono_string_from_utf16:
  * @data: the UTF16 string (LPWSTR) to convert