5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (PLATFORM_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
76 #if defined (PLATFORM_WIN32)
82 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
85 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
87 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
88 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
96 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
98 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
100 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
101 (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
104 #define mono_ptr_array_destroy(ARRAY) do {\
105 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
106 mono_gc_free_fixed ((ARRAY).data); \
109 #define mono_ptr_array_append(ARRAY, VALUE) do { \
110 if ((ARRAY).size >= (ARRAY).capacity) {\
111 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
112 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
113 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
114 mono_gc_free_fixed ((ARRAY).data); \
115 (ARRAY).data = __tmp; \
116 (ARRAY).capacity *= 2;\
118 ((ARRAY).data [(ARRAY).size++] = VALUE); \
121 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
122 ((ARRAY).data [(IDX)] = VALUE); \
125 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
127 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
130 static inline MonoBoolean
131 is_generic_parameter (MonoType *type)
133 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
137 * We expect a pointer to a char, not a string
140 mono_double_ParseImpl (char *ptr, double *result)
142 gchar *endptr = NULL;
149 *result = strtod (ptr, &endptr);
153 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
154 EnterCriticalSection (&mono_strtod_mutex);
155 *result = mono_strtod (ptr, &endptr);
156 LeaveCriticalSection (&mono_strtod_mutex);
158 *result = mono_strtod (ptr, &endptr);
163 if (!*ptr || (endptr && *endptr))
170 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 esize = mono_array_element_size (ac);
183 ea = (gpointer*)((char*)ao->vector + (pos * esize));
185 if (ac->element_class->valuetype)
186 return mono_value_box (this->vtable->domain, ac->element_class, ea);
192 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
200 MONO_CHECK_ARG_NULL (idxs);
202 io = (MonoArray *)idxs;
203 ic = (MonoClass *)io->obj.vtable->klass;
205 ao = (MonoArray *)this;
206 ac = (MonoClass *)ao->obj.vtable->klass;
208 g_assert (ic->rank == 1);
209 if (io->bounds != NULL || io->max_length != ac->rank)
210 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
212 ind = (gint32 *)io->vector;
214 if (ao->bounds == NULL) {
215 if (*ind < 0 || *ind >= ao->max_length)
216 mono_raise_exception (mono_get_exception_index_out_of_range ());
218 return ves_icall_System_Array_GetValueImpl (this, *ind);
221 for (i = 0; i < ac->rank; i++)
222 if ((ind [i] < ao->bounds [i].lower_bound) ||
223 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
224 mono_raise_exception (mono_get_exception_index_out_of_range ());
226 pos = ind [0] - ao->bounds [0].lower_bound;
227 for (i = 1; i < ac->rank; i++)
228 pos = pos*ao->bounds [i].length + ind [i] -
229 ao->bounds [i].lower_bound;
231 return ves_icall_System_Array_GetValueImpl (this, pos);
235 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
237 MonoClass *ac, *vc, *ec;
249 vc = value->vtable->klass;
253 ac = this->obj.vtable->klass;
254 ec = ac->element_class;
256 esize = mono_array_element_size (ac);
257 ea = (gpointer*)((char*)this->vector + (pos * esize));
258 va = (gpointer*)((char*)value + sizeof (MonoObject));
261 memset (ea, 0, esize);
265 #define NO_WIDENING_CONVERSION G_STMT_START{\
266 mono_raise_exception (mono_get_exception_argument ( \
267 "value", "not a widening conversion")); \
270 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
271 if (esize < vsize + (extra)) \
272 mono_raise_exception (mono_get_exception_argument ( \
273 "value", "not a widening conversion")); \
276 #define INVALID_CAST G_STMT_START{\
277 mono_raise_exception (mono_get_exception_invalid_cast ()); \
280 /* Check element (destination) type. */
281 switch (ec->byval_arg.type) {
282 case MONO_TYPE_STRING:
283 switch (vc->byval_arg.type) {
284 case MONO_TYPE_STRING:
290 case MONO_TYPE_BOOLEAN:
291 switch (vc->byval_arg.type) {
292 case MONO_TYPE_BOOLEAN:
305 NO_WIDENING_CONVERSION;
312 if (!ec->valuetype) {
313 if (!mono_object_isinst (value, ec))
315 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
319 if (mono_object_isinst (value, ec)) {
320 if (ec->has_references)
321 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
323 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
330 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
332 et = ec->byval_arg.type;
333 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
334 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
336 vt = vc->byval_arg.type;
337 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
338 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
340 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
346 case MONO_TYPE_CHAR: \
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) u64; \
350 /* You can't assign a signed value to an unsigned array. */ \
355 /* You can't assign a floating point number to an integer array. */ \
358 NO_WIDENING_CONVERSION; \
362 #define ASSIGN_SIGNED(etype) G_STMT_START{\
368 CHECK_WIDENING_CONVERSION(0); \
369 *(etype *) ea = (etype) i64; \
371 /* You can assign an unsigned value to a signed array if the array's */ \
372 /* element size is larger than the value size. */ \
377 case MONO_TYPE_CHAR: \
378 CHECK_WIDENING_CONVERSION(1); \
379 *(etype *) ea = (etype) u64; \
381 /* You can't assign a floating point number to an integer array. */ \
384 NO_WIDENING_CONVERSION; \
388 #define ASSIGN_REAL(etype) G_STMT_START{\
392 CHECK_WIDENING_CONVERSION(0); \
393 *(etype *) ea = (etype) r64; \
395 /* All integer values fit into a floating point array, so we don't */ \
396 /* need to CHECK_WIDENING_CONVERSION here. */ \
401 *(etype *) ea = (etype) i64; \
407 case MONO_TYPE_CHAR: \
408 *(etype *) ea = (etype) u64; \
415 u64 = *(guint8 *) va;
418 u64 = *(guint16 *) va;
421 u64 = *(guint32 *) va;
424 u64 = *(guint64 *) va;
430 i64 = *(gint16 *) va;
433 i64 = *(gint32 *) va;
436 i64 = *(gint64 *) va;
439 r64 = *(gfloat *) va;
442 r64 = *(gdouble *) va;
445 u64 = *(guint16 *) va;
447 case MONO_TYPE_BOOLEAN:
448 /* Boolean is only compatible with itself. */
461 NO_WIDENING_CONVERSION;
468 /* If we can't do a direct copy, let's try a widening conversion. */
471 ASSIGN_UNSIGNED (guint16);
473 ASSIGN_UNSIGNED (guint8);
475 ASSIGN_UNSIGNED (guint16);
477 ASSIGN_UNSIGNED (guint32);
479 ASSIGN_UNSIGNED (guint64);
481 ASSIGN_SIGNED (gint8);
483 ASSIGN_SIGNED (gint16);
485 ASSIGN_SIGNED (gint32);
487 ASSIGN_SIGNED (gint64);
489 ASSIGN_REAL (gfloat);
491 ASSIGN_REAL (gdouble);
495 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
499 #undef NO_WIDENING_CONVERSION
500 #undef CHECK_WIDENING_CONVERSION
501 #undef ASSIGN_UNSIGNED
507 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
515 MONO_CHECK_ARG_NULL (idxs);
517 ic = idxs->obj.vtable->klass;
518 ac = this->obj.vtable->klass;
520 g_assert (ic->rank == 1);
521 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
522 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
524 ind = (gint32 *)idxs->vector;
526 if (this->bounds == NULL) {
527 if (*ind < 0 || *ind >= this->max_length)
528 mono_raise_exception (mono_get_exception_index_out_of_range ());
530 ves_icall_System_Array_SetValueImpl (this, value, *ind);
534 for (i = 0; i < ac->rank; i++)
535 if ((ind [i] < this->bounds [i].lower_bound) ||
536 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
537 mono_raise_exception (mono_get_exception_index_out_of_range ());
539 pos = ind [0] - this->bounds [0].lower_bound;
540 for (i = 1; i < ac->rank; i++)
541 pos = pos * this->bounds [i].length + ind [i] -
542 this->bounds [i].lower_bound;
544 ves_icall_System_Array_SetValueImpl (this, value, pos);
548 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
552 mono_array_size_t *sizes, i;
553 gboolean bounded = FALSE;
557 MONO_CHECK_ARG_NULL (type);
558 MONO_CHECK_ARG_NULL (lengths);
560 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
562 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
564 for (i = 0; i < mono_array_length (lengths); i++)
565 if (mono_array_get (lengths, gint32, i) < 0)
566 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
568 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
569 /* vectors are not the same as one dimensional arrays with no-zero bounds */
574 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
576 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
577 for (i = 0; i < aklass->rank; ++i) {
578 sizes [i] = mono_array_get (lengths, guint32, i);
580 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
582 sizes [i + aklass->rank] = 0;
585 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
591 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
595 mono_array_size_t *sizes, i;
596 gboolean bounded = FALSE;
600 MONO_CHECK_ARG_NULL (type);
601 MONO_CHECK_ARG_NULL (lengths);
603 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
605 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
607 for (i = 0; i < mono_array_length (lengths); i++)
608 if ((mono_array_get (lengths, gint64, i) < 0) ||
609 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
610 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
612 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
613 /* vectors are not the same as one dimensional arrays with no-zero bounds */
618 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
620 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
621 for (i = 0; i < aklass->rank; ++i) {
622 sizes [i] = mono_array_get (lengths, guint64, i);
624 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
626 sizes [i + aklass->rank] = 0;
629 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
635 ves_icall_System_Array_GetRank (MonoObject *this)
639 return this->vtable->klass->rank;
643 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
645 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
646 mono_array_size_t length;
650 if ((dimension < 0) || (dimension >= rank))
651 mono_raise_exception (mono_get_exception_index_out_of_range ());
653 if (this->bounds == NULL)
654 length = this->max_length;
656 length = this->bounds [dimension].length;
658 #ifdef MONO_BIG_ARRAYS
659 if (length > G_MAXINT32)
660 mono_raise_exception (mono_get_exception_overflow ());
666 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
668 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672 if ((dimension < 0) || (dimension >= rank))
673 mono_raise_exception (mono_get_exception_index_out_of_range ());
675 if (this->bounds == NULL)
676 return this->max_length;
678 return this->bounds [dimension].length;
682 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
684 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
688 if ((dimension < 0) || (dimension >= rank))
689 mono_raise_exception (mono_get_exception_index_out_of_range ());
691 if (this->bounds == NULL)
694 return this->bounds [dimension].lower_bound;
698 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
700 int sz = mono_array_element_size (mono_object_class (arr));
701 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
705 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
710 MonoClass *src_class;
711 MonoClass *dest_class;
716 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
719 if (source->bounds || dest->bounds)
722 if ((dest_idx + length > mono_array_length (dest)) ||
723 (source_idx + length > mono_array_length (source)))
726 src_class = source->obj.vtable->klass->element_class;
727 dest_class = dest->obj.vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
734 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
735 int has_refs = dest_class->has_references;
736 for (i = source_idx; i < source_idx + length; ++i) {
737 MonoObject *elem = mono_array_get (source, MonoObject*, i);
738 if (elem && !mono_object_isinst (elem, dest_class))
742 element_size = mono_array_element_size (dest->obj.vtable->klass);
743 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
744 for (i = 0; i < length; ++i) {
745 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
746 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
750 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
752 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
757 /* Check if we're copying a char[] <==> (u)short[] */
758 if (src_class != dest_class) {
759 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
762 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
764 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
765 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
766 for (i = source_idx; i < source_idx + length; ++i) {
767 MonoObject *elem = mono_array_get (source, MonoObject*, i);
768 if (elem && !mono_object_isinst (elem, dest_class))
775 if (dest_class->valuetype) {
776 element_size = mono_array_element_size (source->obj.vtable->klass);
777 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
778 if (dest_class->has_references) {
779 mono_value_copy_array (dest, dest_idx, source_addr, length);
781 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
782 memmove (dest_addr, source_addr, element_size * length);
785 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
792 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
801 ao = (MonoArray *)this;
802 ac = (MonoClass *)ao->obj.vtable->klass;
804 esize = mono_array_element_size (ac);
805 ea = (gpointer*)((char*)ao->vector + (pos * esize));
807 memcpy (value, ea, esize);
811 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
820 ao = (MonoArray *)this;
821 ac = (MonoClass *)ao->obj.vtable->klass;
822 ec = ac->element_class;
824 esize = mono_array_element_size (ac);
825 ea = (gpointer*)((char*)ao->vector + (pos * esize));
827 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
828 g_assert (esize == sizeof (gpointer));
829 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
831 g_assert (ec->inited);
832 if (ec->has_references)
833 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
834 memcpy (ea, value, esize);
839 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
841 MonoClass *klass = array->obj.vtable->klass;
842 guint32 size = mono_array_element_size (klass);
843 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
845 const char *field_data;
847 if (MONO_TYPE_IS_REFERENCE (type) ||
848 (type->type == MONO_TYPE_VALUETYPE &&
849 (!mono_type_get_class (type) ||
850 mono_type_get_class (type)->has_references))) {
851 MonoException *exc = mono_get_exception_argument("array",
852 "Cannot initialize array containing references");
853 mono_raise_exception (exc);
856 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field doesn't have an RVA");
859 mono_raise_exception (exc);
862 size *= array->max_length;
863 field_data = mono_field_get_data (field_handle);
865 if (size > mono_type_size (field_handle->type, &align)) {
866 MonoException *exc = mono_get_exception_argument("field_handle",
867 "Field not large enough to fill array");
868 mono_raise_exception (exc);
871 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
873 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
874 guint ## n *src = (guint ## n *) field_data; \
875 guint ## n *end = (guint ## n *)((char*)src + size); \
877 for (; src < end; data++, src++) { \
878 *data = read ## n (src); \
882 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
884 switch (type->type) {
901 memcpy (mono_array_addr (array, char, 0), field_data, size);
905 memcpy (mono_array_addr (array, char, 0), field_data, size);
907 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
910 double *data = (double*)mono_array_addr (array, double, 0);
912 for (i = 0; i < size; i++, data++) {
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
926 return offsetof (MonoString, chars);
930 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
934 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
937 return mono_object_clone (obj);
941 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
947 MONO_CHECK_ARG_NULL (handle);
949 klass = mono_class_from_mono_type (handle);
950 MONO_CHECK_ARG (handle, klass);
952 /* This will call the type constructor */
953 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
957 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
961 mono_image_check_for_module_cctor (image);
962 if (image->has_module_cctor) {
963 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
964 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
969 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
973 return mono_object_clone (this);
977 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
980 MonoObject **values = NULL;
984 MonoClassField* field;
989 klass = mono_object_class (this);
991 if (mono_class_num_fields (klass) == 0)
992 return mono_object_hash (this);
995 * Compute the starting value of the hashcode for fields of primitive
996 * types, and return the remaining fields in an array to the managed side.
997 * This way, we can avoid costly reflection operations in managed code.
1000 while ((field = mono_class_get_fields (klass, &iter))) {
1001 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1003 if (mono_field_is_deleted (field))
1005 /* FIXME: Add more types */
1006 switch (field->type->type) {
1008 result ^= *(gint32*)((guint8*)this + field->offset);
1010 case MONO_TYPE_STRING: {
1012 s = *(MonoString**)((guint8*)this + field->offset);
1014 result ^= mono_string_hash (s);
1019 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1020 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1021 values [count++] = o;
1027 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1028 for (i = 0; i < count; ++i)
1029 mono_array_setref (*fields, i, values [i]);
1037 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1040 MonoObject **values = NULL;
1042 MonoClassField* field;
1046 MONO_ARCH_SAVE_REGS;
1048 MONO_CHECK_ARG_NULL (that);
1050 if (this->vtable != that->vtable)
1053 klass = mono_object_class (this);
1055 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1056 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1059 * Do the comparison for fields of primitive type and return a result if
1060 * possible. Otherwise, return the remaining fields in an array to the
1061 * managed side. This way, we can avoid costly reflection operations in
1066 while ((field = mono_class_get_fields (klass, &iter))) {
1067 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1069 if (mono_field_is_deleted (field))
1071 /* FIXME: Add more types */
1072 switch (field->type->type) {
1075 case MONO_TYPE_BOOLEAN:
1076 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1081 case MONO_TYPE_CHAR:
1082 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1087 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1092 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1096 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1100 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1105 case MONO_TYPE_STRING: {
1106 MonoString *s1, *s2;
1107 guint32 s1len, s2len;
1108 s1 = *(MonoString**)((guint8*)this + field->offset);
1109 s2 = *(MonoString**)((guint8*)that + field->offset);
1112 if ((s1 == NULL) || (s2 == NULL))
1114 s1len = mono_string_length (s1);
1115 s2len = mono_string_length (s2);
1119 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1125 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1126 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1127 values [count++] = o;
1128 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1129 values [count++] = o;
1132 if (klass->enumtype)
1133 /* enums only have one non-static field */
1139 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1140 for (i = 0; i < count; ++i)
1141 mono_array_setref (*fields, i, values [i]);
1148 static MonoReflectionType *
1149 ves_icall_System_Object_GetType (MonoObject *obj)
1151 MONO_ARCH_SAVE_REGS;
1153 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1154 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1156 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1160 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1162 MONO_ARCH_SAVE_REGS;
1164 mtype->type = &obj->vtable->klass->byval_arg;
1165 g_assert (mtype->type->type);
1169 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1171 MONO_ARCH_SAVE_REGS;
1173 MONO_CHECK_ARG_NULL (obj);
1175 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1179 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1180 MonoReflectionMethod *method,
1181 MonoArray *opt_param_types)
1183 MONO_ARCH_SAVE_REGS;
1185 MONO_CHECK_ARG_NULL (method);
1187 return mono_image_create_method_token (
1188 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1192 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1194 MONO_ARCH_SAVE_REGS;
1196 mono_image_create_pefile (mb, file);
1200 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1202 MONO_ARCH_SAVE_REGS;
1204 mono_image_build_metadata (mb);
1208 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1210 MONO_ARCH_SAVE_REGS;
1212 mono_image_register_token (mb->dynamic_image, token, obj);
1216 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1218 MonoMethod **dest = data;
1220 /* skip unmanaged frames */
1236 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1238 MonoMethod **dest = data;
1240 /* skip unmanaged frames */
1245 if (!strcmp (m->klass->name_space, "System.Reflection"))
1254 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1256 MonoMethod **dest = data;
1258 /* skip unmanaged frames */
1262 if (m->wrapper_type != MONO_WRAPPER_NONE)
1265 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1279 static MonoReflectionType *
1280 type_from_name (const char *str, MonoBoolean ignoreCase)
1282 MonoType *type = NULL;
1283 MonoAssembly *assembly = NULL;
1284 MonoTypeNameParse info;
1285 char *temp_str = g_strdup (str);
1286 gboolean type_resolve = FALSE;
1288 MONO_ARCH_SAVE_REGS;
1290 /* mono_reflection_parse_type() mangles the string */
1291 if (!mono_reflection_parse_type (temp_str, &info)) {
1292 mono_reflection_free_type_info (&info);
1297 if (info.assembly.name) {
1298 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1300 MonoMethod *m = mono_method_get_last_managed ();
1301 MonoMethod *dest = m;
1303 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1308 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1309 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1310 * to crash. This only seems to happen in some strange remoting
1311 * scenarios and I was unable to figure out what's happening there.
1312 * Dec 10, 2005 - Martin.
1316 assembly = dest->klass->image->assembly;
1318 g_warning (G_STRLOC);
1323 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1325 if (!info.assembly.name && !type) /* try mscorlib */
1326 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1328 mono_reflection_free_type_info (&info);
1334 return mono_type_get_object (mono_domain_get (), type);
1338 MonoReflectionType *
1339 mono_type_get (const char *str)
1341 char *copy = g_strdup (str);
1342 MonoReflectionType *type = type_from_name (copy, FALSE);
1349 static MonoReflectionType*
1350 ves_icall_type_from_name (MonoString *name,
1351 MonoBoolean throwOnError,
1352 MonoBoolean ignoreCase)
1354 char *str = mono_string_to_utf8 (name);
1355 MonoReflectionType *type;
1357 type = type_from_name (str, ignoreCase);
1360 MonoException *e = NULL;
1363 e = mono_get_exception_type_load (name, NULL);
1365 mono_loader_clear_error ();
1367 mono_raise_exception (e);
1374 static MonoReflectionType*
1375 ves_icall_type_from_handle (MonoType *handle)
1377 MonoDomain *domain = mono_domain_get ();
1378 MonoClass *klass = mono_class_from_mono_type (handle);
1380 MONO_ARCH_SAVE_REGS;
1382 mono_class_init (klass);
1383 return mono_type_get_object (domain, handle);
1387 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1389 MONO_ARCH_SAVE_REGS;
1391 if (c && type->type && c->type)
1392 return mono_metadata_type_equal (type->type, c->type);
1394 return (type == c) ? TRUE : FALSE;
1397 /* System.TypeCode */
1416 TYPECODE_STRING = 18
1420 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1422 int t = type->type->type;
1424 MONO_ARCH_SAVE_REGS;
1426 if (type->type->byref)
1427 return TYPECODE_OBJECT;
1431 case MONO_TYPE_VOID:
1432 return TYPECODE_OBJECT;
1433 case MONO_TYPE_BOOLEAN:
1434 return TYPECODE_BOOLEAN;
1436 return TYPECODE_BYTE;
1438 return TYPECODE_SBYTE;
1440 return TYPECODE_UINT16;
1442 return TYPECODE_INT16;
1443 case MONO_TYPE_CHAR:
1444 return TYPECODE_CHAR;
1448 return TYPECODE_OBJECT;
1450 return TYPECODE_UINT32;
1452 return TYPECODE_INT32;
1454 return TYPECODE_UINT64;
1456 return TYPECODE_INT64;
1458 return TYPECODE_SINGLE;
1460 return TYPECODE_DOUBLE;
1461 case MONO_TYPE_VALUETYPE:
1462 if (type->type->data.klass->enumtype) {
1463 t = mono_class_enum_basetype (type->type->data.klass)->type;
1466 MonoClass *k = type->type->data.klass;
1467 if (strcmp (k->name_space, "System") == 0) {
1468 if (strcmp (k->name, "Decimal") == 0)
1469 return TYPECODE_DECIMAL;
1470 else if (strcmp (k->name, "DateTime") == 0)
1471 return TYPECODE_DATETIME;
1474 return TYPECODE_OBJECT;
1475 case MONO_TYPE_STRING:
1476 return TYPECODE_STRING;
1477 case MONO_TYPE_SZARRAY:
1478 case MONO_TYPE_ARRAY:
1479 case MONO_TYPE_OBJECT:
1481 case MONO_TYPE_MVAR:
1482 case MONO_TYPE_TYPEDBYREF:
1483 return TYPECODE_OBJECT;
1484 case MONO_TYPE_CLASS:
1486 MonoClass *k = type->type->data.klass;
1487 if (strcmp (k->name_space, "System") == 0) {
1488 if (strcmp (k->name, "DBNull") == 0)
1489 return TYPECODE_DBNULL;
1492 return TYPECODE_OBJECT;
1493 case MONO_TYPE_GENERICINST:
1494 return TYPECODE_OBJECT;
1496 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1502 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1508 MONO_ARCH_SAVE_REGS;
1510 g_assert (type != NULL);
1512 domain = ((MonoObject *)type)->vtable->domain;
1514 if (!c) /* FIXME: dont know what do do here */
1517 klass = mono_class_from_mono_type (type->type);
1518 klassc = mono_class_from_mono_type (c->type);
1520 if (type->type->byref)
1521 return klassc == mono_defaults.object_class;
1523 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1527 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1533 MONO_ARCH_SAVE_REGS;
1535 g_assert (type != NULL);
1537 domain = ((MonoObject *)type)->vtable->domain;
1539 klass = mono_class_from_mono_type (type->type);
1540 klassc = mono_class_from_mono_type (c->type);
1542 if (type->type->byref && !c->type->byref)
1545 return mono_class_is_assignable_from (klass, klassc);
1549 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1551 MonoClass *klass = mono_class_from_mono_type (type->type);
1552 return mono_object_isinst (obj, klass) != NULL;
1556 ves_icall_get_attributes (MonoReflectionType *type)
1558 MonoClass *klass = mono_class_from_mono_type (type->type);
1560 MONO_ARCH_SAVE_REGS;
1562 return klass->flags;
1565 static MonoReflectionMarshal*
1566 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1568 MonoClass *klass = field->field->parent;
1569 MonoMarshalType *info;
1572 if (klass->generic_container ||
1573 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1576 info = mono_marshal_load_type_info (klass);
1578 for (i = 0; i < info->num_fields; ++i) {
1579 if (info->fields [i].field == field->field) {
1580 if (!info->fields [i].mspec)
1583 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1590 static MonoReflectionField*
1591 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1596 klass = handle->parent;
1598 /* FIXME: check that handle is a field of klass or of a parent: return null
1599 * and throw the exception in managed code.
1601 return mono_field_get_object (mono_domain_get (), klass, handle);
1604 static MonoReflectionField*
1605 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1607 MONO_ARCH_SAVE_REGS;
1611 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1615 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1617 MonoType *type = field->field->type;
1619 return type_array_from_modifiers (field->field->parent->image, type, optional);
1623 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1625 MonoDomain *domain = mono_domain_get ();
1626 MonoMethodSignature* sig;
1627 MONO_ARCH_SAVE_REGS;
1629 sig = mono_method_signature (method);
1631 g_assert (mono_loader_get_last_error ());
1632 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1635 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1636 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1637 info->attrs = method->flags;
1638 info->implattrs = method->iflags;
1639 if (sig->call_convention == MONO_CALL_DEFAULT)
1640 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1642 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1647 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1651 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1653 MonoDomain *domain = mono_domain_get ();
1655 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1658 static MonoReflectionMarshal*
1659 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1661 MonoDomain *domain = mono_domain_get ();
1662 MonoReflectionMarshal* res = NULL;
1663 MonoMarshalSpec **mspecs;
1666 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1667 mono_method_get_marshal_info (method, mspecs);
1670 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1672 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1674 mono_metadata_free_marshal_spec (mspecs [i]);
1681 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1683 return field->field->offset - sizeof (MonoObject);
1686 static MonoReflectionType*
1687 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1690 MONO_ARCH_SAVE_REGS;
1692 parent = declaring? field->field->parent: field->klass;
1694 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1698 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1701 MonoClassField *cf = field->field;
1705 MonoDomain *domain = mono_object_domain (field);
1707 gboolean is_static = FALSE;
1708 gboolean is_ref = FALSE;
1710 MONO_ARCH_SAVE_REGS;
1712 if (field->klass->image->assembly->ref_only)
1713 mono_raise_exception (mono_get_exception_invalid_operation (
1714 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1716 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1717 mono_security_core_clr_ensure_reflection_access_field (cf);
1719 mono_class_init (field->klass);
1721 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1724 if (obj && !is_static) {
1725 /* Check that the field belongs to the object */
1726 gboolean found = FALSE;
1729 for (k = obj->vtable->klass; k; k = k->parent) {
1730 if (k == cf->parent) {
1737 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1738 MonoException *ex = mono_get_exception_argument (NULL, msg);
1740 mono_raise_exception (ex);
1744 t = mono_type_get_underlying_type (cf->type);
1746 case MONO_TYPE_STRING:
1747 case MONO_TYPE_OBJECT:
1748 case MONO_TYPE_CLASS:
1749 case MONO_TYPE_ARRAY:
1750 case MONO_TYPE_SZARRAY:
1755 case MONO_TYPE_BOOLEAN:
1758 case MONO_TYPE_CHAR:
1767 case MONO_TYPE_VALUETYPE:
1770 case MONO_TYPE_GENERICINST:
1771 if (mono_type_generic_inst_is_valuetype (t)) {
1778 g_error ("type 0x%x not handled in "
1779 "ves_icall_Monofield_GetValue", t->type);
1785 vtable = mono_class_vtable (domain, cf->parent);
1786 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1787 mono_runtime_class_init (vtable);
1792 mono_field_static_get_value (vtable, cf, &o);
1794 mono_field_get_value (obj, cf, &o);
1799 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1800 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1803 /* Convert the Nullable structure into a boxed vtype */
1805 buf = (guint8*)vtable->data + cf->offset;
1807 buf = (guint8*)obj + cf->offset;
1809 return mono_nullable_box (buf, nklass);
1812 /* boxed value type */
1813 klass = mono_class_from_mono_type (cf->type);
1814 o = mono_object_new (domain, klass);
1815 v = ((gchar *) o) + sizeof (MonoObject);
1817 mono_field_static_get_value (vtable, cf, v);
1819 mono_field_get_value (obj, cf, v);
1826 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1828 MonoClassField *cf = field->field;
1831 MONO_ARCH_SAVE_REGS;
1833 if (field->klass->image->assembly->ref_only)
1834 mono_raise_exception (mono_get_exception_invalid_operation (
1835 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1837 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1838 mono_security_core_clr_ensure_reflection_access_field (cf);
1840 v = (gchar *) value;
1841 if (!cf->type->byref) {
1842 switch (cf->type->type) {
1845 case MONO_TYPE_BOOLEAN:
1848 case MONO_TYPE_CHAR:
1857 case MONO_TYPE_VALUETYPE:
1859 v += sizeof (MonoObject);
1861 case MONO_TYPE_STRING:
1862 case MONO_TYPE_OBJECT:
1863 case MONO_TYPE_CLASS:
1864 case MONO_TYPE_ARRAY:
1865 case MONO_TYPE_SZARRAY:
1868 case MONO_TYPE_GENERICINST: {
1869 MonoGenericClass *gclass = cf->type->data.generic_class;
1870 g_assert (!gclass->context.class_inst->is_open);
1872 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1873 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1874 MonoObject *nullable;
1877 * Convert the boxed vtype into a Nullable structure.
1878 * This is complicated by the fact that Nullables have
1879 * a variable structure.
1881 nullable = mono_object_new (mono_domain_get (), nklass);
1883 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1885 v = mono_object_unbox (nullable);
1888 if (gclass->container_class->valuetype && (v != NULL))
1889 v += sizeof (MonoObject);
1893 g_error ("type 0x%x not handled in "
1894 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1899 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1900 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1901 if (!vtable->initialized)
1902 mono_runtime_class_init (vtable);
1903 mono_field_static_set_value (vtable, cf, v);
1905 mono_field_set_value (obj, cf, v);
1910 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1912 MonoObject *o = NULL;
1913 MonoClassField *field = this->field;
1915 MonoDomain *domain = mono_object_domain (this);
1917 MonoTypeEnum def_type;
1918 const char *def_value;
1920 MONO_ARCH_SAVE_REGS;
1922 mono_class_init (field->parent);
1924 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1925 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1927 if (field->parent->image->dynamic) {
1929 g_assert_not_reached ();
1932 def_value = mono_class_get_field_default_value (field, &def_type);
1937 case MONO_TYPE_BOOLEAN:
1940 case MONO_TYPE_CHAR:
1948 case MONO_TYPE_R8: {
1951 /* boxed value type */
1952 t = g_new0 (MonoType, 1);
1954 klass = mono_class_from_mono_type (t);
1956 o = mono_object_new (domain, klass);
1957 v = ((gchar *) o) + sizeof (MonoObject);
1958 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1961 case MONO_TYPE_STRING:
1962 case MONO_TYPE_CLASS:
1963 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1966 g_assert_not_reached ();
1972 static MonoReflectionType*
1973 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1975 MonoMethod *method = rmethod->method.method;
1977 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1980 /* From MonoProperty.cs */
1982 PInfo_Attributes = 1,
1983 PInfo_GetMethod = 1 << 1,
1984 PInfo_SetMethod = 1 << 2,
1985 PInfo_ReflectedType = 1 << 3,
1986 PInfo_DeclaringType = 1 << 4,
1991 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1993 MonoDomain *domain = mono_object_domain (property);
1995 MONO_ARCH_SAVE_REGS;
1997 if ((req_info & PInfo_ReflectedType) != 0)
1998 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1999 else if ((req_info & PInfo_DeclaringType) != 0)
2000 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2002 if ((req_info & PInfo_Name) != 0)
2003 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2005 if ((req_info & PInfo_Attributes) != 0)
2006 info->attrs = property->property->attrs;
2008 if ((req_info & PInfo_GetMethod) != 0)
2009 MONO_STRUCT_SETREF (info, get, property->property->get ?
2010 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2012 if ((req_info & PInfo_SetMethod) != 0)
2013 MONO_STRUCT_SETREF (info, set, property->property->set ?
2014 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2016 * There may be other methods defined for properties, though, it seems they are not exposed
2017 * in the reflection API
2022 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2024 MonoDomain *domain = mono_object_domain (event);
2026 MONO_ARCH_SAVE_REGS;
2028 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2029 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2031 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2032 info->attrs = event->event->attrs;
2033 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2034 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2035 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2037 if (event->event->other) {
2039 while (event->event->other [n])
2041 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2043 for (i = 0; i < n; i++)
2044 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2049 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2051 MonoDomain *domain = mono_object_domain (type);
2053 GPtrArray *ifaces = NULL;
2055 MonoClass *class = mono_class_from_mono_type (type->type);
2058 MonoGenericContext *context = NULL;
2060 MONO_ARCH_SAVE_REGS;
2062 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2063 context = mono_class_get_context (class);
2064 class = class->generic_class->container_class;
2067 mono_class_setup_vtable (class);
2069 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2071 for (parent = class; parent; parent = parent->parent) {
2072 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2074 for (i = 0; i < tmp_ifaces->len; ++i) {
2075 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2077 if (mono_bitset_test (slots, ic->interface_id))
2080 mono_bitset_set (slots, ic->interface_id);
2082 ifaces = g_ptr_array_new ();
2083 g_ptr_array_add (ifaces, ic);
2085 g_ptr_array_free (tmp_ifaces, TRUE);
2088 mono_bitset_free (slots);
2091 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2093 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2094 for (i = 0; i < ifaces->len; ++i) {
2095 MonoClass *ic = g_ptr_array_index (ifaces, i);
2096 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2097 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2098 inflated = ret = mono_class_inflate_generic_type (ret, context);
2100 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2102 mono_metadata_free_type (inflated);
2104 g_ptr_array_free (ifaces, TRUE);
2110 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2112 MonoClass *class = mono_class_from_mono_type (type->type);
2113 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2114 MonoReflectionMethod *member;
2117 int i = 0, len, ioffset;
2120 MONO_ARCH_SAVE_REGS;
2122 mono_class_setup_vtable (class);
2124 /* type doesn't implement iface: the exception is thrown in managed code */
2125 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2128 len = mono_class_num_methods (iclass);
2129 ioffset = mono_class_interface_offset (class, iclass);
2130 domain = mono_object_domain (type);
2131 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2132 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2135 while ((method = mono_class_get_methods (iclass, &iter))) {
2136 member = mono_method_get_object (domain, method, iclass);
2137 mono_array_setref (*methods, i, member);
2138 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2139 mono_array_setref (*targets, i, member);
2146 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2148 MonoClass *klass = mono_class_from_mono_type (type->type);
2150 if (klass->image->dynamic) {
2151 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2152 *packing = tb->packing_size;
2153 *size = tb->class_size;
2155 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2159 static MonoReflectionType*
2160 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2164 MONO_ARCH_SAVE_REGS;
2166 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2167 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2169 class = mono_class_from_mono_type (type->type);
2171 // GetElementType should only return a type for:
2172 // Array Pointer PassedByRef
2173 if (type->type->byref)
2174 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2175 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2176 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2177 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2178 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2183 static MonoReflectionType*
2184 ves_icall_get_type_parent (MonoReflectionType *type)
2186 MonoClass *class = mono_class_from_mono_type (type->type);
2188 MONO_ARCH_SAVE_REGS;
2190 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2194 ves_icall_type_ispointer (MonoReflectionType *type)
2196 MONO_ARCH_SAVE_REGS;
2198 return type->type->type == MONO_TYPE_PTR;
2202 ves_icall_type_isprimitive (MonoReflectionType *type)
2204 MONO_ARCH_SAVE_REGS;
2206 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2210 ves_icall_type_isbyref (MonoReflectionType *type)
2212 MONO_ARCH_SAVE_REGS;
2214 return type->type->byref;
2218 ves_icall_type_iscomobject (MonoReflectionType *type)
2220 MonoClass *klass = mono_class_from_mono_type (type->type);
2221 MONO_ARCH_SAVE_REGS;
2223 return (klass && klass->is_com_object);
2226 static MonoReflectionModule*
2227 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2229 MonoClass *class = mono_class_from_mono_type (type->type);
2231 MONO_ARCH_SAVE_REGS;
2233 return mono_module_get_object (mono_object_domain (type), class->image);
2236 static MonoReflectionAssembly*
2237 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2240 MonoClass *class = mono_class_from_mono_type (type->type);
2242 MONO_ARCH_SAVE_REGS;
2244 return mono_assembly_get_object (domain, class->image->assembly);
2247 static MonoReflectionType*
2248 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2250 MonoDomain *domain = mono_domain_get ();
2253 MONO_ARCH_SAVE_REGS;
2255 if (type->type->byref)
2257 if (type->type->type == MONO_TYPE_VAR)
2258 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2259 else if (type->type->type == MONO_TYPE_MVAR)
2260 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2262 class = mono_class_from_mono_type (type->type)->nested_in;
2264 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2267 static MonoReflectionType*
2268 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2270 MonoDomain *domain = mono_domain_get ();
2271 MonoClass *class = mono_class_from_mono_type (type->type);
2273 MONO_ARCH_SAVE_REGS;
2275 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2276 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2277 else if (class->element_class)
2278 return mono_type_get_object (domain, &class->element_class->byval_arg);
2284 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2286 MonoDomain *domain = mono_domain_get ();
2287 MonoClass *class = mono_class_from_mono_type (type->type);
2289 MONO_ARCH_SAVE_REGS;
2291 if (type->type->byref) {
2292 char *n = g_strdup_printf ("%s&", class->name);
2293 MonoString *res = mono_string_new (domain, n);
2299 return mono_string_new (domain, class->name);
2304 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2306 MonoDomain *domain = mono_domain_get ();
2307 MonoClass *class = mono_class_from_mono_type (type->type);
2309 MONO_ARCH_SAVE_REGS;
2311 while (class->nested_in)
2312 class = class->nested_in;
2314 if (class->name_space [0] == '\0')
2317 return mono_string_new (domain, class->name_space);
2321 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2323 MonoClass *class = mono_class_from_mono_type (type->type);
2325 MONO_ARCH_SAVE_REGS;
2331 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2334 MonoClass *klass, *pklass;
2335 MonoDomain *domain = mono_object_domain (type);
2336 MonoVTable *array_vtable = mono_class_vtable (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1));
2338 MONO_ARCH_SAVE_REGS;
2340 klass = mono_class_from_mono_type (type->type);
2342 if (klass->generic_container) {
2343 MonoGenericContainer *container = klass->generic_container;
2344 res = mono_array_new_specific (array_vtable, container->type_argc);
2345 for (i = 0; i < container->type_argc; ++i) {
2346 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2347 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2349 } else if (klass->generic_class) {
2350 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2351 res = mono_array_new_specific (array_vtable, inst->type_argc);
2352 for (i = 0; i < inst->type_argc; ++i)
2353 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2355 res = mono_array_new_specific (array_vtable, 0);
2361 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2364 MONO_ARCH_SAVE_REGS;
2366 if (!IS_MONOTYPE (type))
2369 if (type->type->byref)
2372 klass = mono_class_from_mono_type (type->type);
2374 return klass->generic_container != NULL;
2377 static MonoReflectionType*
2378 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2381 MONO_ARCH_SAVE_REGS;
2383 if (type->type->byref)
2386 klass = mono_class_from_mono_type (type->type);
2387 if (klass->generic_container) {
2388 return type; /* check this one */
2390 if (klass->generic_class) {
2391 MonoClass *generic_class = klass->generic_class->container_class;
2393 if (generic_class->wastypebuilder && generic_class->reflection_info)
2394 return generic_class->reflection_info;
2396 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2401 static MonoReflectionType*
2402 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2404 MonoType *geninst, **types;
2407 MONO_ARCH_SAVE_REGS;
2409 count = mono_array_length (type_array);
2410 types = g_new0 (MonoType *, count);
2412 for (i = 0; i < count; i++) {
2413 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2414 types [i] = t->type;
2417 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2422 return mono_type_get_object (mono_object_domain (type), geninst);
2426 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2429 MONO_ARCH_SAVE_REGS;
2431 if (type->type->byref)
2434 klass = mono_class_from_mono_type (type->type);
2435 return klass->generic_class != NULL;
2439 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2442 MONO_ARCH_SAVE_REGS;
2444 if (!IS_MONOTYPE (type))
2447 if (type->type->byref)
2450 klass = mono_class_from_mono_type (type->type);
2451 return klass->generic_class != NULL || klass->generic_container != NULL;
2455 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2457 MONO_ARCH_SAVE_REGS;
2459 if (!IS_MONOTYPE (type))
2462 if (is_generic_parameter (type->type))
2463 return mono_type_get_generic_param_num (type->type);
2467 static GenericParameterAttributes
2468 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2470 MONO_ARCH_SAVE_REGS;
2472 g_assert (IS_MONOTYPE (type));
2473 g_assert (is_generic_parameter (type->type));
2474 return mono_generic_param_info (type->type->data.generic_param)->flags;
2478 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2480 MonoGenericParamInfo *param_info;
2486 MONO_ARCH_SAVE_REGS;
2488 g_assert (IS_MONOTYPE (type));
2490 domain = mono_object_domain (type);
2491 param_info = mono_generic_param_info (type->type->data.generic_param);
2492 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2495 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2496 for (i = 0; i < count; i++)
2497 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2504 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2506 MONO_ARCH_SAVE_REGS;
2507 return is_generic_parameter (type->type);
2511 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2513 MONO_ARCH_SAVE_REGS;
2514 return is_generic_parameter (tb->type.type);
2518 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2519 MonoReflectionType *t)
2521 enumtype->type = t->type;
2524 static MonoReflectionType*
2525 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2527 MonoDynamicGenericClass *gclass;
2528 MonoReflectionType *parent = NULL, *res;
2534 MONO_ARCH_SAVE_REGS;
2536 g_assert (type->type.type->data.generic_class->is_dynamic);
2537 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2539 domain = mono_object_domain (type);
2540 klass = mono_class_from_mono_type (type->generic_type->type.type);
2542 if (!klass->generic_class && !klass->generic_container)
2545 parent = monotype_cast (type->generic_type->parent);
2547 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2550 inflated = mono_class_inflate_generic_type (
2551 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2553 res = mono_type_get_object (domain, inflated);
2554 mono_metadata_free_type (inflated);
2559 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2561 static MonoClass *System_Reflection_MonoGenericClass;
2562 MonoGenericClass *gclass;
2563 MonoReflectionTypeBuilder *tb = NULL;
2564 MonoClass *klass = NULL;
2569 MONO_ARCH_SAVE_REGS;
2571 if (!System_Reflection_MonoGenericClass) {
2572 System_Reflection_MonoGenericClass = mono_class_from_name (
2573 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2574 g_assert (System_Reflection_MonoGenericClass);
2577 domain = mono_object_domain (type);
2579 gclass = type->type.type->data.generic_class;
2580 g_assert (gclass->is_dynamic);
2582 tb = type->generic_type;
2583 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2585 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2587 for (i = 0; i < icount; i++) {
2588 MonoReflectionType *iface;
2592 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2595 it = &klass->interfaces [i]->byval_arg;
2597 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2599 iface = mono_type_get_object (domain, it);
2600 mono_array_setref (res, i, iface);
2601 mono_metadata_free_type (it);
2607 static MonoReflectionMethod*
2608 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2609 MonoReflectionMethod* generic)
2611 MonoGenericClass *gclass;
2612 MonoDynamicGenericClass *dgclass;
2616 MONO_ARCH_SAVE_REGS;
2618 gclass = type->type.type->data.generic_class;
2619 g_assert (gclass->is_dynamic);
2621 dgclass = (MonoDynamicGenericClass *) gclass;
2623 domain = mono_object_domain (type);
2625 for (i = 0; i < dgclass->count_methods; i++)
2626 if (generic->method->token == dgclass->methods [i]->token)
2627 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2632 static MonoReflectionMethod*
2633 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2634 MonoReflectionMethod* generic)
2636 MonoGenericClass *gclass;
2637 MonoDynamicGenericClass *dgclass;
2641 MONO_ARCH_SAVE_REGS;
2643 gclass = type->type.type->data.generic_class;
2644 g_assert (gclass->is_dynamic);
2646 dgclass = (MonoDynamicGenericClass *) gclass;
2648 domain = mono_object_domain (type);
2650 for (i = 0; i < dgclass->count_ctors; i++)
2651 if (generic->method->token == dgclass->ctors [i]->token)
2652 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2658 static MonoReflectionField*
2659 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2660 MonoString* generic_name)
2662 MonoGenericClass *gclass;
2663 MonoDynamicGenericClass *dgclass;
2665 MonoClass *refclass;
2666 char *utf8_name = mono_string_to_utf8 (generic_name);
2669 MONO_ARCH_SAVE_REGS;
2671 gclass = type->type.type->data.generic_class;
2672 g_assert (gclass->is_dynamic);
2674 dgclass = (MonoDynamicGenericClass *) gclass;
2676 refclass = mono_class_from_mono_type (type->type.type);
2678 domain = mono_object_domain (type);
2680 for (i = 0; i < dgclass->count_fields; i++)
2681 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2683 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2692 static MonoReflectionMethod*
2693 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2694 MonoReflectionMethod* generic)
2701 MONO_ARCH_SAVE_REGS;
2703 domain = ((MonoObject *)type)->vtable->domain;
2705 klass = mono_class_from_mono_type (type->type);
2708 while ((method = mono_class_get_methods (klass, &iter))) {
2709 if (method->token == generic->method->token)
2710 return mono_method_get_object (domain, method, klass);
2717 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2718 MonoReflectionType *reflected_type)
2720 MonoGenericClass *gclass;
2721 MonoDynamicGenericClass *dgclass;
2723 MonoClass *refclass;
2727 MONO_ARCH_SAVE_REGS;
2729 gclass = type->type.type->data.generic_class;
2730 g_assert (gclass->is_dynamic);
2731 dgclass = (MonoDynamicGenericClass *) gclass;
2733 refclass = mono_class_from_mono_type (reflected_type->type);
2735 domain = mono_object_domain (type);
2736 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2738 for (i = 0; i < dgclass->count_methods; i++)
2739 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2745 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2746 MonoReflectionType *reflected_type)
2748 static MonoClass *System_Reflection_ConstructorInfo;
2749 MonoGenericClass *gclass;
2750 MonoDynamicGenericClass *dgclass;
2752 MonoClass *refclass;
2756 MONO_ARCH_SAVE_REGS;
2758 if (!System_Reflection_ConstructorInfo)
2759 System_Reflection_ConstructorInfo = mono_class_from_name (
2760 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2762 gclass = type->type.type->data.generic_class;
2763 g_assert (gclass->is_dynamic);
2764 dgclass = (MonoDynamicGenericClass *) gclass;
2766 refclass = mono_class_from_mono_type (reflected_type->type);
2768 domain = mono_object_domain (type);
2769 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2771 for (i = 0; i < dgclass->count_ctors; i++)
2772 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2778 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2779 MonoReflectionType *reflected_type)
2781 MonoGenericClass *gclass;
2782 MonoDynamicGenericClass *dgclass;
2784 MonoClass *refclass;
2788 MONO_ARCH_SAVE_REGS;
2790 gclass = type->type.type->data.generic_class;
2791 g_assert (gclass->is_dynamic);
2792 dgclass = (MonoDynamicGenericClass *) gclass;
2794 refclass = mono_class_from_mono_type (reflected_type->type);
2796 domain = mono_object_domain (type);
2797 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2799 for (i = 0; i < dgclass->count_fields; i++)
2800 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2806 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2807 MonoReflectionType *reflected_type)
2809 static MonoClass *System_Reflection_PropertyInfo;
2810 MonoGenericClass *gclass;
2811 MonoDynamicGenericClass *dgclass;
2813 MonoClass *refclass;
2817 MONO_ARCH_SAVE_REGS;
2819 if (!System_Reflection_PropertyInfo)
2820 System_Reflection_PropertyInfo = mono_class_from_name (
2821 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2823 gclass = type->type.type->data.generic_class;
2824 g_assert (gclass->is_dynamic);
2825 dgclass = (MonoDynamicGenericClass *) gclass;
2827 refclass = mono_class_from_mono_type (reflected_type->type);
2829 domain = mono_object_domain (type);
2830 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2832 for (i = 0; i < dgclass->count_properties; i++)
2833 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2839 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2840 MonoReflectionType *reflected_type)
2842 static MonoClass *System_Reflection_EventInfo;
2843 MonoGenericClass *gclass;
2844 MonoDynamicGenericClass *dgclass;
2846 MonoClass *refclass;
2850 MONO_ARCH_SAVE_REGS;
2852 if (!System_Reflection_EventInfo)
2853 System_Reflection_EventInfo = mono_class_from_name (
2854 mono_defaults.corlib, "System.Reflection", "EventInfo");
2856 gclass = type->type.type->data.generic_class;
2857 g_assert (gclass->is_dynamic);
2858 dgclass = (MonoDynamicGenericClass *) gclass;
2860 refclass = mono_class_from_mono_type (reflected_type->type);
2862 domain = mono_object_domain (type);
2863 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2865 for (i = 0; i < dgclass->count_events; i++)
2866 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2871 static MonoReflectionType*
2872 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2873 MonoReflectionType *target)
2877 MonoReflectionType *res;
2879 MONO_ARCH_SAVE_REGS;
2881 gklass = mono_class_from_mono_type (type->type.type);
2882 res_type = mono_class_inflate_generic_type (mono_reflection_type_get_handle (target), mono_class_get_context (gklass));
2883 res = mono_type_get_object (mono_object_domain (type), res_type);
2884 mono_metadata_free_type (res_type);
2888 static MonoReflectionMethod *
2889 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2894 MONO_ARCH_SAVE_REGS;
2896 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2899 method = mono_type_get_generic_param_owner (type->type)->owner.method;
2901 klass = mono_class_from_mono_type (type->type);
2902 return mono_method_get_object (mono_object_domain (type), method, klass);
2905 static MonoReflectionDllImportAttribute*
2906 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2908 static MonoClass *DllImportAttributeClass = NULL;
2909 MonoDomain *domain = mono_domain_get ();
2910 MonoReflectionDllImportAttribute *attr;
2911 MonoImage *image = method->klass->image;
2912 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2913 MonoTableInfo *tables = image->tables;
2914 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2915 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2916 guint32 im_cols [MONO_IMPLMAP_SIZE];
2917 guint32 scope_token;
2918 const char *import = NULL;
2919 const char *scope = NULL;
2922 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2925 if (!DllImportAttributeClass) {
2926 DllImportAttributeClass =
2927 mono_class_from_name (mono_defaults.corlib,
2928 "System.Runtime.InteropServices", "DllImportAttribute");
2929 g_assert (DllImportAttributeClass);
2932 if (method->klass->image->dynamic) {
2933 MonoReflectionMethodAux *method_aux =
2934 g_hash_table_lookup (
2935 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2937 import = method_aux->dllentry;
2938 scope = method_aux->dll;
2942 if (piinfo->implmap_idx) {
2943 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2945 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2946 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2947 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2948 scope = mono_metadata_string_heap (image, scope_token);
2951 flags = piinfo->piflags;
2953 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2955 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2956 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2957 attr->call_conv = (flags & 0x700) >> 8;
2958 attr->charset = ((flags & 0x6) >> 1) + 1;
2959 if (attr->charset == 1)
2961 attr->exact_spelling = (flags & 0x1) != 0;
2962 attr->set_last_error = (flags & 0x40) != 0;
2963 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2964 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2965 attr->preserve_sig = FALSE;
2970 static MonoReflectionMethod *
2971 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2973 MonoMethodInflated *imethod;
2976 MONO_ARCH_SAVE_REGS;
2978 if (method->method->is_generic)
2981 if (!method->method->is_inflated)
2984 imethod = (MonoMethodInflated *) method->method;
2986 result = imethod->declaring;
2987 /* Not a generic method. */
2988 if (!result->is_generic)
2991 if (method->method->klass->image->dynamic) {
2992 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2993 MonoReflectionMethod *res;
2996 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2997 * the dynamic case as well ?
2999 mono_loader_lock ();
3000 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3001 mono_loader_unlock ();
3007 if (imethod->context.class_inst) {
3008 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3009 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
3012 return mono_method_get_object (mono_object_domain (method), result, NULL);
3016 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3018 MONO_ARCH_SAVE_REGS;
3020 return mono_method_signature (method->method)->generic_param_count != 0;
3024 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3026 MONO_ARCH_SAVE_REGS;
3028 return method->method->is_generic;
3032 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3037 MONO_ARCH_SAVE_REGS;
3039 domain = mono_object_domain (method);
3041 if (method->method->is_inflated) {
3042 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3045 count = inst->type_argc;
3046 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3048 for (i = 0; i < count; i++)
3049 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
3055 count = mono_method_signature (method->method)->generic_param_count;
3056 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3058 for (i = 0; i < count; i++) {
3059 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3060 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3061 MonoClass *pklass = mono_class_from_generic_parameter (
3062 param, method->method->klass->image, TRUE);
3063 mono_array_setref (res, i,
3064 mono_type_get_object (domain, &pklass->byval_arg));
3071 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3074 * Invoke from reflection is supposed to always be a virtual call (the API
3075 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3076 * greater flexibility.
3078 MonoMethod *m = method->method;
3082 MONO_ARCH_SAVE_REGS;
3086 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3087 mono_security_core_clr_ensure_reflection_access_method (m);
3089 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3091 if (!mono_object_isinst (this, m->klass)) {
3092 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
3095 m = mono_object_get_virtual_method (this, m);
3096 /* must pass the pointer to the value for valuetype methods */
3097 if (m->klass->valuetype)
3098 obj = mono_object_unbox (this);
3099 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3100 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3105 pcount = params? mono_array_length (params): 0;
3106 if (pcount != mono_method_signature (m)->param_count) {
3107 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3111 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3112 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
3116 if (m->klass->image->assembly->ref_only) {
3117 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
3121 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3123 mono_array_size_t *lengths;
3124 mono_array_size_t *lower_bounds;
3125 pcount = mono_array_length (params);
3126 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3127 for (i = 0; i < pcount; ++i)
3128 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3130 if (m->klass->rank == pcount) {
3131 /* Only lengths provided. */
3132 lower_bounds = NULL;
3134 g_assert (pcount == (m->klass->rank * 2));
3135 /* lower bounds are first. */
3136 lower_bounds = lengths;
3137 lengths += m->klass->rank;
3140 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3142 return mono_runtime_invoke_array (m, obj, params, NULL);
3146 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3148 MonoDomain *domain = mono_object_domain (method);
3149 MonoMethod *m = method->method;
3150 MonoMethodSignature *sig = mono_method_signature (m);
3151 MonoArray *out_args;
3153 int i, j, outarg_count = 0;
3155 MONO_ARCH_SAVE_REGS;
3157 if (m->klass == mono_defaults.object_class) {
3159 if (!strcmp (m->name, "FieldGetter")) {
3160 MonoClass *k = this->vtable->klass;
3164 /* If this is a proxy, then it must be a CBO */
3165 if (k == mono_defaults.transparent_proxy_class) {
3166 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3167 this = tp->rp->unwrapped_server;
3169 k = this->vtable->klass;
3172 name = mono_array_get (params, MonoString *, 1);
3173 str = mono_string_to_utf8 (name);
3176 MonoClassField* field = mono_class_get_field_from_name (k, str);
3178 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3179 if (field_klass->valuetype)
3180 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3182 result = *((gpointer *)((char *)this + field->offset));
3184 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3185 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3186 mono_array_setref (out_args, 0, result);
3194 g_assert_not_reached ();
3196 } else if (!strcmp (m->name, "FieldSetter")) {
3197 MonoClass *k = this->vtable->klass;
3203 /* If this is a proxy, then it must be a CBO */
3204 if (k == mono_defaults.transparent_proxy_class) {
3205 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3206 this = tp->rp->unwrapped_server;
3208 k = this->vtable->klass;
3211 name = mono_array_get (params, MonoString *, 1);
3212 str = mono_string_to_utf8 (name);
3215 MonoClassField* field = mono_class_get_field_from_name (k, str);
3217 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3218 MonoObject *val = mono_array_get (params, gpointer, 2);
3220 if (field_klass->valuetype) {
3221 size = mono_type_size (field->type, &align);
3223 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3225 memcpy ((char *)this + field->offset,
3226 ((char *)val) + sizeof (MonoObject), size);
3228 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3231 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3232 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3242 g_assert_not_reached ();
3247 for (i = 0; i < mono_array_length (params); i++) {
3248 if (sig->params [i]->byref)
3252 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3254 /* handle constructors only for objects already allocated */
3255 if (!strcmp (method->method->name, ".ctor"))
3258 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3259 g_assert (!method->method->klass->valuetype);
3260 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3262 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3263 if (sig->params [i]->byref) {
3265 arg = mono_array_get (params, gpointer, i);
3266 mono_array_setref (out_args, j, arg);
3271 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3277 read_enum_value (char *mem, int type)
3281 return *(guint8*)mem;
3283 return *(gint8*)mem;
3285 return *(guint16*)mem;
3287 return *(gint16*)mem;
3289 return *(guint32*)mem;
3291 return *(gint32*)mem;
3293 return *(guint64*)mem;
3295 return *(gint64*)mem;
3297 g_assert_not_reached ();
3303 write_enum_value (char *mem, int type, guint64 value)
3307 case MONO_TYPE_I1: {
3308 guint8 *p = (guint8*)mem;
3313 case MONO_TYPE_I2: {
3314 guint16 *p = (void*)mem;
3319 case MONO_TYPE_I4: {
3320 guint32 *p = (void*)mem;
3325 case MONO_TYPE_I8: {
3326 guint64 *p = (void*)mem;
3331 g_assert_not_reached ();
3337 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3340 MonoClass *enumc, *objc;
3344 MONO_ARCH_SAVE_REGS;
3346 MONO_CHECK_ARG_NULL (enumType);
3347 MONO_CHECK_ARG_NULL (value);
3349 domain = mono_object_domain (enumType);
3350 enumc = mono_class_from_mono_type (enumType->type);
3351 objc = value->vtable->klass;
3353 if (!enumc->enumtype)
3354 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3355 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3356 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3358 res = mono_object_new (domain, enumc);
3359 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3360 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3366 ves_icall_System_Enum_get_value (MonoObject *this)
3374 MONO_ARCH_SAVE_REGS;
3379 g_assert (this->vtable->klass->enumtype);
3381 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3382 res = mono_object_new (mono_object_domain (this), enumc);
3383 dst = (char *)res + sizeof (MonoObject);
3384 src = (char *)this + sizeof (MonoObject);
3385 size = mono_class_value_size (enumc, NULL);
3387 memcpy (dst, src, size);
3392 static MonoReflectionType *
3393 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3395 MONO_ARCH_SAVE_REGS;
3397 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3401 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3403 gpointer tdata = (char *)this + sizeof (MonoObject);
3404 gpointer odata = (char *)other + sizeof (MonoObject);
3405 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3406 g_assert (basetype);
3408 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3409 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3410 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3413 return me > other ? 1 : -1; \
3416 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3417 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3418 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3421 return me - other; \
3424 switch (basetype->type) {
3426 COMPARE_ENUM_VALUES (guint8);
3428 COMPARE_ENUM_VALUES (gint8);
3429 case MONO_TYPE_CHAR:
3431 COMPARE_ENUM_VALUES_RANGE (guint16);
3433 COMPARE_ENUM_VALUES (gint16);
3435 COMPARE_ENUM_VALUES (guint32);
3437 COMPARE_ENUM_VALUES (gint32);
3439 COMPARE_ENUM_VALUES (guint64);
3441 COMPARE_ENUM_VALUES (gint64);
3443 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3445 #undef COMPARE_ENUM_VALUES_RANGE
3446 #undef COMPARE_ENUM_VALUES
3451 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3453 gpointer data = (char *)this + sizeof (MonoObject);
3454 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3455 g_assert (basetype);
3457 switch (basetype->type) {
3459 return *((gint8*)data);
3461 return *((guint8*)data);
3462 case MONO_TYPE_CHAR:
3464 return *((guint16*)data);
3467 return *((gint16*)data);
3469 return *((guint32*)data);
3471 return *((gint32*)data);
3473 case MONO_TYPE_I8: {
3474 gint64 value = *((gint64*)data);
3475 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3478 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3484 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3486 MonoDomain *domain = mono_object_domain (type);
3487 MonoClass *enumc = mono_class_from_mono_type (type->type);
3488 guint j = 0, nvalues, crow;
3490 MonoClassField *field;
3492 MONO_ARCH_SAVE_REGS;
3494 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3495 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3496 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3497 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3501 while ((field = mono_class_get_fields (enumc, &iter))) {
3504 MonoTypeEnum def_type;
3506 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3508 if (mono_field_is_deleted (field))
3510 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3512 p = mono_class_get_field_default_value (field, &def_type);
3513 len = mono_metadata_decode_blob_size (p, &p);
3514 switch (mono_class_enum_basetype (enumc)->type) {
3517 mono_array_set (info->values, gchar, j, *p);
3519 case MONO_TYPE_CHAR:
3522 mono_array_set (info->values, gint16, j, read16 (p));
3526 mono_array_set (info->values, gint32, j, read32 (p));
3530 mono_array_set (info->values, gint64, j, read64 (p));
3533 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3540 BFLAGS_IgnoreCase = 1,
3541 BFLAGS_DeclaredOnly = 2,
3542 BFLAGS_Instance = 4,
3544 BFLAGS_Public = 0x10,
3545 BFLAGS_NonPublic = 0x20,
3546 BFLAGS_FlattenHierarchy = 0x40,
3547 BFLAGS_InvokeMethod = 0x100,
3548 BFLAGS_CreateInstance = 0x200,
3549 BFLAGS_GetField = 0x400,
3550 BFLAGS_SetField = 0x800,
3551 BFLAGS_GetProperty = 0x1000,
3552 BFLAGS_SetProperty = 0x2000,
3553 BFLAGS_ExactBinding = 0x10000,
3554 BFLAGS_SuppressChangeType = 0x20000,
3555 BFLAGS_OptionalParamBinding = 0x40000
3558 static MonoReflectionField *
3559 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3562 MonoClass *startklass, *klass;
3564 MonoClassField *field;
3567 int (*compare_func) (const char *s1, const char *s2) = NULL;
3568 domain = ((MonoObject *)type)->vtable->domain;
3569 klass = startklass = mono_class_from_mono_type (type->type);
3571 MONO_ARCH_SAVE_REGS;
3574 mono_raise_exception (mono_get_exception_argument_null ("name"));
3575 if (type->type->byref)
3578 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3581 if (klass->exception_type != MONO_EXCEPTION_NONE)
3582 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3585 while ((field = mono_class_get_fields (klass, &iter))) {
3588 if (field->type == NULL)
3590 if (mono_field_is_deleted (field))
3592 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3593 if (bflags & BFLAGS_Public)
3595 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3596 if (bflags & BFLAGS_NonPublic) {
3603 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3604 if (bflags & BFLAGS_Static)
3605 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3608 if (bflags & BFLAGS_Instance)
3615 utf8_name = mono_string_to_utf8 (name);
3617 if (compare_func (mono_field_get_name (field), utf8_name)) {
3623 return mono_field_get_object (domain, klass, field);
3625 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3632 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3635 MonoClass *startklass, *klass, *refklass;
3640 MonoClassField *field;
3641 MonoPtrArray tmp_array;
3643 MONO_ARCH_SAVE_REGS;
3645 domain = ((MonoObject *)type)->vtable->domain;
3646 if (type->type->byref)
3647 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3648 klass = startklass = mono_class_from_mono_type (type->type);
3649 refklass = mono_class_from_mono_type (reftype->type);
3651 mono_ptr_array_init (tmp_array, 2);
3654 if (klass->exception_type != MONO_EXCEPTION_NONE)
3655 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3658 while ((field = mono_class_get_fields (klass, &iter))) {
3660 if (mono_field_is_deleted (field))
3662 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3663 if (bflags & BFLAGS_Public)
3665 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3666 if (bflags & BFLAGS_NonPublic) {
3673 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3674 if (bflags & BFLAGS_Static)
3675 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3678 if (bflags & BFLAGS_Instance)
3684 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3685 mono_ptr_array_append (tmp_array, member);
3687 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3690 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3692 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3693 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3695 mono_ptr_array_destroy (tmp_array);
3701 method_nonpublic (MonoMethod* method, gboolean start_klass)
3703 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3704 case METHOD_ATTRIBUTE_ASSEM:
3705 return (start_klass || mono_defaults.generic_ilist_class);
3706 case METHOD_ATTRIBUTE_PRIVATE:
3708 case METHOD_ATTRIBUTE_PUBLIC:
3716 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3718 static MonoClass *MethodInfo_array;
3720 MonoClass *startklass, *klass, *refklass;
3725 int i, len, match, nslots;
3726 /*FIXME, use MonoBitSet*/
3727 guint32 method_slots_default [8];
3728 guint32 *method_slots;
3729 gchar *mname = NULL;
3730 int (*compare_func) (const char *s1, const char *s2) = NULL;
3731 MonoVTable *array_vtable;
3732 MonoPtrArray tmp_array;
3734 MONO_ARCH_SAVE_REGS;
3736 mono_ptr_array_init (tmp_array, 4);
3738 if (!MethodInfo_array) {
3739 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3740 mono_memory_barrier ();
3741 MethodInfo_array = klass;
3744 domain = ((MonoObject *)type)->vtable->domain;
3745 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3746 if (type->type->byref)
3747 return mono_array_new_specific (array_vtable, 0);
3748 klass = startklass = mono_class_from_mono_type (type->type);
3749 refklass = mono_class_from_mono_type (reftype->type);
3752 mname = mono_string_to_utf8 (name);
3753 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3756 /* An optimization for calls made from Delegate:CreateDelegate () */
3757 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3758 method = mono_get_delegate_invoke (klass);
3760 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3762 res = mono_array_new_specific (array_vtable, 1);
3763 mono_array_setref (res, 0, member);
3768 mono_class_setup_vtable (klass);
3770 if (is_generic_parameter (type->type))
3771 nslots = klass->parent->vtable_size;
3773 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3774 if (nslots >= sizeof (method_slots_default) * 8) {
3775 method_slots = g_new0 (guint32, nslots / 32 + 1);
3777 method_slots = method_slots_default;
3778 memset (method_slots, 0, sizeof (method_slots_default));
3781 mono_class_setup_vtable (klass);
3782 if (klass->exception_type != MONO_EXCEPTION_NONE)
3783 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3786 while ((method = mono_class_get_methods (klass, &iter))) {
3788 if (method->slot != -1) {
3789 g_assert (method->slot < nslots);
3790 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3792 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3795 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3797 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3798 if (bflags & BFLAGS_Public)
3800 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3806 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3807 if (bflags & BFLAGS_Static)
3808 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3811 if (bflags & BFLAGS_Instance)
3819 if (compare_func (mname, method->name))
3825 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3827 mono_ptr_array_append (tmp_array, member);
3829 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3833 if (method_slots != method_slots_default)
3834 g_free (method_slots);
3836 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3838 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3839 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3841 mono_ptr_array_destroy (tmp_array);
3846 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3849 static MonoClass *System_Reflection_ConstructorInfo;
3850 MonoClass *startklass, *klass, *refklass;
3855 gpointer iter = NULL;
3856 MonoPtrArray tmp_array;
3858 MONO_ARCH_SAVE_REGS;
3860 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3862 domain = ((MonoObject *)type)->vtable->domain;
3863 if (type->type->byref)
3864 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3865 klass = startklass = mono_class_from_mono_type (type->type);
3866 refklass = mono_class_from_mono_type (reftype->type);
3868 if (klass->exception_type != MONO_EXCEPTION_NONE)
3869 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3871 if (!System_Reflection_ConstructorInfo)
3872 System_Reflection_ConstructorInfo = mono_class_from_name (
3873 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3876 while ((method = mono_class_get_methods (klass, &iter))) {
3878 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3880 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3881 if (bflags & BFLAGS_Public)
3884 if (bflags & BFLAGS_NonPublic)
3890 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3891 if (bflags & BFLAGS_Static)
3892 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3895 if (bflags & BFLAGS_Instance)
3901 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3903 mono_ptr_array_append (tmp_array, member);
3906 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3908 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3909 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3911 mono_ptr_array_destroy (tmp_array);
3917 property_hash (gconstpointer data)
3919 MonoProperty *prop = (MonoProperty*)data;
3921 return g_str_hash (prop->name);
3925 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3927 // Properties are hide-by-name-and-signature
3928 if (!g_str_equal (prop1->name, prop2->name))
3931 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3933 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3939 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3944 return method_nonpublic (accessor, start_klass);
3948 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3951 static MonoClass *System_Reflection_PropertyInfo;
3952 MonoClass *startklass, *klass;
3958 gchar *propname = NULL;
3959 int (*compare_func) (const char *s1, const char *s2) = NULL;
3961 GHashTable *properties;
3962 MonoPtrArray tmp_array;
3964 MONO_ARCH_SAVE_REGS;
3966 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3968 if (!System_Reflection_PropertyInfo)
3969 System_Reflection_PropertyInfo = mono_class_from_name (
3970 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3972 domain = ((MonoObject *)type)->vtable->domain;
3973 if (type->type->byref)
3974 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3975 klass = startklass = mono_class_from_mono_type (type->type);
3977 propname = mono_string_to_utf8 (name);
3978 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3981 mono_class_setup_vtable (klass);
3983 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3985 mono_class_setup_vtable (klass);
3986 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3987 g_hash_table_destroy (properties);
3990 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3994 while ((prop = mono_class_get_properties (klass, &iter))) {
4000 flags = method->flags;
4003 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4004 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4005 if (bflags & BFLAGS_Public)
4007 } else if (bflags & BFLAGS_NonPublic) {
4008 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4009 property_accessor_nonpublic(prop->set, startklass == klass)) {
4016 if (flags & METHOD_ATTRIBUTE_STATIC) {
4017 if (bflags & BFLAGS_Static)
4018 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4021 if (bflags & BFLAGS_Instance)
4030 if (compare_func (propname, prop->name))
4034 if (g_hash_table_lookup (properties, prop))
4037 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4039 g_hash_table_insert (properties, prop, prop);
4041 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4044 g_hash_table_destroy (properties);
4047 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4048 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4049 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4051 mono_ptr_array_destroy (tmp_array);
4056 static MonoReflectionEvent *
4057 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4060 MonoClass *klass, *startklass;
4066 MONO_ARCH_SAVE_REGS;
4068 event_name = mono_string_to_utf8 (name);
4069 if (type->type->byref)
4071 klass = startklass = mono_class_from_mono_type (type->type);
4072 domain = mono_object_domain (type);
4075 if (klass->exception_type != MONO_EXCEPTION_NONE)
4076 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4079 while ((event = mono_class_get_events (klass, &iter))) {
4080 if (strcmp (event->name, event_name))
4083 method = event->add;
4085 method = event->remove;
4087 method = event->raise;
4089 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4090 if (!(bflags & BFLAGS_Public))
4093 if (!(bflags & BFLAGS_NonPublic))
4095 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4099 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4100 if (!(bflags & BFLAGS_Static))
4102 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4105 if (!(bflags & BFLAGS_Instance))
4109 if (!(bflags & BFLAGS_NonPublic))
4112 g_free (event_name);
4113 return mono_event_get_object (domain, startklass, event);
4116 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4119 g_free (event_name);
4124 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4127 static MonoClass *System_Reflection_EventInfo;
4128 MonoClass *startklass, *klass;
4135 MonoPtrArray tmp_array;
4137 MONO_ARCH_SAVE_REGS;
4139 mono_ptr_array_init (tmp_array, 4);
4141 if (!System_Reflection_EventInfo)
4142 System_Reflection_EventInfo = mono_class_from_name (
4143 mono_defaults.corlib, "System.Reflection", "EventInfo");
4145 domain = mono_object_domain (type);
4146 if (type->type->byref)
4147 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4148 klass = startklass = mono_class_from_mono_type (type->type);
4151 if (klass->exception_type != MONO_EXCEPTION_NONE)
4152 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4155 while ((event = mono_class_get_events (klass, &iter))) {
4157 method = event->add;
4159 method = event->remove;
4161 method = event->raise;
4163 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4164 if (bflags & BFLAGS_Public)
4166 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4167 if (bflags & BFLAGS_NonPublic)
4172 if (bflags & BFLAGS_NonPublic)
4178 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4179 if (bflags & BFLAGS_Static)
4180 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4183 if (bflags & BFLAGS_Instance)
4188 if (bflags & BFLAGS_Instance)
4192 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4194 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4197 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4199 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4200 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4202 mono_ptr_array_destroy (tmp_array);
4207 static MonoReflectionType *
4208 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4216 MONO_ARCH_SAVE_REGS;
4219 mono_raise_exception (mono_get_exception_argument_null ("name"));
4221 domain = ((MonoObject *)type)->vtable->domain;
4222 if (type->type->byref)
4224 klass = mono_class_from_mono_type (type->type);
4225 str = mono_string_to_utf8 (name);
4228 if (klass->exception_type != MONO_EXCEPTION_NONE)
4229 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4232 * If a nested type is generic, return its generic type definition.
4233 * Note that this means that the return value is essentially a
4234 * nested type of the generic type definition of @klass.
4236 * A note in MSDN claims that a generic type definition can have
4237 * nested types that aren't generic. In any case, the container of that
4238 * nested type would be the generic type definition.
4240 if (klass->generic_class)
4241 klass = klass->generic_class->container_class;
4244 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4246 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4247 if (bflags & BFLAGS_Public)
4250 if (bflags & BFLAGS_NonPublic)
4255 if (strcmp (nested->name, str) == 0){
4257 return mono_type_get_object (domain, &nested->byval_arg);
4260 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4267 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4276 MonoPtrArray tmp_array;
4278 MONO_ARCH_SAVE_REGS;
4280 domain = ((MonoObject *)type)->vtable->domain;
4281 if (type->type->byref)
4282 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4283 klass = mono_class_from_mono_type (type->type);
4284 if (klass->exception_type != MONO_EXCEPTION_NONE)
4285 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4288 * If a nested type is generic, return its generic type definition.
4289 * Note that this means that the return value is essentially the set
4290 * of nested types of the generic type definition of @klass.
4292 * A note in MSDN claims that a generic type definition can have
4293 * nested types that aren't generic. In any case, the container of that
4294 * nested type would be the generic type definition.
4296 if (klass->generic_class)
4297 klass = klass->generic_class->container_class;
4299 mono_ptr_array_init (tmp_array, 1);
4301 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4303 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4304 if (bflags & BFLAGS_Public)
4307 if (bflags & BFLAGS_NonPublic)
4312 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4313 mono_ptr_array_append (tmp_array, member);
4316 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4318 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4319 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4321 mono_ptr_array_destroy (tmp_array);
4326 static MonoReflectionType*
4327 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4330 MonoType *type = NULL;
4331 MonoTypeNameParse info;
4332 gboolean type_resolve;
4334 MONO_ARCH_SAVE_REGS;
4336 /* On MS.NET, this does not fire a TypeResolve event */
4337 type_resolve = TRUE;
4338 str = mono_string_to_utf8 (name);
4339 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4340 if (!mono_reflection_parse_type (str, &info)) {
4342 mono_reflection_free_type_info (&info);
4343 if (throwOnError) /* uhm: this is a parse error, though... */
4344 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4345 /*g_print ("failed parse\n");*/
4349 if (info.assembly.name) {
4351 mono_reflection_free_type_info (&info);
4353 /* 1.0 and 2.0 throw different exceptions */
4354 if (mono_defaults.generic_ilist_class)
4355 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4357 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4362 if (module != NULL) {
4364 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4369 if (assembly->assembly->dynamic) {
4370 /* Enumerate all modules */
4371 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4375 if (abuilder->modules) {
4376 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4377 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4378 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4384 if (!type && abuilder->loaded_modules) {
4385 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4386 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4387 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4394 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4396 mono_reflection_free_type_info (&info);
4398 MonoException *e = NULL;
4401 e = mono_get_exception_type_load (name, NULL);
4403 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4404 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4406 mono_loader_clear_error ();
4409 mono_raise_exception (e);
4414 if (type->type == MONO_TYPE_CLASS) {
4415 MonoClass *klass = mono_type_get_class (type);
4417 if (mono_is_security_manager_active () && !klass->exception_type)
4418 /* Some security problems are detected during generic vtable construction */
4419 mono_class_setup_vtable (klass);
4420 /* need to report exceptions ? */
4421 if (throwOnError && klass->exception_type) {
4422 /* report SecurityException (or others) that occured when loading the assembly */
4423 MonoException *exc = mono_class_get_exception_for_failure (klass);
4424 mono_loader_clear_error ();
4425 mono_raise_exception (exc);
4426 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4431 /* g_print ("got it\n"); */
4432 return mono_type_get_object (mono_object_domain (assembly), type);
4436 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4439 gchar *shadow_ini_file;
4442 /* Check for shadow-copied assembly */
4443 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4444 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4446 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4447 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4453 g_free (shadow_ini_file);
4454 if (content != NULL) {
4457 *filename = content;
4465 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4467 MonoDomain *domain = mono_object_domain (assembly);
4468 MonoAssembly *mass = assembly->assembly;
4469 MonoString *res = NULL;
4474 MONO_ARCH_SAVE_REGS;
4476 if (g_path_is_absolute (mass->image->name)) {
4477 absolute = g_strdup (mass->image->name);
4478 dirname = g_path_get_dirname (absolute);
4480 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4481 dirname = g_strdup (mass->basedir);
4484 replace_shadow_path (domain, dirname, &absolute);
4489 for (i = strlen (absolute) - 1; i >= 0; i--)
4490 if (absolute [i] == '\\')
4495 uri = g_filename_to_uri (absolute, NULL, NULL);
4497 const char *prepend = "file://";
4499 if (*absolute == '/' && *(absolute + 1) == '/') {
4502 prepend = "file:///";
4505 uri = g_strconcat (prepend, absolute, NULL);
4509 res = mono_string_new (domain, uri);
4517 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4519 MonoAssembly *mass = assembly->assembly;
4521 MONO_ARCH_SAVE_REGS;
4523 return mass->in_gac;
4526 static MonoReflectionAssembly*
4527 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4531 MonoImageOpenStatus status;
4533 MONO_ARCH_SAVE_REGS;
4535 name = mono_string_to_utf8 (mname);
4536 res = mono_assembly_load_with_partial_name (name, &status);
4542 return mono_assembly_get_object (mono_domain_get (), res);
4546 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4548 MonoDomain *domain = mono_object_domain (assembly);
4551 MONO_ARCH_SAVE_REGS;
4553 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4559 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4561 MONO_ARCH_SAVE_REGS;
4563 return assembly->assembly->ref_only;
4567 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4569 MonoDomain *domain = mono_object_domain (assembly);
4571 MONO_ARCH_SAVE_REGS;
4573 return mono_string_new (domain, assembly->assembly->image->version);
4576 static MonoReflectionMethod*
4577 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4579 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4581 MONO_ARCH_SAVE_REGS;
4585 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4588 static MonoReflectionModule*
4589 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4591 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4595 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4597 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4598 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4602 MONO_ARCH_SAVE_REGS;
4604 for (i = 0; i < table->rows; ++i) {
4605 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4606 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4612 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4614 static MonoClass *System_Version = NULL;
4615 static MonoMethod *create_version = NULL;
4619 if (!System_Version) {
4620 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4621 g_assert (System_Version);
4624 if (!create_version) {
4625 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4626 create_version = mono_method_desc_search_in_class (desc, System_Version);
4627 g_assert (create_version);
4628 mono_method_desc_free (desc);
4634 args [3] = &revision;
4635 result = mono_object_new (domain, System_Version);
4636 mono_runtime_invoke (create_version, result, args, NULL);
4642 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4644 static MonoClass *System_Reflection_AssemblyName;
4646 MonoDomain *domain = mono_object_domain (assembly);
4648 static MonoMethod *create_culture = NULL;
4649 MonoImage *image = assembly->assembly->image;
4652 MONO_ARCH_SAVE_REGS;
4654 if (!System_Reflection_AssemblyName)
4655 System_Reflection_AssemblyName = mono_class_from_name (
4656 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4658 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4661 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4663 if (count > 0 && !create_culture) {
4664 MonoMethodDesc *desc = mono_method_desc_new (
4665 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4666 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4667 g_assert (create_culture);
4668 mono_method_desc_free (desc);
4671 for (i = 0; i < count; i++) {
4672 MonoReflectionAssemblyName *aname;
4673 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4675 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4677 aname = (MonoReflectionAssemblyName *) mono_object_new (
4678 domain, System_Reflection_AssemblyName);
4680 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4682 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4683 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4684 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4685 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4686 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4687 aname->versioncompat = 1; /* SameMachine (default) */
4688 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4689 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4691 if (create_culture) {
4693 MonoBoolean assembly_ref = 1;
4694 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4695 args [1] = &assembly_ref;
4696 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4699 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4700 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4701 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4703 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4704 /* public key token isn't copied - the class library will
4705 automatically generate it from the public key if required */
4706 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4707 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4709 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4710 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4713 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4716 /* note: this function doesn't return the codebase on purpose (i.e. it can
4717 be used under partial trust as path information isn't present). */
4719 mono_array_setref (result, i, aname);
4730 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4732 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4734 mono_array_setref (info->res, info->idx, name);
4739 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4741 MonoImage *img = assembly->assembly->image;
4746 MONO_ARCH_SAVE_REGS;
4748 mono_image_lock (img);
4749 mono_image_init_name_cache (img);
4752 len = g_hash_table_size (img->name_cache);
4753 mono_image_unlock (img);
4755 /*we can't create objects holding the image lock */
4756 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4758 mono_image_lock (img);
4759 /*len might have changed, create a new array*/
4760 if (len != g_hash_table_size (img->name_cache))
4765 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4766 mono_image_unlock (img);
4771 /* move this in some file in mono/util/ */
4773 g_concat_dir_and_file (const char *dir, const char *file)
4775 g_return_val_if_fail (dir != NULL, NULL);
4776 g_return_val_if_fail (file != NULL, NULL);
4779 * If the directory name doesn't have a / on the end, we need
4780 * to add one so we get a proper path to the file
4782 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4783 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4785 return g_strconcat (dir, file, NULL);
4789 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4791 char *n = mono_string_to_utf8 (name);
4792 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4794 guint32 cols [MONO_MANIFEST_SIZE];
4795 guint32 impl, file_idx;
4799 MONO_ARCH_SAVE_REGS;
4801 for (i = 0; i < table->rows; ++i) {
4802 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4803 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4804 if (strcmp (val, n) == 0)
4808 if (i == table->rows)
4811 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4814 * this code should only be called after obtaining the
4815 * ResourceInfo and handling the other cases.
4817 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4818 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4820 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4825 module = assembly->assembly->image;
4827 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4829 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4833 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4835 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4837 guint32 cols [MONO_MANIFEST_SIZE];
4838 guint32 file_cols [MONO_FILE_SIZE];
4842 MONO_ARCH_SAVE_REGS;
4844 n = mono_string_to_utf8 (name);
4845 for (i = 0; i < table->rows; ++i) {
4846 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4847 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4848 if (strcmp (val, n) == 0)
4852 if (i == table->rows)
4855 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4856 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4859 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4860 case MONO_IMPLEMENTATION_FILE:
4861 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4862 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4863 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4864 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4865 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4866 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4869 info->location = RESOURCE_LOCATION_EMBEDDED;
4872 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4873 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4874 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4875 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4876 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4877 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4879 mono_raise_exception (ex);
4881 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4883 /* Obtain info recursively */
4884 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4885 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4888 case MONO_IMPLEMENTATION_EXP_TYPE:
4889 g_assert_not_reached ();
4898 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4900 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4901 MonoArray *result = NULL;
4906 MONO_ARCH_SAVE_REGS;
4908 /* check hash if needed */
4910 n = mono_string_to_utf8 (name);
4911 for (i = 0; i < table->rows; ++i) {
4912 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4913 if (strcmp (val, n) == 0) {
4916 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4917 fn = mono_string_new (mono_object_domain (assembly), n);
4919 return (MonoObject*)fn;
4927 for (i = 0; i < table->rows; ++i) {
4928 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4932 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4935 for (i = 0; i < table->rows; ++i) {
4936 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4937 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4938 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4939 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4944 return (MonoObject*)result;
4948 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4950 MonoDomain *domain = mono_domain_get();
4953 int i, j, file_count = 0;
4954 MonoImage **modules;
4955 guint32 module_count, real_module_count;
4956 MonoTableInfo *table;
4957 guint32 cols [MONO_FILE_SIZE];
4958 MonoImage *image = assembly->assembly->image;
4960 g_assert (image != NULL);
4961 g_assert (!assembly->assembly->dynamic);
4963 table = &image->tables [MONO_TABLE_FILE];
4964 file_count = table->rows;
4966 modules = image->modules;
4967 module_count = image->module_count;
4969 real_module_count = 0;
4970 for (i = 0; i < module_count; ++i)
4972 real_module_count ++;
4974 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4975 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4977 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4979 for (i = 0; i < module_count; ++i)
4981 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4985 for (i = 0; i < file_count; ++i, ++j) {
4986 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4987 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4988 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4990 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4992 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4993 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4995 mono_array_setref (res, j, mono_module_get_object (domain, m));
5002 static MonoReflectionMethod*
5003 ves_icall_GetCurrentMethod (void)
5005 MonoMethod *m = mono_method_get_last_managed ();
5007 MONO_ARCH_SAVE_REGS;
5009 return mono_method_get_object (mono_domain_get (), m, NULL);
5014 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5017 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5018 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5019 //method is inflated, we should inflate it on the other class
5020 MonoGenericContext ctx;
5021 ctx.method_inst = inflated->context.method_inst;
5022 ctx.class_inst = inflated->context.class_inst;
5023 if (klass->generic_class)
5024 ctx.class_inst = klass->generic_class->context.class_inst;
5025 else if (klass->generic_container)
5026 ctx.class_inst = klass->generic_container->context.class_inst;
5027 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
5030 mono_class_setup_methods (method->klass);
5031 for (i = 0; i < method->klass->method.count; ++i) {
5032 if (method->klass->methods [i] == method) {
5037 mono_class_setup_methods (klass);
5038 g_assert (offset >= 0 && offset < klass->method.count);
5039 return klass->methods [offset];
5042 static MonoReflectionMethod*
5043 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5047 klass = mono_class_from_mono_type (type);
5048 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5050 if (method->klass != klass)
5051 method = mono_method_get_equivalent_method (method, klass);
5053 klass = method->klass;
5054 return mono_method_get_object (mono_domain_get (), method, klass);
5057 static MonoReflectionMethod*
5058 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5060 return mono_method_get_object (mono_domain_get (), method, NULL);
5063 static MonoReflectionMethodBody*
5064 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5066 return mono_method_body_get_object (mono_domain_get (), method);
5069 static MonoReflectionAssembly*
5070 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5072 MonoMethod *dest = NULL;
5074 MONO_ARCH_SAVE_REGS;
5076 mono_stack_walk_no_il (get_executing, &dest);
5077 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5081 static MonoReflectionAssembly*
5082 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5084 MonoDomain* domain = mono_domain_get ();
5086 MONO_ARCH_SAVE_REGS;
5088 if (!domain->entry_assembly)
5091 return mono_assembly_get_object (domain, domain->entry_assembly);
5094 static MonoReflectionAssembly*
5095 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5100 MONO_ARCH_SAVE_REGS;
5103 mono_stack_walk_no_il (get_executing, &dest);
5105 mono_stack_walk_no_il (get_caller, &dest);
5108 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5112 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5113 gboolean assembly_qualified)
5115 MonoDomain *domain = mono_object_domain (object);
5116 MonoTypeNameFormat format;
5120 MONO_ARCH_SAVE_REGS;
5122 format = assembly_qualified ?
5123 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5124 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5126 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5128 name = mono_type_get_name_full (object->type, format);
5132 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5137 res = mono_string_new (domain, name);
5144 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5146 static MonoMethod *create_culture = NULL;
5149 const char *pkey_ptr;
5151 MonoBoolean assembly_ref = 0;
5153 MONO_ARCH_SAVE_REGS;
5155 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5156 aname->major = name->major;
5157 aname->minor = name->minor;
5158 aname->build = name->build;
5159 aname->flags = name->flags;
5160 aname->revision = name->revision;
5161 aname->hashalg = name->hash_alg;
5162 aname->versioncompat = 1; /* SameMachine (default) */
5164 if (by_default_version)
5165 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5168 if (absolute != NULL && *absolute != '\0') {
5169 const gchar *prepend = "file://";
5172 codebase = g_strdup (absolute);
5177 for (i = strlen (codebase) - 1; i >= 0; i--)
5178 if (codebase [i] == '\\')
5181 if (*codebase == '/' && *(codebase + 1) == '/') {
5184 prepend = "file:///";
5188 result = g_strconcat (prepend, codebase, NULL);
5194 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5198 if (!create_culture) {
5199 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5200 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5201 g_assert (create_culture);
5202 mono_method_desc_free (desc);
5205 if (name->culture) {
5206 args [0] = mono_string_new (domain, name->culture);
5207 args [1] = &assembly_ref;
5208 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5211 if (name->public_key) {
5212 pkey_ptr = (char*)name->public_key;
5213 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5215 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5216 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5217 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5218 } else if (default_publickey) {
5219 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5220 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5223 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5224 if (name->public_key_token [0]) {
5228 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5229 p = mono_array_addr (aname->keyToken, char, 0);
5231 for (i = 0, j = 0; i < 8; i++) {
5232 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5233 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5236 } else if (default_token) {
5237 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5242 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5244 MonoDomain *domain = mono_object_domain (assembly);
5245 MonoAssembly *mass = assembly->assembly;
5249 name = g_strdup_printf (
5250 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5252 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5253 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5254 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5255 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5257 res = mono_string_new (domain, name);
5264 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5267 MonoAssembly *mass = assembly->assembly;
5269 MONO_ARCH_SAVE_REGS;
5271 if (g_path_is_absolute (mass->image->name)) {
5272 fill_reflection_assembly_name (mono_object_domain (assembly),
5273 aname, &mass->aname, mass->image->name, TRUE,
5274 TRUE, mono_framework_version () >= 2);
5277 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5279 fill_reflection_assembly_name (mono_object_domain (assembly),
5280 aname, &mass->aname, absolute, TRUE, TRUE,
5281 mono_framework_version () >= 2);
5287 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5290 MonoImageOpenStatus status = MONO_IMAGE_OK;
5293 MonoAssemblyName name;
5296 MONO_ARCH_SAVE_REGS;
5298 filename = mono_string_to_utf8 (fname);
5300 dirname = g_path_get_dirname (filename);
5301 replace_shadow_path (mono_domain_get (), dirname, &filename);
5304 image = mono_image_open (filename, &status);
5310 if (status == MONO_IMAGE_IMAGE_INVALID)
5311 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5313 exc = mono_get_exception_file_not_found2 (NULL, fname);
5314 mono_raise_exception (exc);
5317 res = mono_assembly_fill_assembly_name (image, &name);
5319 mono_image_close (image);
5321 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5324 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5325 TRUE, mono_framework_version () == 1,
5326 mono_framework_version () >= 2);
5329 mono_image_close (image);
5333 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5334 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5336 MonoBoolean result = FALSE;
5337 MonoDeclSecurityEntry entry;
5339 /* SecurityAction.RequestMinimum */
5340 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5341 *minimum = entry.blob;
5342 *minLength = entry.size;
5345 /* SecurityAction.RequestOptional */
5346 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5347 *optional = entry.blob;
5348 *optLength = entry.size;
5351 /* SecurityAction.RequestRefuse */
5352 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5353 *refused = entry.blob;
5354 *refLength = entry.size;
5362 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5366 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5368 guint32 attrs, visibility;
5370 /* we start the count from 1 because we skip the special type <Module> */
5373 for (i = 1; i < tdef->rows; ++i) {
5374 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5375 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5376 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5380 count = tdef->rows - 1;
5382 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5383 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5385 for (i = 1; i < tdef->rows; ++i) {
5386 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5387 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5388 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5389 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5391 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5393 MonoLoaderError *error;
5396 error = mono_loader_get_last_error ();
5397 g_assert (error != NULL);
5399 ex = mono_loader_error_prepare_exception (error);
5400 mono_array_setref (*exceptions, count, ex);
5402 if (mono_loader_get_last_error ())
5403 mono_loader_clear_error ();
5412 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5414 MonoArray *res = NULL;
5415 MonoArray *exceptions = NULL;
5416 MonoImage *image = NULL;
5417 MonoTableInfo *table = NULL;
5420 int i, len, ex_count;
5422 MONO_ARCH_SAVE_REGS;
5424 domain = mono_object_domain (assembly);
5426 g_assert (!assembly->assembly->dynamic);
5427 image = assembly->assembly->image;
5428 table = &image->tables [MONO_TABLE_FILE];
5429 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5431 /* Append data from all modules in the assembly */
5432 for (i = 0; i < table->rows; ++i) {
5433 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5434 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5437 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5438 /* Append the new types to the end of the array */
5439 if (mono_array_length (res2) > 0) {
5441 MonoArray *res3, *ex3;
5443 len1 = mono_array_length (res);
5444 len2 = mono_array_length (res2);
5446 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5447 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5448 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5451 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5452 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5453 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5460 /* the ReflectionTypeLoadException must have all the types (Types property),
5461 * NULL replacing types which throws an exception. The LoaderException must
5462 * contain all exceptions for NULL items.
5465 len = mono_array_length (res);
5468 for (i = 0; i < len; i++) {
5469 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5473 klass = mono_type_get_class (t->type);
5474 if ((klass != NULL) && klass->exception_type) {
5475 /* keep the class in the list */
5476 list = g_list_append (list, klass);
5477 /* and replace Type with NULL */
5478 mono_array_setref (res, i, NULL);
5485 if (list || ex_count) {
5487 MonoException *exc = NULL;
5488 MonoArray *exl = NULL;
5489 int j, length = g_list_length (list) + ex_count;
5491 mono_loader_clear_error ();
5493 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5494 /* Types for which mono_class_get () succeeded */
5495 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5496 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5497 mono_array_setref (exl, i, exc);
5499 /* Types for which it don't */
5500 for (j = 0; j < mono_array_length (exceptions); ++j) {
5501 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5503 g_assert (i < length);
5504 mono_array_setref (exl, i, exc);
5511 exc = mono_get_exception_reflection_type_load (res, exl);
5512 mono_loader_clear_error ();
5513 mono_raise_exception (exc);
5520 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5522 MonoAssemblyName aname;
5523 MonoDomain *domain = mono_object_domain (name);
5525 gboolean is_version_defined;
5526 gboolean is_token_defined;
5528 aname.public_key = NULL;
5529 val = mono_string_to_utf8 (assname);
5530 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5531 g_free ((guint8*) aname.public_key);
5536 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5537 FALSE, is_token_defined);
5539 mono_assembly_name_free (&aname);
5540 g_free ((guint8*) aname.public_key);
5546 static MonoReflectionType*
5547 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5549 MonoDomain *domain = mono_object_domain (module);
5552 MONO_ARCH_SAVE_REGS;
5554 g_assert (module->image);
5556 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5557 /* These images do not have a global type */
5560 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5561 return mono_type_get_object (domain, &klass->byval_arg);
5565 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5567 /*if (module->image)
5568 mono_image_close (module->image);*/
5572 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5574 MonoDomain *domain = mono_object_domain (module);
5576 MONO_ARCH_SAVE_REGS;
5578 g_assert (module->image);
5579 return mono_string_new (domain, module->image->guid);
5583 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5585 #ifdef PLATFORM_WIN32
5586 if (module->image && module->image->is_module_handle)
5587 return module->image->raw_data;
5590 return (gpointer) (-1);
5594 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5596 if (image->dynamic) {
5597 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5598 *pe_kind = dyn->pe_kind;
5599 *machine = dyn->machine;
5602 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5603 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5608 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5610 return (image->md_version_major << 16) | (image->md_version_minor);
5614 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5616 MonoArray *exceptions;
5619 MONO_ARCH_SAVE_REGS;
5622 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5624 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5625 for (i = 0; i < mono_array_length (exceptions); ++i) {
5626 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5628 mono_raise_exception (ex);
5635 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5637 guint32 cols [MONO_MEMBERREF_SIZE];
5639 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5640 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5641 mono_metadata_decode_blob_size (sig, &sig);
5642 return (*sig != 0x6);
5646 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5649 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5650 mono_array_addr (type_args, MonoType*, 0));
5652 context->class_inst = NULL;
5654 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5655 mono_array_addr (method_args, MonoType*, 0));
5657 context->method_inst = NULL;
5661 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5664 int table = mono_metadata_token_table (token);
5665 int index = mono_metadata_token_index (token);
5666 MonoGenericContext context;
5668 *error = ResolveTokenError_Other;
5670 /* Validate token */
5671 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5672 (table != MONO_TABLE_TYPESPEC)) {
5673 *error = ResolveTokenError_BadTable;
5677 if (image->dynamic) {
5678 if (type_args || method_args)
5679 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5680 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5683 return &klass->byval_arg;
5686 if ((index <= 0) || (index > image->tables [table].rows)) {
5687 *error = ResolveTokenError_OutOfRange;
5691 init_generic_context_from_args (&context, type_args, method_args);
5692 klass = mono_class_get_full (image, token, &context);
5694 if (mono_loader_get_last_error ())
5695 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5698 return &klass->byval_arg;
5704 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5706 int table = mono_metadata_token_table (token);
5707 int index = mono_metadata_token_index (token);
5708 MonoGenericContext context;
5711 *error = ResolveTokenError_Other;
5713 /* Validate token */
5714 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5715 (table != MONO_TABLE_MEMBERREF)) {
5716 *error = ResolveTokenError_BadTable;
5720 if (image->dynamic) {
5721 if (type_args || method_args)
5722 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5723 /* FIXME: validate memberref token type */
5724 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5727 if ((index <= 0) || (index > image->tables [table].rows)) {
5728 *error = ResolveTokenError_OutOfRange;
5731 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5732 *error = ResolveTokenError_BadTable;
5736 init_generic_context_from_args (&context, type_args, method_args);
5737 method = mono_get_method_full (image, token, NULL, &context);
5739 if (mono_loader_get_last_error ())
5740 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5746 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5748 int index = mono_metadata_token_index (token);
5750 *error = ResolveTokenError_Other;
5752 /* Validate token */
5753 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5754 *error = ResolveTokenError_BadTable;
5759 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5761 if ((index <= 0) || (index >= image->heap_us.size)) {
5762 *error = ResolveTokenError_OutOfRange;
5766 /* FIXME: What to do if the index points into the middle of a string ? */
5768 return mono_ldstr (mono_domain_get (), image, index);
5771 static MonoClassField*
5772 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5775 int table = mono_metadata_token_table (token);
5776 int index = mono_metadata_token_index (token);
5777 MonoGenericContext context;
5778 MonoClassField *field;
5780 *error = ResolveTokenError_Other;
5782 /* Validate token */
5783 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5784 *error = ResolveTokenError_BadTable;
5788 if (image->dynamic) {
5789 if (type_args || method_args)
5790 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5791 /* FIXME: validate memberref token type */
5792 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5795 if ((index <= 0) || (index > image->tables [table].rows)) {
5796 *error = ResolveTokenError_OutOfRange;
5799 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5800 *error = ResolveTokenError_BadTable;
5804 init_generic_context_from_args (&context, type_args, method_args);
5805 field = mono_field_from_token (image, token, &klass, &context);
5807 if (mono_loader_get_last_error ())
5808 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5815 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5817 int table = mono_metadata_token_table (token);
5819 *error = ResolveTokenError_Other;
5822 case MONO_TABLE_TYPEDEF:
5823 case MONO_TABLE_TYPEREF:
5824 case MONO_TABLE_TYPESPEC: {
5825 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5827 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5831 case MONO_TABLE_METHOD:
5832 case MONO_TABLE_METHODSPEC: {
5833 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5835 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5839 case MONO_TABLE_FIELD: {
5840 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5842 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5846 case MONO_TABLE_MEMBERREF:
5847 if (mono_metadata_memberref_is_method (image, token)) {
5848 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5850 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5855 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5857 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5864 *error = ResolveTokenError_BadTable;
5871 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5873 int table = mono_metadata_token_table (token);
5874 int idx = mono_metadata_token_index (token);
5875 MonoTableInfo *tables = image->tables;
5880 *error = ResolveTokenError_OutOfRange;
5882 /* FIXME: Support other tables ? */
5883 if (table != MONO_TABLE_STANDALONESIG)
5889 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5892 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5894 ptr = mono_metadata_blob_heap (image, sig);
5895 len = mono_metadata_decode_blob_size (ptr, &ptr);
5897 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5898 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5902 static MonoReflectionType*
5903 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5906 int isbyref = 0, rank;
5907 char *str = mono_string_to_utf8 (smodifiers);
5910 MONO_ARCH_SAVE_REGS;
5912 klass = mono_class_from_mono_type (tb->type.type);
5914 /* logic taken from mono_reflection_parse_type(): keep in sync */
5918 if (isbyref) { /* only one level allowed by the spec */
5925 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5928 klass = mono_ptr_class_get (&klass->byval_arg);
5929 mono_class_init (klass);
5940 else if (*p != '*') { /* '*' means unknown lower bound */
5951 klass = mono_array_class_get (klass, rank);
5952 mono_class_init (klass);
5959 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5963 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5968 MONO_ARCH_SAVE_REGS;
5971 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5976 static MonoReflectionType *
5977 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5979 MonoClass *klass, *aklass;
5981 MONO_ARCH_SAVE_REGS;
5983 klass = mono_class_from_mono_type (type->type);
5984 if (rank == 0) //single dimentional array
5985 aklass = mono_array_class_get (klass, 1);
5987 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5989 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5992 static MonoReflectionType *
5993 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5997 MONO_ARCH_SAVE_REGS;
5999 klass = mono_class_from_mono_type (type->type);
6001 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
6004 static MonoReflectionType *
6005 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6009 MONO_ARCH_SAVE_REGS;
6011 pklass = mono_ptr_class_get (type->type);
6013 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
6017 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6018 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6020 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6021 MonoObject *delegate;
6023 MonoMethod *method = info->method;
6025 MONO_ARCH_SAVE_REGS;
6027 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6029 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
6030 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6034 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6036 if (method->dynamic) {
6037 /* Creating a trampoline would leak memory */
6038 func = mono_compile_method (method);
6040 func = mono_create_ftnptr (mono_domain_get (),
6041 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6044 mono_delegate_ctor_with_method (delegate, target, func, method);
6050 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6052 /* Reset the invoke impl to the default one */
6053 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6057 * Magic number to convert a time which is relative to
6058 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6060 #define EPOCH_ADJUST ((guint64)62135596800LL)
6063 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6065 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6067 #ifdef PLATFORM_WIN32
6068 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6070 convert_to_absolute_date(SYSTEMTIME *date)
6072 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6073 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6074 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6075 /* from the calendar FAQ */
6076 int a = (14 - date->wMonth) / 12;
6077 int y = date->wYear - a;
6078 int m = date->wMonth + 12 * a - 2;
6079 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6081 /* d is now the day of the week for the first of the month (0 == Sunday) */
6083 int day_of_week = date->wDayOfWeek;
6085 /* set day_in_month to the first day in the month which falls on day_of_week */
6086 int day_in_month = 1 + (day_of_week - d);
6087 if (day_in_month <= 0)
6090 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6091 date->wDay = day_in_month + (date->wDay - 1) * 7;
6092 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6097 #ifndef PLATFORM_WIN32
6099 * Return's the offset from GMT of a local time.
6101 * tm is a local time
6102 * t is the same local time as seconds.
6105 gmt_offset(struct tm *tm, time_t t)
6107 #if defined (HAVE_TM_GMTOFF)
6108 return tm->tm_gmtoff;
6113 g.tm_isdst = tm->tm_isdst;
6115 return (int)difftime(t, t2);
6120 * This is heavily based on zdump.c from glibc 2.2.
6122 * * data[0]: start of daylight saving time (in DateTime ticks).
6123 * * data[1]: end of daylight saving time (in DateTime ticks).
6124 * * data[2]: utcoffset (in TimeSpan ticks).
6125 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6126 * * name[0]: name of this timezone when not daylight saving.
6127 * * name[1]: name of this timezone when daylight saving.
6129 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6130 * the class library allows years between 1 and 9999.
6132 * Returns true on success and zero on failure.
6135 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6137 #ifndef PLATFORM_WIN32
6138 MonoDomain *domain = mono_domain_get ();
6139 struct tm start, tt;
6143 int is_daylight = 0, day;
6146 MONO_ARCH_SAVE_REGS;
6148 MONO_CHECK_ARG_NULL (data);
6149 MONO_CHECK_ARG_NULL (names);
6151 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6152 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6155 * no info is better than crashing: we'll need our own tz data
6156 * to make this work properly, anyway. The range is probably
6157 * reduced to 1970 .. 2037 because that is what mktime is
6158 * guaranteed to support (we get into an infinite loop
6162 memset (&start, 0, sizeof (start));
6165 start.tm_year = year-1900;
6167 t = mktime (&start);
6169 if ((year < 1970) || (year > 2037) || (t == -1)) {
6171 tt = *localtime (&t);
6172 strftime (tzone, sizeof (tzone), "%Z", &tt);
6173 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6174 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6178 gmtoff = gmt_offset (&start, t);
6180 /* For each day of the year, calculate the tm_gmtoff. */
6181 for (day = 0; day < 365; day++) {
6184 tt = *localtime (&t);
6186 /* Daylight saving starts or ends here. */
6187 if (gmt_offset (&tt, t) != gmtoff) {
6191 /* Try to find the exact hour when daylight saving starts/ends. */
6195 tt1 = *localtime (&t1);
6196 } while (gmt_offset (&tt1, t1) != gmtoff);
6198 /* Try to find the exact minute when daylight saving starts/ends. */
6201 tt1 = *localtime (&t1);
6202 } while (gmt_offset (&tt1, t1) == gmtoff);
6204 strftime (tzone, sizeof (tzone), "%Z", &tt);
6206 /* Write data, if we're already in daylight saving, we're done. */
6208 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6209 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6212 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6213 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6217 /* This is only set once when we enter daylight saving. */
6218 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6219 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6221 gmtoff = gmt_offset (&tt, t);
6226 strftime (tzone, sizeof (tzone), "%Z", &tt);
6227 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6228 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6229 mono_array_set ((*data), gint64, 0, 0);
6230 mono_array_set ((*data), gint64, 1, 0);
6231 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6232 mono_array_set ((*data), gint64, 3, 0);
6237 MonoDomain *domain = mono_domain_get ();
6238 TIME_ZONE_INFORMATION tz_info;
6243 tz_id = GetTimeZoneInformation (&tz_info);
6244 if (tz_id == TIME_ZONE_ID_INVALID)
6247 MONO_CHECK_ARG_NULL (data);
6248 MONO_CHECK_ARG_NULL (names);
6250 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6251 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6253 for (i = 0; i < 32; ++i)
6254 if (!tz_info.DaylightName [i])
6256 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6257 for (i = 0; i < 32; ++i)
6258 if (!tz_info.StandardName [i])
6260 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6262 if ((year <= 1601) || (year > 30827)) {
6264 * According to MSDN, the MS time functions can't handle dates outside
6270 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6271 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6272 tz_info.StandardDate.wYear = year;
6273 convert_to_absolute_date(&tz_info.StandardDate);
6274 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6279 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6280 tz_info.DaylightDate.wYear = year;
6281 convert_to_absolute_date(&tz_info.DaylightDate);
6282 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6287 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6289 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6290 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6297 ves_icall_System_Object_obj_address (MonoObject *this)
6299 MONO_ARCH_SAVE_REGS;
6306 static inline gint32
6307 mono_array_get_byte_length (MonoArray *array)
6313 klass = array->obj.vtable->klass;
6315 if (array->bounds == NULL)
6316 length = array->max_length;
6319 for (i = 0; i < klass->rank; ++ i)
6320 length *= array->bounds [i].length;
6323 switch (klass->element_class->byval_arg.type) {
6326 case MONO_TYPE_BOOLEAN:
6330 case MONO_TYPE_CHAR:
6338 return length * sizeof (gpointer);
6349 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6351 MONO_ARCH_SAVE_REGS;
6353 return mono_array_get_byte_length (array);
6357 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6359 MONO_ARCH_SAVE_REGS;
6361 return mono_array_get (array, gint8, idx);
6365 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6367 MONO_ARCH_SAVE_REGS;
6369 mono_array_set (array, gint8, idx, value);
6373 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6375 guint8 *src_buf, *dest_buf;
6377 MONO_ARCH_SAVE_REGS;
6379 /* watch out for integer overflow */
6380 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6383 src_buf = (guint8 *)src->vector + src_offset;
6384 dest_buf = (guint8 *)dest->vector + dest_offset;
6387 memcpy (dest_buf, src_buf, count);
6389 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6395 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6397 MonoDomain *domain = mono_object_domain (this);
6399 MonoRealProxy *rp = ((MonoRealProxy *)this);
6400 MonoTransparentProxy *tp;
6404 MONO_ARCH_SAVE_REGS;
6406 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6407 tp = (MonoTransparentProxy*) res;
6409 MONO_OBJECT_SETREF (tp, rp, rp);
6410 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6411 klass = mono_class_from_mono_type (type);
6413 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6414 tp->remote_class = mono_remote_class (domain, class_name, klass);
6416 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6420 static MonoReflectionType *
6421 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6423 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6426 /* System.Environment */
6429 ves_icall_System_Environment_get_UserName (void)
6431 MONO_ARCH_SAVE_REGS;
6433 /* using glib is more portable */
6434 return mono_string_new (mono_domain_get (), g_get_user_name ());
6439 ves_icall_System_Environment_get_MachineName (void)
6441 #if defined (PLATFORM_WIN32)
6446 len = MAX_COMPUTERNAME_LENGTH + 1;
6447 buf = g_new (gunichar2, len);
6450 if (GetComputerName (buf, (PDWORD) &len))
6451 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6455 #elif !defined(DISABLE_SOCKETS)
6459 if (gethostname (buf, sizeof (buf)) == 0)
6460 result = mono_string_new (mono_domain_get (), buf);
6466 return mono_string_new (mono_domain_get (), "mono");
6471 ves_icall_System_Environment_get_Platform (void)
6473 #if defined (PLATFORM_WIN32)
6476 #elif defined(__MACH__)
6478 if (mono_framework_version () < 2)
6482 // For compatibility with our client code, this will be 4 for a while.
6483 // We will eventually move to 6 to match .NET, but it requires all client
6484 // code to be updated and the documentation everywhere to be updated
6490 if (mono_framework_version () < 2)
6497 ves_icall_System_Environment_get_NewLine (void)
6499 MONO_ARCH_SAVE_REGS;
6501 #if defined (PLATFORM_WIN32)
6502 return mono_string_new (mono_domain_get (), "\r\n");
6504 return mono_string_new (mono_domain_get (), "\n");
6509 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6514 MONO_ARCH_SAVE_REGS;
6519 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6520 value = g_getenv (utf8_name);
6527 return mono_string_new (mono_domain_get (), value);
6531 * There is no standard way to get at environ.
6534 #ifndef __MINGW32_VERSION
6536 /* Apple defines this in crt_externs.h but doesn't provide that header for
6537 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6538 * in fact exist on all implementations (so far)
6540 gchar ***_NSGetEnviron();
6541 #define environ (*_NSGetEnviron())
6550 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6552 #ifdef PLATFORM_WIN32
6561 env_strings = GetEnvironmentStrings();
6564 env_string = env_strings;
6565 while (*env_string != '\0') {
6566 /* weird case that MS seems to skip */
6567 if (*env_string != '=')
6569 while (*env_string != '\0')
6575 domain = mono_domain_get ();
6576 names = mono_array_new (domain, mono_defaults.string_class, n);
6580 env_string = env_strings;
6581 while (*env_string != '\0') {
6582 /* weird case that MS seems to skip */
6583 if (*env_string != '=') {
6584 equal_str = wcschr(env_string, '=');
6585 g_assert(equal_str);
6586 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6587 mono_array_setref (names, n, str);
6590 while (*env_string != '\0')
6595 FreeEnvironmentStrings (env_strings);
6607 MONO_ARCH_SAVE_REGS;
6610 for (e = environ; *e != 0; ++ e)
6613 domain = mono_domain_get ();
6614 names = mono_array_new (domain, mono_defaults.string_class, n);
6617 for (e = environ; *e != 0; ++ e) {
6618 parts = g_strsplit (*e, "=", 2);
6620 str = mono_string_new (domain, *parts);
6621 mono_array_setref (names, n, str);
6634 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6636 #if !GLIB_CHECK_VERSION(2,4,0)
6637 #define g_setenv(a,b,c) setenv(a,b,c)
6638 #define g_unsetenv(a) unsetenv(a)
6642 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6644 #ifdef PLATFORM_WIN32
6645 gunichar2 *utf16_name, *utf16_value;
6647 gchar *utf8_name, *utf8_value;
6650 MONO_ARCH_SAVE_REGS;
6652 #ifdef PLATFORM_WIN32
6653 utf16_name = mono_string_to_utf16 (name);
6654 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6655 SetEnvironmentVariable (utf16_name, NULL);
6656 g_free (utf16_name);
6660 utf16_value = mono_string_to_utf16 (value);
6662 SetEnvironmentVariable (utf16_name, utf16_value);
6664 g_free (utf16_name);
6665 g_free (utf16_value);
6667 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6669 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6670 g_unsetenv (utf8_name);
6675 utf8_value = mono_string_to_utf8 (value);
6676 g_setenv (utf8_name, utf8_value, TRUE);
6679 g_free (utf8_value);
6684 ves_icall_System_Environment_Exit (int result)
6686 MONO_ARCH_SAVE_REGS;
6688 mono_threads_set_shutting_down ();
6690 mono_runtime_set_shutting_down ();
6692 /* Suspend all managed threads since the runtime is going away */
6693 mono_thread_suspend_all_other_threads ();
6695 mono_runtime_quit ();
6697 /* we may need to do some cleanup here... */
6702 ves_icall_System_Environment_GetGacPath (void)
6704 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6708 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6710 #if defined (PLATFORM_WIN32)
6711 #ifndef CSIDL_FLAG_CREATE
6712 #define CSIDL_FLAG_CREATE 0x8000
6715 WCHAR path [MAX_PATH];
6716 /* Create directory if no existing */
6717 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6721 return mono_string_new_utf16 (mono_domain_get (), path, len);
6724 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6726 return mono_string_new (mono_domain_get (), "");
6730 ves_icall_System_Environment_GetLogicalDrives (void)
6732 gunichar2 buf [128], *ptr, *dname;
6734 guint initial_size = 127, size = 128;
6737 MonoString *drivestr;
6738 MonoDomain *domain = mono_domain_get ();
6741 MONO_ARCH_SAVE_REGS;
6746 while (size > initial_size) {
6747 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6748 if (size > initial_size) {
6751 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6752 initial_size = size;
6766 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6771 while (*u16) { u16++; len ++; }
6772 drivestr = mono_string_new_utf16 (domain, dname, len);
6773 mono_array_setref (result, ndrives++, drivestr);
6784 ves_icall_System_Environment_InternalGetHome (void)
6786 MONO_ARCH_SAVE_REGS;
6788 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6791 static const char *encodings [] = {
6793 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6794 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6795 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6797 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6798 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6799 "x_unicode_2_0_utf_7",
6801 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6802 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6804 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6807 "unicodefffe", "utf_16be",
6814 * Returns the internal codepage, if the value of "int_code_page" is
6815 * 1 at entry, and we can not compute a suitable code page number,
6816 * returns the code page as a string
6819 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6824 char *codepage = NULL;
6826 int want_name = *int_code_page;
6829 *int_code_page = -1;
6830 MONO_ARCH_SAVE_REGS;
6832 g_get_charset (&cset);
6833 c = codepage = strdup (cset);
6834 for (c = codepage; *c; c++){
6835 if (isascii (*c) && isalpha (*c))
6840 /* g_print ("charset: %s\n", cset); */
6842 /* handle some common aliases */
6845 for (i = 0; p != 0; ){
6846 if ((gssize) p < 7){
6848 p = encodings [++i];
6851 if (strcmp (p, codepage) == 0){
6852 *int_code_page = code;
6855 p = encodings [++i];
6858 if (strstr (codepage, "utf_8") != NULL)
6859 *int_code_page |= 0x10000000;
6862 if (want_name && *int_code_page == -1)
6863 return mono_string_new (mono_domain_get (), cset);
6869 ves_icall_System_Environment_get_HasShutdownStarted (void)
6871 if (mono_runtime_is_shutting_down ())
6874 if (mono_domain_is_unloading (mono_domain_get ()))
6881 ves_icall_System_Environment_BroadcastSettingChange (void)
6883 #ifdef PLATFORM_WIN32
6884 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6889 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6890 MonoReflectionMethod *method,
6891 MonoArray *out_args)
6893 MONO_ARCH_SAVE_REGS;
6895 mono_message_init (mono_object_domain (this), this, method, out_args);
6899 ves_icall_IsTransparentProxy (MonoObject *proxy)
6901 MONO_ARCH_SAVE_REGS;
6906 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6912 static MonoReflectionMethod *
6913 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6914 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6918 MonoMethod **vtable;
6919 MonoMethod *res = NULL;
6921 MONO_CHECK_ARG_NULL (rtype);
6922 MONO_CHECK_ARG_NULL (rmethod);
6924 method = rmethod->method;
6925 klass = mono_class_from_mono_type (rtype->type);
6927 if (MONO_CLASS_IS_INTERFACE (klass))
6930 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6933 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6934 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6940 mono_class_setup_vtable (klass);
6941 vtable = klass->vtable;
6943 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6944 int offs = mono_class_interface_offset (klass, method->klass);
6946 res = vtable [offs + method->slot];
6948 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6951 if (method->slot != -1)
6952 res = vtable [method->slot];
6958 return mono_method_get_object (mono_domain_get (), res, NULL);
6962 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6967 MONO_ARCH_SAVE_REGS;
6969 klass = mono_class_from_mono_type (type->type);
6970 vtable = mono_class_vtable (mono_domain_get (), klass);
6972 if (enable) vtable->remote = 1;
6973 else vtable->remote = 0;
6977 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6982 MONO_ARCH_SAVE_REGS;
6984 domain = mono_object_domain (type);
6985 klass = mono_class_from_mono_type (type->type);
6987 if (klass->rank >= 1) {
6988 g_assert (klass->rank == 1);
6989 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6991 /* Bypass remoting object creation check */
6992 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6997 ves_icall_System_IO_get_temp_path (void)
6999 MONO_ARCH_SAVE_REGS;
7001 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7004 #ifndef PLATFORM_NO_DRIVEINFO
7006 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7007 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7011 ULARGE_INTEGER wapi_free_bytes_avail;
7012 ULARGE_INTEGER wapi_total_number_of_bytes;
7013 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7015 MONO_ARCH_SAVE_REGS;
7017 *error = ERROR_SUCCESS;
7018 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7019 &wapi_total_number_of_free_bytes);
7022 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7023 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7024 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7026 *free_bytes_avail = 0;
7027 *total_number_of_bytes = 0;
7028 *total_number_of_free_bytes = 0;
7029 *error = GetLastError ();
7036 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7038 MONO_ARCH_SAVE_REGS;
7040 return GetDriveType (mono_string_chars (root_path_name));
7045 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7047 MONO_ARCH_SAVE_REGS;
7049 return mono_compile_method (method);
7053 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7058 MONO_ARCH_SAVE_REGS;
7060 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7062 #if defined (PLATFORM_WIN32)
7063 /* Avoid mixing '/' and '\\' */
7066 for (i = strlen (path) - 1; i >= 0; i--)
7067 if (path [i] == '/')
7071 mcpath = mono_string_new (mono_domain_get (), path);
7078 get_bundled_machine_config (void)
7080 const gchar *machine_config;
7082 MONO_ARCH_SAVE_REGS;
7084 machine_config = mono_get_machine_config ();
7086 if (!machine_config)
7089 return mono_string_new (mono_domain_get (), machine_config);
7093 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7098 MONO_ARCH_SAVE_REGS;
7100 path = g_path_get_dirname (mono_get_config_dir ());
7102 #if defined (PLATFORM_WIN32)
7103 /* Avoid mixing '/' and '\\' */
7106 for (i = strlen (path) - 1; i >= 0; i--)
7107 if (path [i] == '/')
7111 ipath = mono_string_new (mono_domain_get (), path);
7118 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7120 MonoPEResourceDataEntry *entry;
7123 MONO_ARCH_SAVE_REGS;
7125 if (!assembly || !result || !size)
7130 image = assembly->assembly->image;
7131 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7135 *result = mono_image_rva_map (image, entry->rde_data_offset);
7140 *size = entry->rde_size;
7146 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7148 return mono_debug_using_mono_debugger ();
7152 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7154 #if defined (PLATFORM_WIN32)
7155 OutputDebugString (mono_string_chars (message));
7157 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7161 /* Only used for value types */
7163 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7168 MONO_ARCH_SAVE_REGS;
7170 domain = mono_object_domain (type);
7171 klass = mono_class_from_mono_type (type->type);
7173 if (mono_class_is_nullable (klass))
7174 /* No arguments -> null */
7177 return mono_object_new (domain, klass);
7180 static MonoReflectionMethod *
7181 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7183 MonoClass *klass, *parent;
7184 MonoMethod *method = m->method;
7185 MonoMethod *result = NULL;
7187 MONO_ARCH_SAVE_REGS;
7189 if (method->klass == NULL)
7192 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7193 MONO_CLASS_IS_INTERFACE (method->klass) ||
7194 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7197 klass = method->klass;
7198 if (klass->generic_class)
7199 klass = klass->generic_class->container_class;
7201 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7202 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7203 mono_class_setup_vtable (parent);
7204 if (parent->vtable_size <= method->slot)
7209 if (klass == method->klass)
7212 result = klass->vtable [method->slot];
7213 if (result == NULL) {
7214 /* It is an abstract method */
7215 gpointer iter = NULL;
7216 while ((result = mono_class_get_methods (klass, &iter)))
7217 if (result->slot == method->slot)
7224 return mono_method_get_object (mono_domain_get (), result, NULL);
7228 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7230 MonoMethod *method = m->method;
7232 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7237 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7239 MONO_ARCH_SAVE_REGS;
7241 iter->sig = *(MonoMethodSignature**)argsp;
7243 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7244 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7247 /* FIXME: it's not documented what start is exactly... */
7251 iter->args = argsp + sizeof (gpointer);
7252 #ifndef MONO_ARCH_REGPARMS
7254 guint32 i, arg_size;
7256 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7257 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7258 iter->args = (char*)iter->args + arg_size;
7263 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7265 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7269 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7271 guint32 i, arg_size;
7274 MONO_ARCH_SAVE_REGS;
7276 i = iter->sig->sentinelpos + iter->next_arg;
7278 g_assert (i < iter->sig->param_count);
7280 res.type = iter->sig->params [i];
7281 res.klass = mono_class_from_mono_type (res.type);
7282 res.value = iter->args;
7283 arg_size = mono_type_stack_size (res.type, &align);
7284 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7285 if (arg_size <= sizeof (gpointer)) {
7287 int padding = arg_size - mono_type_size (res.type, &dummy);
7288 res.value = (guint8*)res.value + padding;
7291 iter->args = (char*)iter->args + arg_size;
7294 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7300 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7302 guint32 i, arg_size;
7305 MONO_ARCH_SAVE_REGS;
7307 i = iter->sig->sentinelpos + iter->next_arg;
7309 g_assert (i < iter->sig->param_count);
7311 while (i < iter->sig->param_count) {
7312 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7314 res.type = iter->sig->params [i];
7315 res.klass = mono_class_from_mono_type (res.type);
7316 /* FIXME: endianess issue... */
7317 res.value = iter->args;
7318 arg_size = mono_type_stack_size (res.type, &align);
7319 iter->args = (char*)iter->args + arg_size;
7321 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7324 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7333 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7336 MONO_ARCH_SAVE_REGS;
7338 i = iter->sig->sentinelpos + iter->next_arg;
7340 g_assert (i < iter->sig->param_count);
7342 return iter->sig->params [i];
7346 mono_TypedReference_ToObject (MonoTypedRef tref)
7348 MONO_ARCH_SAVE_REGS;
7350 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7351 MonoObject** objp = tref.value;
7355 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7359 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7361 MONO_ARCH_SAVE_REGS;
7363 if (MONO_TYPE_IS_REFERENCE (type)) {
7364 MonoObject** objp = value;
7368 return mono_value_box (mono_domain_get (), klass, value);
7372 prelink_method (MonoMethod *method)
7374 const char *exc_class, *exc_arg;
7375 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7377 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7379 mono_raise_exception(
7380 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7382 /* create the wrapper, too? */
7386 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7388 MONO_ARCH_SAVE_REGS;
7389 prelink_method (method->method);
7393 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7395 MonoClass *klass = mono_class_from_mono_type (type->type);
7397 gpointer iter = NULL;
7398 MONO_ARCH_SAVE_REGS;
7400 while ((m = mono_class_get_methods (klass, &iter)))
7404 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7406 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7407 gint32 const **exponents,
7408 gunichar2 const **digitLowerTable,
7409 gunichar2 const **digitUpperTable,
7410 gint64 const **tenPowersList,
7411 gint32 const **decHexDigits)
7413 *mantissas = Formatter_MantissaBitsTable;
7414 *exponents = Formatter_TensExponentTable;
7415 *digitLowerTable = Formatter_DigitLowerTable;
7416 *digitUpperTable = Formatter_DigitUpperTable;
7417 *tenPowersList = Formatter_TenPowersList;
7418 *decHexDigits = Formatter_DecHexDigits;
7421 /* These parameters are "readonly" in corlib/System/Char.cs */
7423 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7424 guint8 const **numeric_data,
7425 gdouble const **numeric_data_values,
7426 guint16 const **to_lower_data_low,
7427 guint16 const **to_lower_data_high,
7428 guint16 const **to_upper_data_low,
7429 guint16 const **to_upper_data_high)
7431 *category_data = CategoryData;
7432 *numeric_data = NumericData;
7433 *numeric_data_values = NumericDataValues;
7434 *to_lower_data_low = ToLowerDataLow;
7435 *to_lower_data_high = ToLowerDataHigh;
7436 *to_upper_data_low = ToUpperDataLow;
7437 *to_upper_data_high = ToUpperDataHigh;
7441 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7443 return method->method->token;
7447 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7448 * and avoid useless allocations.
7451 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7455 for (i = 0; i < type->num_mods; ++i) {
7456 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7461 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7463 for (i = 0; i < type->num_mods; ++i) {
7464 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7465 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7466 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7474 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7476 MonoType *type = param->ClassImpl->type;
7477 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7478 MonoImage *image = method->method->klass->image;
7479 int pos = param->PositionImpl;
7480 MonoMethodSignature *sig = mono_method_signature (method->method);
7484 type = sig->params [pos];
7486 return type_array_from_modifiers (image, type, optional);
7490 get_property_type (MonoProperty *prop)
7492 MonoMethodSignature *sig;
7494 sig = mono_method_signature (prop->get);
7496 } else if (prop->set) {
7497 sig = mono_method_signature (prop->set);
7498 return sig->params [sig->param_count - 1];
7504 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7506 MonoType *type = get_property_type (property->property);
7507 MonoImage *image = property->klass->image;
7511 return type_array_from_modifiers (image, type, optional);
7515 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7517 MonoCustomAttrInfo *cinfo;
7520 cinfo = mono_reflection_get_custom_attrs_info (obj);
7523 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7525 mono_custom_attrs_free (cinfo);
7530 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7532 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7534 if (mono_loader_get_last_error ()) {
7535 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7536 g_assert_not_reached ();
7545 GCHandle_CheckCurrentDomain (guint32 gchandle)
7547 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7551 ves_icall_Mono_Runtime_GetDisplayName (void)
7553 static const char display_name_str [] = "Mono " VERSION;
7554 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7555 return display_name;
7559 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7561 MonoString *message;
7565 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7566 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7569 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7571 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7579 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7580 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7581 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7582 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7583 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7584 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7585 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7586 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7590 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7595 gunichar2 last, prev_last, prev2_last;
7603 last = prev_last = 0, prev2_last = 0;
7604 for (i = 0; i < ilength; i++) {
7606 if (c >= sizeof (dbase64)) {
7607 exc = mono_exception_from_name_msg (mono_get_corlib (),
7608 "System", "FormatException",
7609 "Invalid character found.");
7610 mono_raise_exception (exc);
7611 } else if (isspace (c)) {
7614 prev2_last = prev_last;
7620 olength = ilength - ignored;
7622 if (allowWhitespaceOnly && olength == 0) {
7623 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7626 if ((olength & 3) != 0 || olength <= 0) {
7627 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7628 "FormatException", "Invalid length.");
7629 mono_raise_exception (exc);
7632 if (prev2_last == '=') {
7633 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7634 mono_raise_exception (exc);
7637 olength = (olength * 3) / 4;
7641 if (prev_last == '=')
7644 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7645 res_ptr = mono_array_addr (result, guchar, 0);
7646 for (i = 0; i < ilength; ) {
7649 for (k = 0; k < 4 && i < ilength;) {
7655 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7656 exc = mono_exception_from_name_msg (mono_get_corlib (),
7657 "System", "FormatException",
7658 "Invalid character found.");
7659 mono_raise_exception (exc);
7664 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7666 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7668 *res_ptr++ = (b [2] << 6) | b [3];
7670 while (i < ilength && isspace (start [i]))
7678 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7680 MONO_ARCH_SAVE_REGS;
7682 return base64_to_byte_array (mono_string_chars (str),
7683 mono_string_length (str), allowWhitespaceOnly);
7687 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7689 MONO_ARCH_SAVE_REGS;
7691 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7695 #define ICALL_TYPE(id,name,first)
7696 #define ICALL(id,name,func) Icall_ ## id,
7699 #include "metadata/icall-def.h"
7705 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7706 #define ICALL(id,name,func)
7708 #include "metadata/icall-def.h"
7714 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7715 #define ICALL(id,name,func)
7717 guint16 first_icall;
7720 static const IcallTypeDesc
7721 icall_type_descs [] = {
7722 #include "metadata/icall-def.h"
7726 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7729 #define ICALL_TYPE(id,name,first)
7732 #ifdef HAVE_ARRAY_ELEM_INIT
7733 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7734 #define MSGSTRFIELD1(line) str##line
7736 static const struct msgstrtn_t {
7737 #define ICALL(id,name,func)
7739 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7740 #include "metadata/icall-def.h"
7742 } icall_type_names_str = {
7743 #define ICALL_TYPE(id,name,first) (name),
7744 #include "metadata/icall-def.h"
7747 static const guint16 icall_type_names_idx [] = {
7748 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7749 #include "metadata/icall-def.h"
7752 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7754 static const struct msgstr_t {
7756 #define ICALL_TYPE(id,name,first)
7757 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7758 #include "metadata/icall-def.h"
7760 } icall_names_str = {
7761 #define ICALL(id,name,func) (name),
7762 #include "metadata/icall-def.h"
7765 static const guint16 icall_names_idx [] = {
7766 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7767 #include "metadata/icall-def.h"
7770 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7776 #define ICALL_TYPE(id,name,first) name,
7777 #define ICALL(id,name,func)
7778 static const char* const
7779 icall_type_names [] = {
7780 #include "metadata/icall-def.h"
7784 #define icall_type_name_get(id) (icall_type_names [(id)])
7788 #define ICALL_TYPE(id,name,first)
7789 #define ICALL(id,name,func) name,
7790 static const char* const
7792 #include "metadata/icall-def.h"
7795 #define icall_name_get(id) icall_names [(id)]
7797 #endif /* !HAVE_ARRAY_ELEM_INIT */
7801 #define ICALL_TYPE(id,name,first)
7802 #define ICALL(id,name,func) func,
7803 static const gconstpointer
7804 icall_functions [] = {
7805 #include "metadata/icall-def.h"
7809 static GHashTable *icall_hash = NULL;
7810 static GHashTable *jit_icall_hash_name = NULL;
7811 static GHashTable *jit_icall_hash_addr = NULL;
7814 mono_icall_init (void)
7818 /* check that tables are sorted: disable in release */
7821 const char *prev_class = NULL;
7822 const char *prev_method;
7824 for (i = 0; i < Icall_type_num; ++i) {
7825 const IcallTypeDesc *desc;
7828 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7829 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7830 prev_class = icall_type_name_get (i);
7831 desc = &icall_type_descs [i];
7832 num_icalls = icall_desc_num_icalls (desc);
7833 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7834 for (j = 0; j < num_icalls; ++j) {
7835 const char *methodn = icall_name_get (desc->first_icall + j);
7836 if (prev_method && strcmp (prev_method, methodn) >= 0)
7837 g_print ("method %s should come before method %s\n", methodn, prev_method);
7838 prev_method = methodn;
7843 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7847 mono_icall_cleanup (void)
7849 g_hash_table_destroy (icall_hash);
7850 g_hash_table_destroy (jit_icall_hash_name);
7851 g_hash_table_destroy (jit_icall_hash_addr);
7855 mono_add_internal_call (const char *name, gconstpointer method)
7857 mono_loader_lock ();
7859 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7861 mono_loader_unlock ();
7864 #ifdef HAVE_ARRAY_ELEM_INIT
7866 compare_method_imap (const void *key, const void *elem)
7868 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7869 return strcmp (key, method_name);
7873 find_method_icall (const IcallTypeDesc *imap, const char *name)
7875 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7878 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7882 compare_class_imap (const void *key, const void *elem)
7884 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7885 return strcmp (key, class_name);
7888 static const IcallTypeDesc*
7889 find_class_icalls (const char *name)
7891 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7894 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7899 compare_method_imap (const void *key, const void *elem)
7901 const char** method_name = (const char**)elem;
7902 return strcmp (key, *method_name);
7906 find_method_icall (const IcallTypeDesc *imap, const char *name)
7908 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7911 return (gpointer)icall_functions [(nameslot - icall_names)];
7915 compare_class_imap (const void *key, const void *elem)
7917 const char** class_name = (const char**)elem;
7918 return strcmp (key, *class_name);
7921 static const IcallTypeDesc*
7922 find_class_icalls (const char *name)
7924 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7927 return &icall_type_descs [nameslot - icall_type_names];
7933 * we should probably export this as an helper (handle nested types).
7934 * Returns the number of chars written in buf.
7937 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7939 int nspacelen, cnamelen;
7940 nspacelen = strlen (klass->name_space);
7941 cnamelen = strlen (klass->name);
7942 if (nspacelen + cnamelen + 2 > bufsize)
7945 memcpy (buf, klass->name_space, nspacelen);
7946 buf [nspacelen ++] = '.';
7948 memcpy (buf + nspacelen, klass->name, cnamelen);
7949 buf [nspacelen + cnamelen] = 0;
7950 return nspacelen + cnamelen;
7954 mono_lookup_internal_call (MonoMethod *method)
7959 int typelen = 0, mlen, siglen;
7961 const IcallTypeDesc *imap;
7963 g_assert (method != NULL);
7965 if (method->is_inflated)
7966 method = ((MonoMethodInflated *) method)->declaring;
7968 if (method->klass->nested_in) {
7969 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7973 mname [pos++] = '/';
7976 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7982 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7987 imap = find_class_icalls (mname);
7989 mname [typelen] = ':';
7990 mname [typelen + 1] = ':';
7992 mlen = strlen (method->name);
7993 memcpy (mname + typelen + 2, method->name, mlen);
7994 sigstart = mname + typelen + 2 + mlen;
7997 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7998 siglen = strlen (tmpsig);
7999 if (typelen + mlen + siglen + 6 > sizeof (mname))
8002 memcpy (sigstart + 1, tmpsig, siglen);
8003 sigstart [siglen + 1] = ')';
8004 sigstart [siglen + 2] = 0;
8007 mono_loader_lock ();
8009 res = g_hash_table_lookup (icall_hash, mname);
8011 mono_loader_unlock ();
8014 /* try without signature */
8016 res = g_hash_table_lookup (icall_hash, mname);
8018 mono_loader_unlock ();
8022 /* it wasn't found in the static call tables */
8024 mono_loader_unlock ();
8027 res = find_method_icall (imap, sigstart - mlen);
8029 mono_loader_unlock ();
8032 /* try _with_ signature */
8034 res = find_method_icall (imap, sigstart - mlen);
8036 mono_loader_unlock ();
8040 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8041 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8042 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8043 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8044 g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
8045 g_print ("If you see other errors or faults after this message they are probably related\n");
8046 g_print ("and you need to fix your mono install first.\n");
8048 mono_loader_unlock ();
8054 type_from_typename (char *typename)
8056 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8058 if (!strcmp (typename, "int"))
8059 klass = mono_defaults.int_class;
8060 else if (!strcmp (typename, "ptr"))
8061 klass = mono_defaults.int_class;
8062 else if (!strcmp (typename, "void"))
8063 klass = mono_defaults.void_class;
8064 else if (!strcmp (typename, "int32"))
8065 klass = mono_defaults.int32_class;
8066 else if (!strcmp (typename, "uint32"))
8067 klass = mono_defaults.uint32_class;
8068 else if (!strcmp (typename, "int8"))
8069 klass = mono_defaults.sbyte_class;
8070 else if (!strcmp (typename, "uint8"))
8071 klass = mono_defaults.byte_class;
8072 else if (!strcmp (typename, "int16"))
8073 klass = mono_defaults.int16_class;
8074 else if (!strcmp (typename, "uint16"))
8075 klass = mono_defaults.uint16_class;
8076 else if (!strcmp (typename, "long"))
8077 klass = mono_defaults.int64_class;
8078 else if (!strcmp (typename, "ulong"))
8079 klass = mono_defaults.uint64_class;
8080 else if (!strcmp (typename, "float"))
8081 klass = mono_defaults.single_class;
8082 else if (!strcmp (typename, "double"))
8083 klass = mono_defaults.double_class;
8084 else if (!strcmp (typename, "object"))
8085 klass = mono_defaults.object_class;
8086 else if (!strcmp (typename, "obj"))
8087 klass = mono_defaults.object_class;
8088 else if (!strcmp (typename, "string"))
8089 klass = mono_defaults.string_class;
8090 else if (!strcmp (typename, "bool"))
8091 klass = mono_defaults.boolean_class;
8092 else if (!strcmp (typename, "boolean"))
8093 klass = mono_defaults.boolean_class;
8095 g_error ("%s", typename);
8096 g_assert_not_reached ();
8098 return &klass->byval_arg;
8101 MonoMethodSignature*
8102 mono_create_icall_signature (const char *sigstr)
8107 MonoMethodSignature *res;
8109 mono_loader_lock ();
8110 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8112 mono_loader_unlock ();
8116 parts = g_strsplit (sigstr, " ", 256);
8125 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8128 #ifdef PLATFORM_WIN32
8130 * Under windows, the default pinvoke calling convention is STDCALL but
8133 res->call_convention = MONO_CALL_C;
8136 res->ret = type_from_typename (parts [0]);
8137 for (i = 1; i < len; ++i) {
8138 res->params [i - 1] = type_from_typename (parts [i]);
8143 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8145 mono_loader_unlock ();
8151 mono_find_jit_icall_by_name (const char *name)
8153 MonoJitICallInfo *info;
8154 g_assert (jit_icall_hash_name);
8156 mono_loader_lock ();
8157 info = g_hash_table_lookup (jit_icall_hash_name, name);
8158 mono_loader_unlock ();
8163 mono_find_jit_icall_by_addr (gconstpointer addr)
8165 MonoJitICallInfo *info;
8166 g_assert (jit_icall_hash_addr);
8168 mono_loader_lock ();
8169 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8170 mono_loader_unlock ();
8176 * mono_get_jit_icall_info:
8178 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8179 * caller should access it while holding the loader lock.
8182 mono_get_jit_icall_info (void)
8184 return jit_icall_hash_name;
8188 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8190 mono_loader_lock ();
8191 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8192 mono_loader_unlock ();
8196 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8198 MonoJitICallInfo *info;
8203 mono_loader_lock ();
8205 if (!jit_icall_hash_name) {
8206 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8207 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8210 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8211 g_warning ("jit icall already defined \"%s\"\n", name);
8212 g_assert_not_reached ();
8215 info = g_new0 (MonoJitICallInfo, 1);
8222 info->wrapper = func;
8224 info->wrapper = NULL;
8227 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8228 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8230 mono_loader_unlock ();