Merge pull request #1659 from alexanderkyte/stringbuilder-referencesource
[mono.git] / mono / metadata / marshal.c
index 462f3b8cf851b33949da063efb4993ac2e6e416b..f688ff41b8da4eac788cfccd4bf6aa08ddbdb384 100644 (file)
@@ -695,12 +695,15 @@ mono_array_to_byte_byvalarray (gpointer native_arr, MonoArray *arr, guint32 elnu
 }
 
 static MonoStringBuilder *
-mono_string_builder_new (void)
+mono_string_builder_new (int starting_string_length)
 {
        static MonoClass *string_builder_class;
        static MonoMethod *sb_ctor;
        static void *args [1];
-       static int initial_len;
+       int initial_len = starting_string_length;
+
+       if (initial_len < 0)
+               initial_len = 0;
 
        if (!string_builder_class) {
                MonoMethodDesc *desc;
@@ -714,7 +717,6 @@ mono_string_builder_new (void)
 
                // We make a new array in the _to_builder function, so this
                // array will always be garbage collected.
-               initial_len = 1;
                args [0] = &initial_len;
        }
 
@@ -724,7 +726,7 @@ mono_string_builder_new (void)
 
        mono_runtime_invoke (sb_ctor, sb, args, &exc);
 
-       g_assert (sb->chunkChars->max_length == initial_len);
+       g_assert (sb->chunkChars->max_length >= initial_len);
        g_assert (!exc);
 
        return sb;
@@ -733,17 +735,11 @@ mono_string_builder_new (void)
 static void
 mono_string_utf16_to_builder_copy (MonoStringBuilder *sb, gunichar2 *text, size_t string_len)
 {
-       MonoClass *ac = mono_array_class_get (mono_defaults.char_class, 1);
-       g_assert (ac);
-       int builder_capacity = mono_string_builder_capacity (sb);
-
-       MonoArray* newArray = mono_array_new (mono_domain_get (), mono_defaults.char_class, builder_capacity);
-
-       gunichar2 *charDst = (gunichar2 *)newArray->vector;
+       gunichar2 *charDst = (gunichar2 *)sb->chunkChars->vector;
        gunichar2 *charSrc = (gunichar2 *)text;
        memcpy (charDst, charSrc, sizeof (gunichar2) * string_len);
 
-       MONO_OBJECT_SETREF (sb, chunkChars, newArray);
+       sb->chunkLength = string_len;
 
        return;
 }
@@ -754,7 +750,10 @@ mono_string_utf16_to_builder2 (gunichar2 *text)
        if (!text)
                return NULL;
 
-       MonoStringBuilder *sb = mono_string_builder_new ();
+       int len;
+       for (len = 0; text [len] != 0; ++len);
+
+       MonoStringBuilder *sb = mono_string_builder_new (len);
        mono_string_utf16_to_builder (sb, text);
 
        return sb;
@@ -769,12 +768,14 @@ mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
        int len = strlen (text);
        if (len > mono_string_builder_capacity (sb))
                len = mono_string_builder_capacity (sb);
+
        GError *error = NULL;
-       gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, NULL, &error);
+       glong copied;
+       gunichar2* ut = g_utf8_to_utf16 (text, len, NULL, &copied, &error);
 
        if (!error) {
                MONO_OBJECT_SETREF (sb, chunkPrevious, NULL);
-               mono_string_utf16_to_builder_copy (sb, ut, len);
+               mono_string_utf16_to_builder_copy (sb, ut, copied);
        } else
                g_error_free (error);
 
@@ -787,7 +788,8 @@ mono_string_utf8_to_builder2 (char *text)
        if (!text)
                return NULL;
 
-       MonoStringBuilder *sb = mono_string_builder_new ();
+       int len = strlen (text);
+       MonoStringBuilder *sb = mono_string_builder_new (len);
        mono_string_utf8_to_builder (sb, text);
 
        return sb;
@@ -1990,7 +1992,8 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin
 {
        int pos_noabort, pos_noex;
 
-       mono_mb_emit_ptr (mb, (gpointer) mono_thread_interruption_request_flag ());
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
        mono_mb_emit_byte (mb, CEE_LDIND_U4);
        pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
 
@@ -8141,7 +8144,7 @@ mono_marshal_get_isinst_with_cache (void)
        mono_mb_emit_ldloc (mb, 1);
        mono_mb_emit_byte (mb, CEE_LDC_I4);
        mono_mb_emit_i4 (mb, ~0x1);
-       mono_mb_emit_byte (mb, CEE_CONV_U);
+       mono_mb_emit_byte (mb, CEE_CONV_I);
        mono_mb_emit_byte (mb, CEE_AND);
        mono_mb_emit_ldloc (mb, 0);
        /*if ((cached_vtable & ~0x1)== obj_vtable)*/
@@ -10344,11 +10347,20 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr)
 void*
 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
 {
+       void *res;
+
 #ifdef HOST_WIN32
-       return CoTaskMemAlloc (size);
+       res = CoTaskMemAlloc (size);
 #else
-       return g_try_malloc ((gulong)size);
+       if ((gulong)size == 0)
+               /* This returns a valid pointer for size 0 on MS.NET */
+               size = 4;
+
+       res = g_try_malloc ((gulong)size);
 #endif
+       if (!res)
+               mono_gc_out_of_memory ((gulong)size);
+       return res;
 }
 
 void
@@ -10364,11 +10376,16 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_ReAllocCoTaskMem (gpointer ptr, int size)
 {
+       void *res;
+
 #ifdef HOST_WIN32
-       return CoTaskMemRealloc (ptr, size);
+       res = CoTaskMemRealloc (ptr, size);
 #else
-       return g_try_realloc (ptr, (gulong)size);
+       res = g_try_realloc (ptr, (gulong)size);
 #endif
+       if (!res)
+               mono_gc_out_of_memory ((gulong)size);
+       return res;
 }
 
 void*