[Mono-list] Array.Copy
Martin Baulig
martin@gnome.org
06 Mar 2002 20:07:15 +0100
--=-=-=
Hi guys,
here's a patch for my new Array.Copy implementation:
--=-=-=
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=diff
Index: Array.cs
===================================================================
RCS file: /cvs/public/mcs/class/corlib/System/Array.cs,v
retrieving revision 1.24
diff -u -u -r1.24 Array.cs
--- Array.cs 2002/03/06 10:40:05 1.24
+++ Array.cs 2002/03/06 15:14:07
@@ -63,12 +63,9 @@
public extern void SetValue (object value, int[] idxs);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern object GetValueImpl (int pos);
+ internal extern static void CopyImpl (Array source, int source_idx, Array dest, int dest_idx, int length);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal extern void SetValueImpl (object value, int pos);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern static Array CreateInstanceImpl(Type elementType, int[] lengths, int [] bounds);
// Properties
@@ -358,48 +355,7 @@
public static void Copy (Array source, int source_idx, Array dest, int dest_idx, int length)
{
- if (source == null || dest == null)
- throw new ArgumentNullException ();
-
- if (length < 0)
- throw new ArgumentOutOfRangeException ();
-
- if (source == null || dest == null)
- throw new ArgumentNullException ();
-
- if (source_idx < source.GetLowerBound (0) || dest_idx < dest.GetLowerBound (0))
- throw new ArgumentException ();
-
- source_idx -= source.GetLowerBound (0);
- dest_idx -= dest.GetLowerBound (0);
-
- if (source_idx + length > source.Length || dest_idx + length > dest.Length)
- throw new ArgumentException ();
-
- if (source.Rank != dest.Rank)
- throw new RankException ();
-
- // FIXME: This should be implemented in C so that we can use memcpy()
- // whereever possible.
-
- for (int i = 0; i < length; i++)
- {
- Object srcval = source.GetValueImpl (source_idx + i);
-
- bool argumentException = false;
- bool castException = false;
-
- try {
- dest.SetValueImpl (srcval, dest_idx + i);
- } catch (ArgumentException) {
- argumentException = true;
- } catch (InvalidCastException) {
- castException = true;
- }
-
- if (argumentException || castException)
- throw new ArrayTypeMismatchException ();
- }
+ CopyImpl (source, source_idx, dest, dest_idx, length);
}
public static int IndexOf (Array array, object value)
Index: ChangeLog
===================================================================
RCS file: /cvs/public/mcs/class/corlib/System/ChangeLog,v
retrieving revision 1.211
diff -u -u -r1.211 ChangeLog
--- ChangeLog 2002/03/06 13:21:22 1.211
+++ ChangeLog 2002/03/06 15:14:09
@@ -1,3 +1,7 @@
+2002-03-06 Martin Baulig <martin@gnome.org>
+
+ * Array.cs (Copy): This is now implemented in C.
+
2002-03-06 Dietmar Maurer <dietmar@ximian.com>
* Int64.cs (Parse): bug fix for max. negative value.
--=-=-=
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=diff
Index: ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/metadata/ChangeLog,v
retrieving revision 1.204
diff -u -u -r1.204 ChangeLog
--- ChangeLog 2002/03/06 10:23:33 1.204
+++ ChangeLog 2002/03/06 15:13:11
@@ -1,5 +1,18 @@
2002-03-06 Martin Baulig <martin@gnome.org>
+ * icall.c (ves_icall_System_Array_GetValueImpl): This is now a static function,
+ no longer an interncall.
+ (ves_icall_System_Array_SetValueImpl): Likewise.
+ (ves_icall_System_Array_SetValueImpl): Added `guint32 raise_exception' argument and
+ returns a boolean indicating whether the call was successful.
+ (ves_icall_System_Array_CopyImpl): New internall. Implements Array.Copy in C and
+ uses memcpy() whenever appropriate.
+ (ves_icall_System_Array_FastCopy): Removed.
+
+ * exception.c (mono_get_exception_rank): New exception.
+
+2002-03-06 Martin Baulig <martin@gnome.org>
+
* icall.c (ves_icall_System_Array_CreateInstanceImpl): Make this work with
non-zero lower bounds. See testcases #F10-#F13.
Index: exception.c
===================================================================
RCS file: /cvs/public/mono/mono/metadata/exception.c,v
retrieving revision 1.9
diff -u -u -r1.9 exception.c
--- exception.c 2002/03/05 19:00:35 1.9
+++ exception.c 2002/03/06 15:13:11
@@ -105,6 +105,13 @@
}
MonoException *
+mono_get_exception_rank ()
+{
+ return mono_exception_from_name (mono_defaults.corlib, "System",
+ "RankException");
+}
+
+MonoException *
mono_get_exception_type_load ()
{
return mono_exception_from_name (mono_defaults.corlib, "System",
Index: exception.h
===================================================================
RCS file: /cvs/public/mono/mono/metadata/exception.h,v
retrieving revision 1.7
diff -u -u -r1.7 exception.h
--- exception.h 2002/03/05 19:00:35 1.7
+++ exception.h 2002/03/06 15:13:11
@@ -44,6 +44,9 @@
mono_get_exception_array_type_mismatch (void);
MonoException *
+mono_get_exception_rank (void);
+
+MonoException *
mono_get_exception_type_load (void);
MonoException *
Index: icall.c
===================================================================
RCS file: /cvs/public/mono/mono/metadata/icall.c,v
retrieving revision 1.82
diff -u -u -r1.82 icall.c
--- icall.c 2002/03/06 10:23:33 1.82
+++ icall.c 2002/03/06 15:13:13
@@ -85,8 +85,9 @@
return ves_icall_System_Array_GetValueImpl (this, pos);
}
-static void
-ves_icall_System_Array_SetValueImpl (MonoObject *this, MonoObject *value, guint32 pos)
+static guint32
+ves_icall_System_Array_SetValueImpl (MonoObject *this, MonoObject *value, guint32 pos,
+ guint32 raise_exception)
{
MonoArray *ao, *vo;
MonoClass *ac, *vc, *ec;
@@ -113,22 +114,29 @@
if (!vo) {
memset (ea, 0, esize);
- return;
+ return 1;
}
#define NO_WIDENING_CONVERSION G_STMT_START{\
- mono_raise_exception (mono_get_exception_argument ( \
- "value", "not a widening conversion")); \
+ if (raise_exception) \
+ mono_raise_exception (mono_get_exception_argument ( \
+ "value", "not a widening conversion")); \
+ return 0; \
}G_STMT_END
#define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
- if (esize < vsize + ## extra) \
- mono_raise_exception (mono_get_exception_argument ( \
- "value", "not a widening conversion")); \
+ if (esize < vsize + ## extra) { \
+ if (raise_exception) \
+ mono_raise_exception (mono_get_exception_argument ( \
+ "value", "not a widening conversion")); \
+ return 0; \
+ } \
}G_STMT_END
#define INVALID_CAST G_STMT_START{\
- mono_raise_exception (mono_get_exception_invalid_cast ()); \
+ if (raise_exception) \
+ mono_raise_exception (mono_get_exception_invalid_cast ()); \
+ return 0; \
}G_STMT_END
/* Check element (destination) type. */
@@ -165,12 +173,12 @@
if (!ec->valuetype) {
*ea = (gpointer)vo;
- return;
+ return 1;
}
if (mono_object_isinst (value, ec)) {
memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
- return;
+ return 1;
}
if (!vc->valuetype)
@@ -193,7 +201,7 @@
case MONO_TYPE_CHAR: \
CHECK_WIDENING_CONVERSION(0); \
*(## etype *) ea = (## etype) u64; \
- return; \
+ return 1; \
/* You can't assign a signed value to an unsigned array. */ \
case MONO_TYPE_I1: \
case MONO_TYPE_I2: \
@@ -214,7 +222,7 @@
case MONO_TYPE_I8: \
CHECK_WIDENING_CONVERSION(0); \
*(## etype *) ea = (## etype) i64; \
- return; \
+ return 1; \
/* You can assign an unsigned value to a signed array if the array's */ \
/* element size is larger than the value size. */ \
case MONO_TYPE_U1: \
@@ -224,7 +232,7 @@
case MONO_TYPE_CHAR: \
CHECK_WIDENING_CONVERSION(1); \
*(## etype *) ea = (## etype) u64; \
- return; \
+ return 1; \
/* You can't assign a floating point number to an integer array. */ \
case MONO_TYPE_R4: \
case MONO_TYPE_R8: \
@@ -238,7 +246,7 @@
case MONO_TYPE_R8: \
CHECK_WIDENING_CONVERSION(0); \
*(## etype *) ea = (## etype) r64; \
- return; \
+ return 1; \
/* All integer values fit into a floating point array, so we don't */ \
/* need to CHECK_WIDENING_CONVERSION here. */ \
case MONO_TYPE_I1: \
@@ -246,14 +254,14 @@
case MONO_TYPE_I4: \
case MONO_TYPE_I8: \
*(## etype *) ea = (## etype) i64; \
- return; \
+ return 1; \
case MONO_TYPE_U1: \
case MONO_TYPE_U2: \
case MONO_TYPE_U4: \
case MONO_TYPE_U8: \
case MONO_TYPE_CHAR: \
*(## etype *) ea = (## etype) u64; \
- return; \
+ return 1; \
} \
}G_STMT_END
@@ -339,8 +347,7 @@
}
INVALID_CAST;
- /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
- return;
+ return 0;
#undef INVALID_CAST
#undef NO_WIDENING_CONVERSION
@@ -386,8 +393,88 @@
for (i = 1; i < ac->rank; i++)
pos = pos*ao->bounds [i].length + ind [i] -
ao->bounds [i].lower_bound;
+
+ ves_icall_System_Array_SetValueImpl (this, value, pos, 1);
+}
+
+
+static void
+ves_icall_System_Array_CopyImpl (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
+{
+ MonoArray *sa, *da;
+ MonoClass *sc, *dc;
+ gpointer dptr, sptr;
+ gint32 esize, i;
+
+ MONO_CHECK_ARG_NULL (dest);
+
+ sa = (MonoArray *)source;
+ if (sa)
+ sc = (MonoClass *)sa->obj.vtable->klass->element_class;
+ else
+ sc = NULL;
+
+ da = (MonoArray *)dest;
+ dc = (MonoClass *)da->obj.vtable->klass->element_class;
+
+ if (length < 0)
+ mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
+
+ MONO_CHECK_ARG (dest_idx, dest_idx >= da->bounds [0].lower_bound);
+ MONO_CHECK_ARG (length,
+ (length >= 0) &&
+ (dest_idx + length <= da->bounds [0].lower_bound +
+ da->bounds [0].length));
+
+ esize = mono_array_element_size (dc);
+
+ dest_idx -= da->bounds [0].lower_bound;
+ dptr = (char*)da->vector + (dest_idx * esize);
- ves_icall_System_Array_SetValueImpl (this, value, pos);
+ if (!sa) {
+ /* Array.Clear */
+ memset (dptr, 0, esize * length);
+ return;
+ }
+
+ MONO_CHECK_ARG (source_idx, source_idx >= sa->bounds [0].lower_bound);
+ MONO_CHECK_ARG (length,
+ (source_idx + length <= sa->bounds [0].lower_bound +
+ sa->bounds [0].length));
+
+ source_idx -= sa->bounds [0].lower_bound;
+ sptr = (char*)sa->vector + (source_idx * esize);
+
+ if (sa->obj.vtable->klass->rank != da->obj.vtable->klass->rank)
+ mono_raise_exception (mono_get_exception_rank ());
+
+ if (!sc->valuetype && !dc->valuetype) {
+ memcpy (dptr, sptr, esize * length);
+ return;
+ }
+
+ if (sc->valuetype && dc->valuetype && (sc->byval_arg.type == dc->byval_arg.type)) {
+ memcpy (dptr, sptr, esize * length);
+ return;
+ }
+
+ for (i = 0; i < length; i++) {
+ MonoObject *value;
+ int svt, dvt;
+
+ value = ves_icall_System_Array_GetValueImpl ((MonoObject *) sa, i);
+ if (ves_icall_System_Array_SetValueImpl ((MonoObject *) da, value, i, 0))
+ continue;
+
+ svt = sc->valuetype || (sc->byval_arg.type == MONO_TYPE_STRING);
+ dvt = dc->valuetype || (dc->byval_arg.type == MONO_TYPE_STRING);
+
+ if ((dc->valuetype || dc->byval_arg.type == MONO_TYPE_STRING) &&
+ (sc->byval_arg.type == MONO_TYPE_OBJECT))
+ mono_raise_exception (mono_get_exception_invalid_cast ());
+ else
+ mono_raise_exception (mono_get_exception_array_type_mismatch ());
+ }
}
static MonoArray *
@@ -451,16 +538,6 @@
}
static void
-ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
-{
- int element_size = mono_array_element_size (source->obj.vtable->klass);
- void * dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
- void * source_addr = mono_array_addr_with_size (source, element_size, dest_idx);
-
- memcpy (dest_addr, source_addr, element_size * length);
-}
-
-static void
ves_icall_InitializeArray (MonoArray *array, MonoClassField *field_handle)
{
MonoClass *klass = array->obj.vtable->klass;
@@ -1555,13 +1632,11 @@
*/
"System.Array::GetValue", ves_icall_System_Array_GetValue,
"System.Array::SetValue", ves_icall_System_Array_SetValue,
- "System.Array::GetValueImpl", ves_icall_System_Array_GetValueImpl,
- "System.Array::SetValueImpl", ves_icall_System_Array_SetValueImpl,
"System.Array::GetRank", ves_icall_System_Array_GetRank,
"System.Array::GetLength", ves_icall_System_Array_GetLength,
"System.Array::GetLowerBound", ves_icall_System_Array_GetLowerBound,
"System.Array::CreateInstanceImpl", ves_icall_System_Array_CreateInstanceImpl,
- "System.Array::FastCopy", ves_icall_System_Array_FastCopy,
+ "System.Array::CopyImpl", ves_icall_System_Array_CopyImpl,
"System.Array::Clone", mono_array_clone,
/*
--=-=-=
--
Martin Baulig
martin@gnome.org
--=-=-=--