Преглед изворни кода

2004-07-03 Zoltan Varga <[email protected]>

	* marshal.c: Fix managed->native stringbuilder marshalling. Implement
	marshalling of stringbuilder arrays. Fixes #59900.

svn path=/trunk/mono/; revision=30659
Zoltan Varga пре 21 година
родитељ
комит
7b30a3f2e1
2 измењених фајлова са 160 додато и 67 уклоњено
  1. 5 0
      mono/metadata/ChangeLog
  2. 155 67
      mono/metadata/marshal.c

+ 5 - 0
mono/metadata/ChangeLog

@@ -1,3 +1,8 @@
+2004-07-03  Zoltan Varga  <[email protected]>
+
+	* marshal.c: Fix managed->native stringbuilder marshalling. Implement
+	marshalling of stringbuilder arrays. Fixes #59900.
+
 2004-07-02  Zoltan Varga  <[email protected]>
 
 	* icall.c: Add EnumBuilder:setup_enum_type icall.

+ 155 - 67
mono/metadata/marshal.c

@@ -45,9 +45,6 @@ struct _MonoMethodBuilder {
 static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
 
-static gint 
-mono_marshal_runtime_glist_find_klass (gconstpointer a, gconstpointer b);
-
 static MonoMethod *
 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
 {
@@ -224,17 +221,20 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb)
 {
 	GError *error = NULL;
 	glong *res;
+	gchar *tmp;
 
 	if (!sb)
 		return NULL;
 
 	res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
 
-	g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
+	tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
 	if (error) {
 		g_error_free (error);
 		mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
 	}
+	else
+		memcpy (res, tmp, sb->length + 1);
 
 	return res;
 }
@@ -1270,6 +1270,52 @@ mono_marshal_get_string_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *sp
 	}
 }
 
+static MonoMarshalNative
+mono_marshal_get_stringbuilder_to_ptr_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
+{
+	MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
+
+	switch (encoding) {
+	case MONO_NATIVE_LPWSTR:
+		return MONO_MARSHAL_CONV_SB_LPWSTR;
+		break;
+	case MONO_NATIVE_LPSTR:
+		return MONO_MARSHAL_CONV_SB_LPSTR;
+		break;
+	case MONO_NATIVE_LPTSTR:
+		return MONO_MARSHAL_CONV_SB_LPTSTR;
+		break;
+	default:
+		return -1;
+	}
+}
+
+static MonoMarshalNative
+mono_marshal_get_ptr_to_stringbuilder_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free)
+{
+	MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
+
+	*need_free = TRUE;
+
+	switch (encoding) {
+	case MONO_NATIVE_LPWSTR:
+		/* 
+		 * mono_string_builder_to_utf16 does not allocate a 
+		 * new buffer, so no need to free it.
+		 */
+		*need_free = FALSE;
+		return MONO_MARSHAL_CONV_LPWSTR_SB;
+	case MONO_NATIVE_LPSTR:
+		return MONO_MARSHAL_CONV_LPSTR_SB;
+		break;
+	case MONO_NATIVE_LPTSTR:
+		return MONO_MARSHAL_CONV_LPTSTR_SB;
+		break;
+	default:
+		return -1;
+	}
+}
+
 static inline MonoMethod*
 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
 {
@@ -1621,7 +1667,7 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params)
 			}
 		}
 
-		return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox (this): this, mparams, NULL);
+		return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this): this, mparams, NULL);
 	}
 
 	msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
