Merge pull request #3142 from henricm/fix-for-win-mono_string_to_utf8
[mono.git] / mono / metadata / marshal.c
index ceb5367974b80a15489cef2f71c72bd26c72687f..2b3eea28a151551d82226202078524a6b435e4a3 100644 (file)
@@ -45,6 +45,7 @@
 #include "mono/utils/mono-memory-model.h"
 #include "mono/utils/atomic.h"
 #include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-coop.h>
 #include <mono/utils/mono-error-internals.h>
 
 #include <string.h>
@@ -961,7 +962,7 @@ mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
  *
  * Returns: a utf8 string with the contents of the StringBuilder.
  *
- * The return value must be released with g_free.
+ * The return value must be released with mono_marshal_free.
  *
  * This is a JIT icall, it sets the pending exception and returns NULL on error.
  */
@@ -982,14 +983,14 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
 
        if (gerror) {
                g_error_free (gerror);
-               g_free (str_utf16);
+               mono_marshal_free (str_utf16);
                mono_set_pending_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
                return NULL;
        } else {
                guint len = mono_string_builder_capacity (sb) + 1;
                gchar *res = (gchar *)mono_marshal_alloc (len * sizeof (gchar), &error);
                if (!mono_error_ok (&error)) {
-                       g_free (str_utf16);
+                       mono_marshal_free (str_utf16);
                        g_free (tmp);
                        mono_error_set_pending_exception (&error);
                        return NULL;
@@ -999,7 +1000,7 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
                memcpy (res, tmp, str_len * sizeof (gchar));
                res[str_len] = '\0';
 
-               g_free (str_utf16);
+               mono_marshal_free (str_utf16);
                g_free (tmp);
                return res;
        }
@@ -1013,7 +1014,8 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
  *
  * Returns: a utf16 string with the contents of the StringBuilder.
  *
- * The return value must not be freed.
+ * The return value must be released with mono_marshal_free.
+ *
  * This is a JIT icall, it sets the pending exception and returns NULL on error.
  */
 gunichar2*
@@ -7323,7 +7325,6 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        MonoClass *klass;
        int i, argnum, *tmp_locals;
        int type, param_shift = 0;
-       static MonoMethodSignature *get_last_error_sig = NULL;
        int coop_gc_stack_dummy, coop_gc_var;
 
        memset (&m, 0, sizeof (m));
@@ -7449,33 +7450,16 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
                }
        }
 
-       if (MONO_TYPE_ISSTRUCT (sig->ret)) {
-               MonoClass *klass = mono_class_from_mono_type (sig->ret);
-               mono_class_init (klass);
-               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
-                       /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
-                       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-                       mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
-                       mono_mb_emit_stloc (mb, m.vtaddr_var);
-               }
-       }
-
-       /* Unblock before converting the result, since that can involve calls into the runtime */
-       if (mono_threads_is_coop_enabled ()) {
-               mono_mb_emit_ldloc (mb, coop_gc_var);
-               mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
-               mono_mb_emit_icall (mb, mono_threads_exit_gc_safe_region_unbalanced);
-       }
-
        /* Set LastError if needed */
        if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
+#ifdef TARGET_WIN32
+               static MonoMethodSignature *get_last_error_sig = NULL;
                if (!get_last_error_sig) {
                        get_last_error_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
                        get_last_error_sig->ret = &mono_defaults.int_class->byval_arg;
                        get_last_error_sig->pinvoke = 1;
                }
 
-#ifdef TARGET_WIN32
                /*
                 * Have to call GetLastError () early and without a wrapper, since various runtime components could
                 * clobber its value.
@@ -7487,6 +7471,24 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
 #endif
        }
 
+       if (MONO_TYPE_ISSTRUCT (sig->ret)) {
+               MonoClass *klass = mono_class_from_mono_type (sig->ret);
+               mono_class_init (klass);
+               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+                       /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
+                       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+                       mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
+                       mono_mb_emit_stloc (mb, m.vtaddr_var);
+               }
+       }
+
+       /* Unblock before converting the result, since that can involve calls into the runtime */
+       if (mono_threads_is_coop_enabled ()) {
+               mono_mb_emit_ldloc (mb, coop_gc_var);
+               mono_mb_emit_ldloc_addr (mb, coop_gc_stack_dummy);
+               mono_mb_emit_icall (mb, mono_threads_exit_gc_safe_region_unbalanced);
+       }
+
        /* convert the result */
        if (!sig->ret->byref) {
                MonoMarshalSpec *spec = mspecs [0];