Merge pull request #1659 from alexanderkyte/stringbuilder-referencesource
authorZoltan Varga <vargaz@gmail.com>
Thu, 26 Mar 2015 15:29:01 +0000 (11:29 -0400)
committerZoltan Varga <vargaz@gmail.com>
Thu, 26 Mar 2015 15:29:01 +0000 (11:29 -0400)
Fixed StringBuilder marshaling capacity error, and then the tests broken by fixing it.

1  2 
mono/metadata/marshal.c
mono/metadata/object-internals.h

diff --combined mono/metadata/marshal.c
index ff21db7fc3d6dc0a1f1edf8cb6840cdc6860c57e,abded5c17e1a905c806ba95371be80822e407435..f688ff41b8da4eac788cfccd4bf6aa08ddbdb384
@@@ -695,12 -695,15 +695,15 @@@ mono_array_to_byte_byvalarray (gpointe
  }
  
  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;
  
                // 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;
        }
  
  
        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;
  }
  
  static void
- mono_string_utf16_to_builder_copy (MonoStringBuilder *sb, gunichar2 *text, size_t len)
+ 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);
-       MonoArray* newArray = mono_array_new (mono_domain_get (), mono_defaults.char_class, len);
-       gunichar2 *charDst = (gunichar2 *)newArray->vector;
+       gunichar2 *charDst = (gunichar2 *)sb->chunkChars->vector;
        gunichar2 *charSrc = (gunichar2 *)text;
-       memcpy (charDst, charSrc, sizeof (gunichar2) * len);
+       memcpy (charDst, charSrc, sizeof (gunichar2) * string_len);
  
-       MONO_OBJECT_SETREF (sb, chunkChars, newArray);
-       sb->chunkOffset = 0;
-       sb->chunkLength = len;
+       sb->chunkLength = string_len;
  
        return;
  }
@@@ -755,7 -750,10 +750,10 @@@ mono_string_utf16_to_builder2 (gunichar
        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;
  void
  mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
  {
        if (!sb || !text)
                return;
  
        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 +788,8 @@@ mono_string_utf8_to_builder2 (char *tex
        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;
@@@ -802,6 -804,9 +804,9 @@@ mono_string_utf16_to_builder (MonoStrin
  
        guint32 len;
        for (len = 0; text [len] != 0; ++len);
+       
+       if (len > mono_string_builder_capacity (sb))
+               len = mono_string_builder_capacity (sb);
  
        mono_string_utf16_to_builder_copy (sb, text, len);
  }
@@@ -837,7 -842,7 +842,7 @@@ mono_string_builder_to_utf8 (MonoString
                mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
                return NULL;
        } else {
-               guint len = mono_string_builder_length (sb) + 1;
+               guint len = mono_string_builder_capacity (sb) + 1;
                gchar *res = mono_marshal_alloc (len * sizeof (gchar));
                g_assert (str_len < len);
                memcpy (res, tmp, str_len * sizeof (gchar));
@@@ -868,7 -873,7 +873,7 @@@ mono_string_builder_to_utf16 (MonoStrin
  
        g_assert (sb->chunkChars);
  
-       guint len = mono_string_builder_length (sb);
+       guint len = mono_string_builder_capacity (sb);
  
        if (len == 0)
                len = 1;
@@@ -1987,8 -1992,7 +1992,8 @@@ emit_thread_interrupt_checkpoint_call (
  {
        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);
  
@@@ -8139,7 -8143,7 +8144,7 @@@ mono_marshal_get_isinst_with_cache (voi
        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)*/
@@@ -10342,20 -10346,11 +10347,20 @@@ ves_icall_System_Runtime_InteropService
  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
@@@ -10371,16 -10366,11 +10376,16 @@@ ves_icall_System_Runtime_InteropService
  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*
index 5862f9e180f13330314fafd349bb51558697bfe1,0ae655451ffe82fca20dcf48f5f0629c2d6cbcfd..6041aa1ae648969e0cf4377647a4c3286b5c9a04
@@@ -87,7 -87,7 +87,7 @@@
                return retval;                                                                            \
         };                             }G_STMT_END
  
- #define mono_string_builder_length(sb) sb->chunkOffset + sb->chunkChars->max_length
+ #define mono_string_builder_capacity(sb) sb->chunkOffset + sb->chunkChars->max_length
  #define mono_string_builder_string_length(sb) sb->chunkOffset + sb->chunkLength
  
  /* 
@@@ -363,7 -363,6 +363,7 @@@ typedef struct 
        gint32 il_offset;
        gint32 native_offset;
        gint64 method_address;
 +      gint32 method_index;
        MonoReflectionMethod *method;
        MonoString *filename;
        gint32 line;
@@@ -390,7 -389,7 +390,7 @@@ struct _MonoInternalThread 
        HANDLE      start_notify;
        gpointer stack_ptr;
        gpointer *static_data;
 -      gpointer jit_data;
 +      gpointer dead_field_remove_me; /* This used to be jit_data, but that was moved to MonoThreadInfo. */
        void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */
        MonoAppContext *current_appcontext;
        MonoException *pending_exception;
@@@ -1646,9 -1645,6 +1646,9 @@@ ves_icall_Mono_Runtime_GetNativeStackTr
  char *
  mono_exception_get_managed_backtrace (MonoException *exc);
  
 +void
 +mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer);
 +
  #endif /* __MONO_OBJECT_INTERNALS_H__ */