@@ -3386,31 +3432,22 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 				mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
 				mono_mb_emit_stloc (mb, tmp_locals [i]);
 			} else if (klass == mono_defaults.stringbuilder_class) {
-				MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
+				MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
 
 				g_assert (!t->byref);
 				mono_mb_emit_ldarg (mb, argnum);
 				mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
 				mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
 
-				switch (encoding) {
-				case MONO_NATIVE_LPWSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPWSTR);
-					break;
-				case MONO_NATIVE_LPSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
-					break;
-				case MONO_NATIVE_LPTSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPTSTR);
-					break;
-				default: {
+				if (encoding != -1)
+					mono_mb_emit_byte (mb, encoding);
+				else {
 					char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
 					MonoException *exc = mono_get_exception_not_implemented (msg);
 					g_warning (msg);
 					g_free (msg);
 					mono_raise_exception (exc);
 				}
-				}
 
 				mono_mb_emit_stloc (mb, tmp_locals [i]);
 			} else {
@@ -3506,10 +3543,13 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 			else {
 				MonoClass *eklass;
 				guint32 label1, label2, label3;
-				int index_var, dest_ptr;
+				int index_var, dest_ptr, esize;
+				MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
 
 				dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
 
+				eklass = klass->element_class;
+
 				/* Check null */
 				mono_mb_emit_ldarg (mb, argnum);
 				mono_mb_emit_stloc (mb, tmp_locals [i]);
@@ -3518,9 +3558,23 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 				label1 = mb->pos;
 				mono_mb_emit_i4 (mb, 0);
 
+				if (eklass == mono_defaults.stringbuilder_class) {
+					if (encoding == -1) {
+						char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
+						MonoException *exc = mono_get_exception_not_implemented (msg);
+						g_warning (msg);
+						g_free (msg);
+						mono_raise_exception (exc);
+					}
+				}
+
+				if (eklass == mono_defaults.stringbuilder_class)
+					esize = sizeof (gpointer);
+				else
+					esize = mono_class_native_size (eklass, NULL);
+
 				/* allocate space for the native struct and store the address */
-				eklass = klass->element_class;
-				mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
+				mono_mb_emit_icon (mb, esize);
 				mono_mb_emit_ldarg (mb, argnum);
 				mono_mb_emit_byte (mb, CEE_LDLEN);
 				mono_mb_emit_byte (mb, CEE_MUL);
@@ -3545,22 +3599,34 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 
 				/* Emit marshalling code */
 
-				/* set the src_ptr */
-				mono_mb_emit_ldarg (mb, argnum);
-				mono_mb_emit_ldloc (mb, index_var);
-				mono_mb_emit_byte (mb, CEE_LDELEMA);
-				mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
-				mono_mb_emit_byte (mb, CEE_STLOC_0);
+				if (eklass == mono_defaults.stringbuilder_class) {
+					mono_mb_emit_ldloc (mb, dest_ptr);
+					mono_mb_emit_ldarg (mb, argnum);
+					mono_mb_emit_ldloc (mb, index_var);
+					mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+					mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+					mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
+					mono_mb_emit_byte (mb, encoding);
+					mono_mb_emit_byte (mb, CEE_STIND_I);
+				}
+				else {
+					/* set the src_ptr */
+					mono_mb_emit_ldarg (mb, argnum);
+					mono_mb_emit_ldloc (mb, index_var);
+					mono_mb_emit_byte (mb, CEE_LDELEMA);
+					mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
+					mono_mb_emit_byte (mb, CEE_STLOC_0);
 
-				/* set dst_ptr */
-				mono_mb_emit_ldloc (mb, dest_ptr);
-				mono_mb_emit_byte (mb, CEE_STLOC_1);
+					/* set dst_ptr */
+					mono_mb_emit_ldloc (mb, dest_ptr);
+					mono_mb_emit_byte (mb, CEE_STLOC_1);
 
-				/* emit valuetype conversion code */
-				emit_struct_conv (mb, eklass, FALSE);
+					/* emit valuetype conversion code */
+					emit_struct_conv (mb, eklass, FALSE);
+				}
 
 				mono_mb_emit_add_to_local (mb, index_var, 1);
-				mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
+				mono_mb_emit_add_to_local (mb, dest_ptr, esize);
 
 				mono_mb_emit_byte (mb, CEE_BR);
 				mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
@@ -3987,33 +4053,20 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 		case MONO_TYPE_CLASS:
 		case MONO_TYPE_OBJECT:			
 			if (t->data.klass == mono_defaults.stringbuilder_class) {
-				MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
-				gboolean need_free = TRUE;
+				gboolean need_free;
+				MonoMarshalNative encoding;
+
+				encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
 
 				g_assert (!t->byref);
+				g_assert (encoding != -1);
+
 				mono_mb_emit_ldarg (mb, argnum);
 				mono_mb_emit_ldloc (mb, tmp_locals [i]);
 				mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
 				mono_mb_emit_byte (mb, CEE_MONO_PROC2);
 
-				switch (encoding) {
-				case MONO_NATIVE_LPWSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_SB);
-					/* 
-					 * mono_string_builder_to_utf16 does not allocate a 
-					 * new buffer, so no need to free it.
-					 */
-					need_free = FALSE;
-					break;
-				case MONO_NATIVE_LPSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
-					break;
-				case MONO_NATIVE_LPTSTR:
-					mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPTSTR_SB);
-					break;
-				default:
-					g_assert_not_reached ();
-				}
+				mono_mb_emit_byte (mb, encoding);
 
 				if (need_free) {
 					mono_mb_emit_ldloc (mb, tmp_locals [i]);
@@ -4128,13 +4181,17 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 			}
 
 			/* Character arrays are implicitly marshalled as [Out] */
-			if ((klass->element_class == mono_defaults.char_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
+			if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
 				/* FIXME: Optimize blittable case */
 				MonoClass *eklass;
 				guint32 label1, label2, label3;
-				int index_var, src_ptr;
+				int index_var, src_ptr, esize;
 
 				eklass = klass->element_class;
+				if (eklass == mono_defaults.stringbuilder_class)
+					esize = sizeof (gpointer);
+				else
+					esize = mono_class_native_size (eklass, NULL);
 				src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
 
 				/* Check null */
@@ -4160,22 +4217,53 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 
 				/* Emit marshalling code */
 
-				/* set the src_ptr */
-				mono_mb_emit_ldloc (mb, src_ptr);
-				mono_mb_emit_byte (mb, CEE_STLOC_0);
+				if (eklass == mono_defaults.stringbuilder_class) {
+					gboolean need_free;
+					MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
 
-				/* set dst_ptr */
-				mono_mb_emit_ldarg (mb, argnum);
-				mono_mb_emit_ldloc (mb, index_var);
-				mono_mb_emit_byte (mb, CEE_LDELEMA);
-				mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
-				mono_mb_emit_byte (mb, CEE_STLOC_1);
+					g_assert (encoding != -1);
 
-				/* emit valuetype conversion code */
-				emit_struct_conv (mb, eklass, TRUE);
+					/* dest */
+					mono_mb_emit_ldarg (mb, argnum);
+					mono_mb_emit_ldloc (mb, index_var);
+					mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+
+					/* src */
+					mono_mb_emit_ldloc (mb, src_ptr);
+					mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+					mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+					mono_mb_emit_byte (mb, CEE_MONO_PROC2);
+
+					mono_mb_emit_byte (mb, encoding);
+
+					if (need_free) {
+						/* src */
+						mono_mb_emit_ldloc (mb, src_ptr);
+						mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+						mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+						mono_mb_emit_byte (mb, CEE_MONO_FREE);
+					}
+				}
+				else {
+					/* set the src_ptr */
+					mono_mb_emit_ldloc (mb, src_ptr);
+					mono_mb_emit_byte (mb, CEE_STLOC_0);
+
+					/* set dst_ptr */
+					mono_mb_emit_ldarg (mb, argnum);
+					mono_mb_emit_ldloc (mb, index_var);
+					mono_mb_emit_byte (mb, CEE_LDELEMA);
+					mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
+					mono_mb_emit_byte (mb, CEE_STLOC_1);
+
+					/* emit valuetype conversion code */
+					emit_struct_conv (mb, eklass, TRUE);
+				}
 
 				mono_mb_emit_add_to_local (mb, index_var, 1);
-				mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
+				mono_mb_emit_add_to_local (mb, src_ptr, esize);
 
 				mono_mb_emit_byte (mb, CEE_BR);
 				mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));