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, MonoType *type)
1593 gboolean found = FALSE;
1600 klass = handle->parent;
1602 klass = mono_class_from_mono_type (type);
1604 /* Check that the field belongs to the class */
1605 for (k = klass; k; k = k->parent) {
1606 if (k == handle->parent) {
1613 /* The managed code will throw the exception */
1617 return mono_field_get_object (mono_domain_get (), klass, handle);
1620 static MonoReflectionField*
1621 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1623 MONO_ARCH_SAVE_REGS;
1627 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1631 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1633 MonoType *type = field->field->type;
1635 return type_array_from_modifiers (field->field->parent->image, type, optional);
1639 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1641 MonoDomain *domain = mono_domain_get ();
1642 MonoMethodSignature* sig;
1643 MONO_ARCH_SAVE_REGS;
1645 sig = mono_method_signature (method);
1647 g_assert (mono_loader_get_last_error ());
1648 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1651 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1652 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1653 info->attrs = method->flags;
1654 info->implattrs = method->iflags;
1655 if (sig->call_convention == MONO_CALL_DEFAULT)
1656 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1658 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1663 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1667 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1669 MonoDomain *domain = mono_domain_get ();
1671 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1674 static MonoReflectionMarshal*
1675 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1677 MonoDomain *domain = mono_domain_get ();
1678 MonoReflectionMarshal* res = NULL;
1679 MonoMarshalSpec **mspecs;
1682 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1683 mono_method_get_marshal_info (method, mspecs);
1686 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1688 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1690 mono_metadata_free_marshal_spec (mspecs [i]);
1697 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1699 return field->field->offset - sizeof (MonoObject);
1702 static MonoReflectionType*
1703 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1706 MONO_ARCH_SAVE_REGS;
1708 parent = declaring? field->field->parent: field->klass;
1710 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1714 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1717 MonoClassField *cf = field->field;
1721 MonoDomain *domain = mono_object_domain (field);
1723 gboolean is_static = FALSE;
1724 gboolean is_ref = FALSE;
1726 MONO_ARCH_SAVE_REGS;
1728 if (field->klass->image->assembly->ref_only)
1729 mono_raise_exception (mono_get_exception_invalid_operation (
1730 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1732 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1733 mono_security_core_clr_ensure_reflection_access_field (cf);
1735 mono_class_init (field->klass);
1737 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1740 if (obj && !is_static) {
1741 /* Check that the field belongs to the object */
1742 gboolean found = FALSE;
1745 for (k = obj->vtable->klass; k; k = k->parent) {
1746 if (k == cf->parent) {
1753 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);
1754 MonoException *ex = mono_get_exception_argument (NULL, msg);
1756 mono_raise_exception (ex);
1760 t = mono_type_get_underlying_type (cf->type);
1762 case MONO_TYPE_STRING:
1763 case MONO_TYPE_OBJECT:
1764 case MONO_TYPE_CLASS:
1765 case MONO_TYPE_ARRAY:
1766 case MONO_TYPE_SZARRAY:
1771 case MONO_TYPE_BOOLEAN:
1774 case MONO_TYPE_CHAR:
1783 case MONO_TYPE_VALUETYPE:
1786 case MONO_TYPE_GENERICINST:
1787 if (mono_type_generic_inst_is_valuetype (t)) {
1794 g_error ("type 0x%x not handled in "
1795 "ves_icall_Monofield_GetValue", t->type);
1801 vtable = mono_class_vtable (domain, cf->parent);
1802 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1803 mono_runtime_class_init (vtable);
1808 mono_field_static_get_value (vtable, cf, &o);
1810 mono_field_get_value (obj, cf, &o);
1815 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1816 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1819 /* Convert the Nullable structure into a boxed vtype */
1821 buf = (guint8*)vtable->data + cf->offset;
1823 buf = (guint8*)obj + cf->offset;
1825 return mono_nullable_box (buf, nklass);
1828 /* boxed value type */
1829 klass = mono_class_from_mono_type (cf->type);
1830 o = mono_object_new (domain, klass);
1831 v = ((gchar *) o) + sizeof (MonoObject);
1833 mono_field_static_get_value (vtable, cf, v);
1835 mono_field_get_value (obj, cf, v);
1842 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1844 MonoClassField *cf = field->field;
1847 MONO_ARCH_SAVE_REGS;
1849 if (field->klass->image->assembly->ref_only)
1850 mono_raise_exception (mono_get_exception_invalid_operation (
1851 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1853 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1854 mono_security_core_clr_ensure_reflection_access_field (cf);
1856 v = (gchar *) value;
1857 if (!cf->type->byref) {
1858 switch (cf->type->type) {
1861 case MONO_TYPE_BOOLEAN:
1864 case MONO_TYPE_CHAR:
1873 case MONO_TYPE_VALUETYPE:
1875 v += sizeof (MonoObject);
1877 case MONO_TYPE_STRING:
1878 case MONO_TYPE_OBJECT:
1879 case MONO_TYPE_CLASS:
1880 case MONO_TYPE_ARRAY:
1881 case MONO_TYPE_SZARRAY:
1884 case MONO_TYPE_GENERICINST: {
1885 MonoGenericClass *gclass = cf->type->data.generic_class;
1886 g_assert (!gclass->context.class_inst->is_open);
1888 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1889 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1890 MonoObject *nullable;
1893 * Convert the boxed vtype into a Nullable structure.
1894 * This is complicated by the fact that Nullables have
1895 * a variable structure.
1897 nullable = mono_object_new (mono_domain_get (), nklass);
1899 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1901 v = mono_object_unbox (nullable);
1904 if (gclass->container_class->valuetype && (v != NULL))
1905 v += sizeof (MonoObject);
1909 g_error ("type 0x%x not handled in "
1910 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1915 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1916 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1917 if (!vtable->initialized)
1918 mono_runtime_class_init (vtable);
1919 mono_field_static_set_value (vtable, cf, v);
1921 mono_field_set_value (obj, cf, v);
1926 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1928 MonoObject *o = NULL;
1929 MonoClassField *field = this->field;
1931 MonoDomain *domain = mono_object_domain (this);
1933 MonoTypeEnum def_type;
1934 const char *def_value;
1936 MONO_ARCH_SAVE_REGS;
1938 mono_class_init (field->parent);
1940 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1941 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1943 if (field->parent->image->dynamic) {
1945 g_assert_not_reached ();
1948 def_value = mono_class_get_field_default_value (field, &def_type);
1953 case MONO_TYPE_BOOLEAN:
1956 case MONO_TYPE_CHAR:
1964 case MONO_TYPE_R8: {
1967 /* boxed value type */
1968 t = g_new0 (MonoType, 1);
1970 klass = mono_class_from_mono_type (t);
1972 o = mono_object_new (domain, klass);
1973 v = ((gchar *) o) + sizeof (MonoObject);
1974 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1977 case MONO_TYPE_STRING:
1978 case MONO_TYPE_CLASS:
1979 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1982 g_assert_not_reached ();
1988 static MonoReflectionType*
1989 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1991 MonoMethod *method = rmethod->method.method;
1993 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1996 /* From MonoProperty.cs */
1998 PInfo_Attributes = 1,
1999 PInfo_GetMethod = 1 << 1,
2000 PInfo_SetMethod = 1 << 2,
2001 PInfo_ReflectedType = 1 << 3,
2002 PInfo_DeclaringType = 1 << 4,
2007 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2009 MonoDomain *domain = mono_object_domain (property);
2011 MONO_ARCH_SAVE_REGS;
2013 if ((req_info & PInfo_ReflectedType) != 0)
2014 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2015 else if ((req_info & PInfo_DeclaringType) != 0)
2016 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2018 if ((req_info & PInfo_Name) != 0)
2019 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2021 if ((req_info & PInfo_Attributes) != 0)
2022 info->attrs = property->property->attrs;
2024 if ((req_info & PInfo_GetMethod) != 0)
2025 MONO_STRUCT_SETREF (info, get, property->property->get ?
2026 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2028 if ((req_info & PInfo_SetMethod) != 0)
2029 MONO_STRUCT_SETREF (info, set, property->property->set ?
2030 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2032 * There may be other methods defined for properties, though, it seems they are not exposed
2033 * in the reflection API
2038 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2040 MonoDomain *domain = mono_object_domain (event);
2042 MONO_ARCH_SAVE_REGS;
2044 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2045 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2047 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2048 info->attrs = event->event->attrs;
2049 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2050 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2051 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2053 if (event->event->other) {
2055 while (event->event->other [n])
2057 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2059 for (i = 0; i < n; i++)
2060 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2065 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2067 MonoDomain *domain = mono_object_domain (type);
2069 GPtrArray *ifaces = NULL;
2071 MonoClass *class = mono_class_from_mono_type (type->type);
2074 MonoGenericContext *context = NULL;
2076 MONO_ARCH_SAVE_REGS;
2078 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2079 context = mono_class_get_context (class);
2080 class = class->generic_class->container_class;
2083 mono_class_setup_vtable (class);
2085 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2087 for (parent = class; parent; parent = parent->parent) {
2088 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2090 for (i = 0; i < tmp_ifaces->len; ++i) {
2091 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2093 if (mono_bitset_test (slots, ic->interface_id))
2096 mono_bitset_set (slots, ic->interface_id);
2098 ifaces = g_ptr_array_new ();
2099 g_ptr_array_add (ifaces, ic);
2101 g_ptr_array_free (tmp_ifaces, TRUE);
2104 mono_bitset_free (slots);
2107 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2109 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2110 for (i = 0; i < ifaces->len; ++i) {
2111 MonoClass *ic = g_ptr_array_index (ifaces, i);
2112 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2113 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2114 inflated = ret = mono_class_inflate_generic_type (ret, context);
2116 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2118 mono_metadata_free_type (inflated);
2120 g_ptr_array_free (ifaces, TRUE);
2126 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2128 MonoClass *class = mono_class_from_mono_type (type->type);
2129 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2130 MonoReflectionMethod *member;
2133 int i = 0, len, ioffset;
2136 MONO_ARCH_SAVE_REGS;
2138 mono_class_setup_vtable (class);
2140 /* type doesn't implement iface: the exception is thrown in managed code */
2141 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2144 len = mono_class_num_methods (iclass);
2145 ioffset = mono_class_interface_offset (class, iclass);
2146 domain = mono_object_domain (type);
2147 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2148 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2151 while ((method = mono_class_get_methods (iclass, &iter))) {
2152 member = mono_method_get_object (domain, method, iclass);
2153 mono_array_setref (*methods, i, member);
2154 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2155 mono_array_setref (*targets, i, member);
2162 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2164 MonoClass *klass = mono_class_from_mono_type (type->type);
2166 if (klass->image->dynamic) {
2167 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2168 *packing = tb->packing_size;
2169 *size = tb->class_size;
2171 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2175 static MonoReflectionType*
2176 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2180 MONO_ARCH_SAVE_REGS;
2182 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2183 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2185 class = mono_class_from_mono_type (type->type);
2187 // GetElementType should only return a type for:
2188 // Array Pointer PassedByRef
2189 if (type->type->byref)
2190 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2191 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2192 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2193 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2194 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2199 static MonoReflectionType*
2200 ves_icall_get_type_parent (MonoReflectionType *type)
2202 MonoClass *class = mono_class_from_mono_type (type->type);
2204 MONO_ARCH_SAVE_REGS;
2206 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2210 ves_icall_type_ispointer (MonoReflectionType *type)
2212 MONO_ARCH_SAVE_REGS;
2214 return type->type->type == MONO_TYPE_PTR;
2218 ves_icall_type_isprimitive (MonoReflectionType *type)
2220 MONO_ARCH_SAVE_REGS;
2222 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)));
2226 ves_icall_type_isbyref (MonoReflectionType *type)
2228 MONO_ARCH_SAVE_REGS;
2230 return type->type->byref;
2234 ves_icall_type_iscomobject (MonoReflectionType *type)
2236 MonoClass *klass = mono_class_from_mono_type (type->type);
2237 MONO_ARCH_SAVE_REGS;
2239 return (klass && klass->is_com_object);
2242 static MonoReflectionModule*
2243 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2245 MonoClass *class = mono_class_from_mono_type (type->type);
2247 MONO_ARCH_SAVE_REGS;
2249 return mono_module_get_object (mono_object_domain (type), class->image);
2252 static MonoReflectionAssembly*
2253 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2255 MonoDomain *domain = mono_domain_get ();
2256 MonoClass *class = mono_class_from_mono_type (type->type);
2258 MONO_ARCH_SAVE_REGS;
2260 return mono_assembly_get_object (domain, class->image->assembly);
2263 static MonoReflectionType*
2264 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2266 MonoDomain *domain = mono_domain_get ();
2269 MONO_ARCH_SAVE_REGS;
2271 if (type->type->byref)
2273 if (type->type->type == MONO_TYPE_VAR)
2274 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2275 else if (type->type->type == MONO_TYPE_MVAR)
2276 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2278 class = mono_class_from_mono_type (type->type)->nested_in;
2280 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2283 static MonoReflectionType*
2284 ves_icall_MonoType_get_UnderlyingSystemType (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 (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2292 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2293 else if (class->element_class)
2294 return mono_type_get_object (domain, &class->element_class->byval_arg);
2300 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2302 MonoDomain *domain = mono_domain_get ();
2303 MonoClass *class = mono_class_from_mono_type (type->type);
2305 MONO_ARCH_SAVE_REGS;
2307 if (type->type->byref) {
2308 char *n = g_strdup_printf ("%s&", class->name);
2309 MonoString *res = mono_string_new (domain, n);
2315 return mono_string_new (domain, class->name);
2320 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2322 MonoDomain *domain = mono_domain_get ();
2323 MonoClass *class = mono_class_from_mono_type (type->type);
2325 MONO_ARCH_SAVE_REGS;
2327 while (class->nested_in)
2328 class = class->nested_in;
2330 if (class->name_space [0] == '\0')
2333 return mono_string_new (domain, class->name_space);
2337 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2341 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2342 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2344 class = mono_class_from_mono_type (type->type);
2349 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2352 MonoClass *klass, *pklass;
2353 MonoDomain *domain = mono_object_domain (type);
2354 MonoVTable *array_vtable = mono_class_vtable (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1));
2356 MONO_ARCH_SAVE_REGS;
2358 klass = mono_class_from_mono_type (type->type);
2360 if (klass->generic_container) {
2361 MonoGenericContainer *container = klass->generic_container;
2362 res = mono_array_new_specific (array_vtable, container->type_argc);
2363 for (i = 0; i < container->type_argc; ++i) {
2364 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2365 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2367 } else if (klass->generic_class) {
2368 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2369 res = mono_array_new_specific (array_vtable, inst->type_argc);
2370 for (i = 0; i < inst->type_argc; ++i)
2371 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2373 res = mono_array_new_specific (array_vtable, 0);
2379 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2382 MONO_ARCH_SAVE_REGS;
2384 if (!IS_MONOTYPE (type))
2387 if (type->type->byref)
2390 klass = mono_class_from_mono_type (type->type);
2392 return klass->generic_container != NULL;
2395 static MonoReflectionType*
2396 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2399 MONO_ARCH_SAVE_REGS;
2401 if (type->type->byref)
2404 klass = mono_class_from_mono_type (type->type);
2405 if (klass->generic_container) {
2406 return type; /* check this one */
2408 if (klass->generic_class) {
2409 MonoClass *generic_class = klass->generic_class->container_class;
2411 if (generic_class->wastypebuilder && generic_class->reflection_info)
2412 return generic_class->reflection_info;
2414 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2419 static MonoReflectionType*
2420 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2422 MonoType *geninst, **types;
2425 MONO_ARCH_SAVE_REGS;
2427 count = mono_array_length (type_array);
2428 types = g_new0 (MonoType *, count);
2430 for (i = 0; i < count; i++) {
2431 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2432 types [i] = t->type;
2435 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2440 return mono_type_get_object (mono_object_domain (type), geninst);
2444 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2447 MONO_ARCH_SAVE_REGS;
2449 if (type->type->byref)
2452 klass = mono_class_from_mono_type (type->type);
2453 return klass->generic_class != NULL;
2457 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2460 MONO_ARCH_SAVE_REGS;
2462 if (!IS_MONOTYPE (type))
2465 if (type->type->byref)
2468 klass = mono_class_from_mono_type (type->type);
2469 return klass->generic_class != NULL || klass->generic_container != NULL;
2473 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2475 MONO_ARCH_SAVE_REGS;
2477 if (!IS_MONOTYPE (type))
2480 if (is_generic_parameter (type->type))
2481 return mono_type_get_generic_param_num (type->type);
2485 static GenericParameterAttributes
2486 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2488 MONO_ARCH_SAVE_REGS;
2490 g_assert (IS_MONOTYPE (type));
2491 g_assert (is_generic_parameter (type->type));
2492 return mono_generic_param_info (type->type->data.generic_param)->flags;
2496 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2498 MonoGenericParamInfo *param_info;
2504 MONO_ARCH_SAVE_REGS;
2506 g_assert (IS_MONOTYPE (type));
2508 domain = mono_object_domain (type);
2509 param_info = mono_generic_param_info (type->type->data.generic_param);
2510 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2513 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2514 for (i = 0; i < count; i++)
2515 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2522 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2524 MONO_ARCH_SAVE_REGS;
2525 return is_generic_parameter (type->type);
2529 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2531 MONO_ARCH_SAVE_REGS;
2532 return is_generic_parameter (tb->type.type);
2536 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2537 MonoReflectionType *t)
2539 enumtype->type = t->type;
2542 static MonoReflectionType*
2543 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2545 MonoDynamicGenericClass *gclass;
2546 MonoReflectionType *parent = NULL, *res;
2552 MONO_ARCH_SAVE_REGS;
2554 g_assert (type->type.type->data.generic_class->is_dynamic);
2555 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2557 domain = mono_object_domain (type);
2558 klass = mono_class_from_mono_type (type->generic_type->type.type);
2560 if (!klass->generic_class && !klass->generic_container)
2563 parent = monotype_cast (type->generic_type->parent);
2565 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2568 inflated = mono_class_inflate_generic_type (
2569 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2571 res = mono_type_get_object (domain, inflated);
2572 mono_metadata_free_type (inflated);
2577 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2579 static MonoClass *System_Reflection_MonoGenericClass;
2580 MonoGenericClass *gclass;
2581 MonoReflectionTypeBuilder *tb = NULL;
2582 MonoClass *klass = NULL;
2587 MONO_ARCH_SAVE_REGS;
2589 if (!System_Reflection_MonoGenericClass) {
2590 System_Reflection_MonoGenericClass = mono_class_from_name (
2591 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2592 g_assert (System_Reflection_MonoGenericClass);
2595 domain = mono_object_domain (type);
2597 gclass = type->type.type->data.generic_class;
2598 g_assert (gclass->is_dynamic);
2600 tb = type->generic_type;
2601 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2603 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2605 for (i = 0; i < icount; i++) {
2606 MonoReflectionType *iface;
2610 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2613 it = &klass->interfaces [i]->byval_arg;
2615 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2617 iface = mono_type_get_object (domain, it);
2618 mono_array_setref (res, i, iface);
2619 mono_metadata_free_type (it);
2625 static MonoReflectionMethod*
2626 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2627 MonoReflectionMethod* generic)
2629 MonoGenericClass *gclass;
2630 MonoDynamicGenericClass *dgclass;
2634 MONO_ARCH_SAVE_REGS;
2636 gclass = type->type.type->data.generic_class;
2637 g_assert (gclass->is_dynamic);
2639 dgclass = (MonoDynamicGenericClass *) gclass;
2641 domain = mono_object_domain (type);
2643 for (i = 0; i < dgclass->count_methods; i++)
2644 if (generic->method->token == dgclass->methods [i]->token)
2645 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2650 static MonoReflectionMethod*
2651 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2652 MonoReflectionMethod* generic)
2654 MonoGenericClass *gclass;
2655 MonoDynamicGenericClass *dgclass;
2659 MONO_ARCH_SAVE_REGS;
2661 gclass = type->type.type->data.generic_class;
2662 g_assert (gclass->is_dynamic);
2664 dgclass = (MonoDynamicGenericClass *) gclass;
2666 domain = mono_object_domain (type);
2668 for (i = 0; i < dgclass->count_ctors; i++)
2669 if (generic->method->token == dgclass->ctors [i]->token)
2670 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2676 static MonoReflectionField*
2677 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2678 MonoString* generic_name)
2680 MonoGenericClass *gclass;
2681 MonoDynamicGenericClass *dgclass;
2683 MonoClass *refclass;
2684 char *utf8_name = mono_string_to_utf8 (generic_name);
2687 MONO_ARCH_SAVE_REGS;
2689 gclass = type->type.type->data.generic_class;
2690 g_assert (gclass->is_dynamic);
2692 dgclass = (MonoDynamicGenericClass *) gclass;
2694 refclass = mono_class_from_mono_type (type->type.type);
2696 domain = mono_object_domain (type);
2698 for (i = 0; i < dgclass->count_fields; i++)
2699 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2701 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2710 static MonoReflectionMethod*
2711 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2712 MonoReflectionMethod* generic)
2719 MONO_ARCH_SAVE_REGS;
2721 domain = ((MonoObject *)type)->vtable->domain;
2723 klass = mono_class_from_mono_type (type->type);
2726 while ((method = mono_class_get_methods (klass, &iter))) {
2727 if (method->token == generic->method->token)
2728 return mono_method_get_object (domain, method, klass);
2735 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2736 MonoReflectionType *reflected_type)
2738 MonoGenericClass *gclass;
2739 MonoDynamicGenericClass *dgclass;
2741 MonoClass *refclass;
2745 MONO_ARCH_SAVE_REGS;
2747 gclass = type->type.type->data.generic_class;
2748 g_assert (gclass->is_dynamic);
2749 dgclass = (MonoDynamicGenericClass *) gclass;
2751 refclass = mono_class_from_mono_type (reflected_type->type);
2753 domain = mono_object_domain (type);
2754 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2756 for (i = 0; i < dgclass->count_methods; i++)
2757 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2763 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2764 MonoReflectionType *reflected_type)
2766 static MonoClass *System_Reflection_ConstructorInfo;
2767 MonoGenericClass *gclass;
2768 MonoDynamicGenericClass *dgclass;
2770 MonoClass *refclass;
2774 MONO_ARCH_SAVE_REGS;
2776 if (!System_Reflection_ConstructorInfo)
2777 System_Reflection_ConstructorInfo = mono_class_from_name (
2778 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2780 gclass = type->type.type->data.generic_class;
2781 g_assert (gclass->is_dynamic);
2782 dgclass = (MonoDynamicGenericClass *) gclass;
2784 refclass = mono_class_from_mono_type (reflected_type->type);
2786 domain = mono_object_domain (type);
2787 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2789 for (i = 0; i < dgclass->count_ctors; i++)
2790 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2796 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2797 MonoReflectionType *reflected_type)
2799 MonoGenericClass *gclass;
2800 MonoDynamicGenericClass *dgclass;
2802 MonoClass *refclass;
2806 MONO_ARCH_SAVE_REGS;
2808 gclass = type->type.type->data.generic_class;
2809 g_assert (gclass->is_dynamic);
2810 dgclass = (MonoDynamicGenericClass *) gclass;
2812 refclass = mono_class_from_mono_type (reflected_type->type);
2814 domain = mono_object_domain (type);
2815 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2817 for (i = 0; i < dgclass->count_fields; i++)
2818 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2824 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2825 MonoReflectionType *reflected_type)
2827 static MonoClass *System_Reflection_PropertyInfo;
2828 MonoGenericClass *gclass;
2829 MonoDynamicGenericClass *dgclass;
2831 MonoClass *refclass;
2835 MONO_ARCH_SAVE_REGS;
2837 if (!System_Reflection_PropertyInfo)
2838 System_Reflection_PropertyInfo = mono_class_from_name (
2839 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2841 gclass = type->type.type->data.generic_class;
2842 g_assert (gclass->is_dynamic);
2843 dgclass = (MonoDynamicGenericClass *) gclass;
2845 refclass = mono_class_from_mono_type (reflected_type->type);
2847 domain = mono_object_domain (type);
2848 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2850 for (i = 0; i < dgclass->count_properties; i++)
2851 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2857 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2858 MonoReflectionType *reflected_type)
2860 static MonoClass *System_Reflection_EventInfo;
2861 MonoGenericClass *gclass;
2862 MonoDynamicGenericClass *dgclass;
2864 MonoClass *refclass;
2868 MONO_ARCH_SAVE_REGS;
2870 if (!System_Reflection_EventInfo)
2871 System_Reflection_EventInfo = mono_class_from_name (
2872 mono_defaults.corlib, "System.Reflection", "EventInfo");
2874 gclass = type->type.type->data.generic_class;
2875 g_assert (gclass->is_dynamic);
2876 dgclass = (MonoDynamicGenericClass *) gclass;
2878 refclass = mono_class_from_mono_type (reflected_type->type);
2880 domain = mono_object_domain (type);
2881 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2883 for (i = 0; i < dgclass->count_events; i++)
2884 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2889 static MonoReflectionType*
2890 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2891 MonoReflectionType *target)
2895 MonoReflectionType *res;
2897 MONO_ARCH_SAVE_REGS;
2899 gklass = mono_class_from_mono_type (type->type.type);
2900 res_type = mono_class_inflate_generic_type (mono_reflection_type_get_handle (target), mono_class_get_context (gklass));
2901 res = mono_type_get_object (mono_object_domain (type), res_type);
2902 mono_metadata_free_type (res_type);
2906 static MonoReflectionMethod *
2907 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2910 MonoType *type = ref_type->type;
2912 MONO_ARCH_SAVE_REGS;
2914 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2915 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2916 if (type->type == MONO_TYPE_VAR)
2919 method = mono_type_get_generic_param_owner (type)->owner.method;
2921 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2924 static MonoReflectionDllImportAttribute*
2925 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2927 static MonoClass *DllImportAttributeClass = NULL;
2928 MonoDomain *domain = mono_domain_get ();
2929 MonoReflectionDllImportAttribute *attr;
2930 MonoImage *image = method->klass->image;
2931 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2932 MonoTableInfo *tables = image->tables;
2933 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2934 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2935 guint32 im_cols [MONO_IMPLMAP_SIZE];
2936 guint32 scope_token;
2937 const char *import = NULL;
2938 const char *scope = NULL;
2941 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2944 if (!DllImportAttributeClass) {
2945 DllImportAttributeClass =
2946 mono_class_from_name (mono_defaults.corlib,
2947 "System.Runtime.InteropServices", "DllImportAttribute");
2948 g_assert (DllImportAttributeClass);
2951 if (method->klass->image->dynamic) {
2952 MonoReflectionMethodAux *method_aux =
2953 g_hash_table_lookup (
2954 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2956 import = method_aux->dllentry;
2957 scope = method_aux->dll;
2961 if (piinfo->implmap_idx) {
2962 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2964 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2965 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2966 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2967 scope = mono_metadata_string_heap (image, scope_token);
2970 flags = piinfo->piflags;
2972 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2974 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2975 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2976 attr->call_conv = (flags & 0x700) >> 8;
2977 attr->charset = ((flags & 0x6) >> 1) + 1;
2978 if (attr->charset == 1)
2980 attr->exact_spelling = (flags & 0x1) != 0;
2981 attr->set_last_error = (flags & 0x40) != 0;
2982 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2983 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2984 attr->preserve_sig = FALSE;
2989 static MonoReflectionMethod *
2990 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2992 MonoMethodInflated *imethod;
2995 MONO_ARCH_SAVE_REGS;
2997 if (method->method->is_generic)
3000 if (!method->method->is_inflated)
3003 imethod = (MonoMethodInflated *) method->method;
3005 result = imethod->declaring;
3006 /* Not a generic method. */
3007 if (!result->is_generic)
3010 if (method->method->klass->image->dynamic) {
3011 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3012 MonoReflectionMethod *res;
3015 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3016 * the dynamic case as well ?
3018 mono_loader_lock ();
3019 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3020 mono_loader_unlock ();
3026 if (imethod->context.class_inst) {
3027 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3028 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
3031 return mono_method_get_object (mono_object_domain (method), result, NULL);
3035 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3037 MONO_ARCH_SAVE_REGS;
3039 return mono_method_signature (method->method)->generic_param_count != 0;
3043 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3045 MONO_ARCH_SAVE_REGS;
3047 return method->method->is_generic;
3051 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3056 MONO_ARCH_SAVE_REGS;
3058 domain = mono_object_domain (method);
3060 if (method->method->is_inflated) {
3061 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3064 count = inst->type_argc;
3065 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3067 for (i = 0; i < count; i++)
3068 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
3074 count = mono_method_signature (method->method)->generic_param_count;
3075 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3077 for (i = 0; i < count; i++) {
3078 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3079 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3080 MonoClass *pklass = mono_class_from_generic_parameter (
3081 param, method->method->klass->image, TRUE);
3082 mono_array_setref (res, i,
3083 mono_type_get_object (domain, &pklass->byval_arg));
3090 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3093 * Invoke from reflection is supposed to always be a virtual call (the API
3094 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3095 * greater flexibility.
3097 MonoMethod *m = method->method;
3101 MONO_ARCH_SAVE_REGS;
3105 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3106 mono_security_core_clr_ensure_reflection_access_method (m);
3108 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3110 if (!mono_object_isinst (this, m->klass)) {
3111 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
3114 m = mono_object_get_virtual_method (this, m);
3115 /* must pass the pointer to the value for valuetype methods */
3116 if (m->klass->valuetype)
3117 obj = mono_object_unbox (this);
3118 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3119 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3124 pcount = params? mono_array_length (params): 0;
3125 if (pcount != mono_method_signature (m)->param_count) {
3126 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3130 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3131 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."));
3135 if (m->klass->image->assembly->ref_only) {
3136 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."));
3140 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3142 mono_array_size_t *lengths;
3143 mono_array_size_t *lower_bounds;
3144 pcount = mono_array_length (params);
3145 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3146 for (i = 0; i < pcount; ++i)
3147 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3149 if (m->klass->rank == pcount) {
3150 /* Only lengths provided. */
3151 lower_bounds = NULL;
3153 g_assert (pcount == (m->klass->rank * 2));
3154 /* lower bounds are first. */
3155 lower_bounds = lengths;
3156 lengths += m->klass->rank;
3159 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3161 return mono_runtime_invoke_array (m, obj, params, NULL);
3165 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3167 MonoDomain *domain = mono_object_domain (method);
3168 MonoMethod *m = method->method;
3169 MonoMethodSignature *sig = mono_method_signature (m);
3170 MonoArray *out_args;
3172 int i, j, outarg_count = 0;
3174 MONO_ARCH_SAVE_REGS;
3176 if (m->klass == mono_defaults.object_class) {
3178 if (!strcmp (m->name, "FieldGetter")) {
3179 MonoClass *k = this->vtable->klass;
3183 /* If this is a proxy, then it must be a CBO */
3184 if (k == mono_defaults.transparent_proxy_class) {
3185 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3186 this = tp->rp->unwrapped_server;
3188 k = this->vtable->klass;
3191 name = mono_array_get (params, MonoString *, 1);
3192 str = mono_string_to_utf8 (name);
3195 MonoClassField* field = mono_class_get_field_from_name (k, str);
3197 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3198 if (field_klass->valuetype)
3199 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3201 result = *((gpointer *)((char *)this + field->offset));
3203 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3204 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3205 mono_array_setref (out_args, 0, result);
3213 g_assert_not_reached ();
3215 } else if (!strcmp (m->name, "FieldSetter")) {
3216 MonoClass *k = this->vtable->klass;
3222 /* If this is a proxy, then it must be a CBO */
3223 if (k == mono_defaults.transparent_proxy_class) {
3224 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3225 this = tp->rp->unwrapped_server;
3227 k = this->vtable->klass;
3230 name = mono_array_get (params, MonoString *, 1);
3231 str = mono_string_to_utf8 (name);
3234 MonoClassField* field = mono_class_get_field_from_name (k, str);
3236 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3237 MonoObject *val = mono_array_get (params, gpointer, 2);
3239 if (field_klass->valuetype) {
3240 size = mono_type_size (field->type, &align);
3242 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3244 memcpy ((char *)this + field->offset,
3245 ((char *)val) + sizeof (MonoObject), size);
3247 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3250 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3251 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3261 g_assert_not_reached ();
3266 for (i = 0; i < mono_array_length (params); i++) {
3267 if (sig->params [i]->byref)
3271 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3273 /* handle constructors only for objects already allocated */
3274 if (!strcmp (method->method->name, ".ctor"))
3277 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3278 g_assert (!method->method->klass->valuetype);
3279 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3281 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3282 if (sig->params [i]->byref) {
3284 arg = mono_array_get (params, gpointer, i);
3285 mono_array_setref (out_args, j, arg);
3290 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3296 read_enum_value (char *mem, int type)
3300 return *(guint8*)mem;
3302 return *(gint8*)mem;
3304 return *(guint16*)mem;
3306 return *(gint16*)mem;
3308 return *(guint32*)mem;
3310 return *(gint32*)mem;
3312 return *(guint64*)mem;
3314 return *(gint64*)mem;
3316 g_assert_not_reached ();
3322 write_enum_value (char *mem, int type, guint64 value)
3326 case MONO_TYPE_I1: {
3327 guint8 *p = (guint8*)mem;
3332 case MONO_TYPE_I2: {
3333 guint16 *p = (void*)mem;
3338 case MONO_TYPE_I4: {
3339 guint32 *p = (void*)mem;
3344 case MONO_TYPE_I8: {
3345 guint64 *p = (void*)mem;
3350 g_assert_not_reached ();
3356 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3359 MonoClass *enumc, *objc;
3363 MONO_ARCH_SAVE_REGS;
3365 MONO_CHECK_ARG_NULL (enumType);
3366 MONO_CHECK_ARG_NULL (value);
3368 domain = mono_object_domain (enumType);
3369 enumc = mono_class_from_mono_type (enumType->type);
3370 objc = value->vtable->klass;
3372 if (!enumc->enumtype)
3373 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3374 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3375 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."));
3377 res = mono_object_new (domain, enumc);
3378 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3379 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3385 ves_icall_System_Enum_get_value (MonoObject *this)
3393 MONO_ARCH_SAVE_REGS;
3398 g_assert (this->vtable->klass->enumtype);
3400 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3401 res = mono_object_new (mono_object_domain (this), enumc);
3402 dst = (char *)res + sizeof (MonoObject);
3403 src = (char *)this + sizeof (MonoObject);
3404 size = mono_class_value_size (enumc, NULL);
3406 memcpy (dst, src, size);
3411 static MonoReflectionType *
3412 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3414 MONO_ARCH_SAVE_REGS;
3416 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3420 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3422 gpointer tdata = (char *)this + sizeof (MonoObject);
3423 gpointer odata = (char *)other + sizeof (MonoObject);
3424 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3425 g_assert (basetype);
3427 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3428 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3429 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3432 return me > other ? 1 : -1; \
3435 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3436 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3437 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3440 return me - other; \
3443 switch (basetype->type) {
3445 COMPARE_ENUM_VALUES (guint8);
3447 COMPARE_ENUM_VALUES (gint8);
3448 case MONO_TYPE_CHAR:
3450 COMPARE_ENUM_VALUES_RANGE (guint16);
3452 COMPARE_ENUM_VALUES (gint16);
3454 COMPARE_ENUM_VALUES (guint32);
3456 COMPARE_ENUM_VALUES (gint32);
3458 COMPARE_ENUM_VALUES (guint64);
3460 COMPARE_ENUM_VALUES (gint64);
3462 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3464 #undef COMPARE_ENUM_VALUES_RANGE
3465 #undef COMPARE_ENUM_VALUES
3470 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3472 gpointer data = (char *)this + sizeof (MonoObject);
3473 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3474 g_assert (basetype);
3476 switch (basetype->type) {
3478 return *((gint8*)data);
3480 return *((guint8*)data);
3481 case MONO_TYPE_CHAR:
3483 return *((guint16*)data);
3486 return *((gint16*)data);
3488 return *((guint32*)data);
3490 return *((gint32*)data);
3492 case MONO_TYPE_I8: {
3493 gint64 value = *((gint64*)data);
3494 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3497 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3503 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3505 MonoDomain *domain = mono_object_domain (type);
3506 MonoClass *enumc = mono_class_from_mono_type (type->type);
3507 guint j = 0, nvalues, crow;
3509 MonoClassField *field;
3511 MONO_ARCH_SAVE_REGS;
3513 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3514 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3515 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3516 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3520 while ((field = mono_class_get_fields (enumc, &iter))) {
3523 MonoTypeEnum def_type;
3525 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3527 if (mono_field_is_deleted (field))
3529 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3531 p = mono_class_get_field_default_value (field, &def_type);
3532 len = mono_metadata_decode_blob_size (p, &p);
3533 switch (mono_class_enum_basetype (enumc)->type) {
3536 mono_array_set (info->values, gchar, j, *p);
3538 case MONO_TYPE_CHAR:
3541 mono_array_set (info->values, gint16, j, read16 (p));
3545 mono_array_set (info->values, gint32, j, read32 (p));
3549 mono_array_set (info->values, gint64, j, read64 (p));
3552 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3559 BFLAGS_IgnoreCase = 1,
3560 BFLAGS_DeclaredOnly = 2,
3561 BFLAGS_Instance = 4,
3563 BFLAGS_Public = 0x10,
3564 BFLAGS_NonPublic = 0x20,
3565 BFLAGS_FlattenHierarchy = 0x40,
3566 BFLAGS_InvokeMethod = 0x100,
3567 BFLAGS_CreateInstance = 0x200,
3568 BFLAGS_GetField = 0x400,
3569 BFLAGS_SetField = 0x800,
3570 BFLAGS_GetProperty = 0x1000,
3571 BFLAGS_SetProperty = 0x2000,
3572 BFLAGS_ExactBinding = 0x10000,
3573 BFLAGS_SuppressChangeType = 0x20000,
3574 BFLAGS_OptionalParamBinding = 0x40000
3577 static MonoReflectionField *
3578 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3581 MonoClass *startklass, *klass;
3583 MonoClassField *field;
3586 int (*compare_func) (const char *s1, const char *s2) = NULL;
3587 domain = ((MonoObject *)type)->vtable->domain;
3588 klass = startklass = mono_class_from_mono_type (type->type);
3590 MONO_ARCH_SAVE_REGS;
3593 mono_raise_exception (mono_get_exception_argument_null ("name"));
3594 if (type->type->byref)
3597 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3600 if (klass->exception_type != MONO_EXCEPTION_NONE)
3601 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3604 while ((field = mono_class_get_fields (klass, &iter))) {
3607 if (field->type == NULL)
3609 if (mono_field_is_deleted (field))
3611 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3612 if (bflags & BFLAGS_Public)
3614 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3615 if (bflags & BFLAGS_NonPublic) {
3622 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3623 if (bflags & BFLAGS_Static)
3624 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3627 if (bflags & BFLAGS_Instance)
3634 utf8_name = mono_string_to_utf8 (name);
3636 if (compare_func (mono_field_get_name (field), utf8_name)) {
3642 return mono_field_get_object (domain, klass, field);
3644 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3651 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3654 MonoClass *startklass, *klass, *refklass;
3659 MonoClassField *field;
3660 MonoPtrArray tmp_array;
3662 MONO_ARCH_SAVE_REGS;
3664 domain = ((MonoObject *)type)->vtable->domain;
3665 if (type->type->byref)
3666 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3667 klass = startklass = mono_class_from_mono_type (type->type);
3668 refklass = mono_class_from_mono_type (reftype->type);
3670 mono_ptr_array_init (tmp_array, 2);
3673 if (klass->exception_type != MONO_EXCEPTION_NONE)
3674 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3677 while ((field = mono_class_get_fields (klass, &iter))) {
3679 if (mono_field_is_deleted (field))
3681 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3682 if (bflags & BFLAGS_Public)
3684 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3685 if (bflags & BFLAGS_NonPublic) {
3692 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3693 if (bflags & BFLAGS_Static)
3694 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3697 if (bflags & BFLAGS_Instance)
3703 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3704 mono_ptr_array_append (tmp_array, member);
3706 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3709 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3711 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3712 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3714 mono_ptr_array_destroy (tmp_array);
3720 method_nonpublic (MonoMethod* method, gboolean start_klass)
3722 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3723 case METHOD_ATTRIBUTE_ASSEM:
3724 return (start_klass || mono_defaults.generic_ilist_class);
3725 case METHOD_ATTRIBUTE_PRIVATE:
3727 case METHOD_ATTRIBUTE_PUBLIC:
3735 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3737 static MonoClass *MethodInfo_array;
3739 MonoClass *startklass, *klass, *refklass;
3744 int i, len, match, nslots;
3745 /*FIXME, use MonoBitSet*/
3746 guint32 method_slots_default [8];
3747 guint32 *method_slots;
3748 gchar *mname = NULL;
3749 int (*compare_func) (const char *s1, const char *s2) = NULL;
3750 MonoVTable *array_vtable;
3751 MonoPtrArray tmp_array;
3753 MONO_ARCH_SAVE_REGS;
3755 mono_ptr_array_init (tmp_array, 4);
3757 if (!MethodInfo_array) {
3758 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3759 mono_memory_barrier ();
3760 MethodInfo_array = klass;
3763 domain = ((MonoObject *)type)->vtable->domain;
3764 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3765 if (type->type->byref)
3766 return mono_array_new_specific (array_vtable, 0);
3767 klass = startklass = mono_class_from_mono_type (type->type);
3768 refklass = mono_class_from_mono_type (reftype->type);
3771 mname = mono_string_to_utf8 (name);
3772 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3775 /* An optimization for calls made from Delegate:CreateDelegate () */
3776 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3777 method = mono_get_delegate_invoke (klass);
3779 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3781 res = mono_array_new_specific (array_vtable, 1);
3782 mono_array_setref (res, 0, member);
3787 mono_class_setup_vtable (klass);
3789 if (is_generic_parameter (type->type))
3790 nslots = mono_class_get_vtable_size (klass->parent);
3792 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3793 if (nslots >= sizeof (method_slots_default) * 8) {
3794 method_slots = g_new0 (guint32, nslots / 32 + 1);
3796 method_slots = method_slots_default;
3797 memset (method_slots, 0, sizeof (method_slots_default));
3800 mono_class_setup_vtable (klass);
3801 if (klass->exception_type != MONO_EXCEPTION_NONE)
3802 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3805 while ((method = mono_class_get_methods (klass, &iter))) {
3807 if (method->slot != -1) {
3808 g_assert (method->slot < nslots);
3809 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3811 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3814 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3816 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3817 if (bflags & BFLAGS_Public)
3819 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3825 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3826 if (bflags & BFLAGS_Static)
3827 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3830 if (bflags & BFLAGS_Instance)
3838 if (compare_func (mname, method->name))
3844 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3846 mono_ptr_array_append (tmp_array, member);
3848 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3852 if (method_slots != method_slots_default)
3853 g_free (method_slots);
3855 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3857 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3858 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3860 mono_ptr_array_destroy (tmp_array);
3865 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3868 static MonoClass *System_Reflection_ConstructorInfo;
3869 MonoClass *startklass, *klass, *refklass;
3874 gpointer iter = NULL;
3875 MonoPtrArray tmp_array;
3877 MONO_ARCH_SAVE_REGS;
3879 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3881 domain = ((MonoObject *)type)->vtable->domain;
3882 if (type->type->byref)
3883 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3884 klass = startklass = mono_class_from_mono_type (type->type);
3885 refklass = mono_class_from_mono_type (reftype->type);
3887 if (klass->exception_type != MONO_EXCEPTION_NONE)
3888 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3890 if (!System_Reflection_ConstructorInfo)
3891 System_Reflection_ConstructorInfo = mono_class_from_name (
3892 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3895 while ((method = mono_class_get_methods (klass, &iter))) {
3897 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3899 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3900 if (bflags & BFLAGS_Public)
3903 if (bflags & BFLAGS_NonPublic)
3909 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3910 if (bflags & BFLAGS_Static)
3911 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3914 if (bflags & BFLAGS_Instance)
3920 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3922 mono_ptr_array_append (tmp_array, member);
3925 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3927 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3928 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3930 mono_ptr_array_destroy (tmp_array);
3936 property_hash (gconstpointer data)
3938 MonoProperty *prop = (MonoProperty*)data;
3940 return g_str_hash (prop->name);
3944 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3946 // Properties are hide-by-name-and-signature
3947 if (!g_str_equal (prop1->name, prop2->name))
3950 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3952 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3958 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3963 return method_nonpublic (accessor, start_klass);
3967 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3970 static MonoClass *System_Reflection_PropertyInfo;
3971 MonoClass *startklass, *klass;
3977 gchar *propname = NULL;
3978 int (*compare_func) (const char *s1, const char *s2) = NULL;
3980 GHashTable *properties;
3981 MonoPtrArray tmp_array;
3983 MONO_ARCH_SAVE_REGS;
3985 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3987 if (!System_Reflection_PropertyInfo)
3988 System_Reflection_PropertyInfo = mono_class_from_name (
3989 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3991 domain = ((MonoObject *)type)->vtable->domain;
3992 if (type->type->byref)
3993 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3994 klass = startklass = mono_class_from_mono_type (type->type);
3996 propname = mono_string_to_utf8 (name);
3997 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
4000 mono_class_setup_vtable (klass);
4002 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4004 mono_class_setup_vtable (klass);
4005 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4006 g_hash_table_destroy (properties);
4009 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4013 while ((prop = mono_class_get_properties (klass, &iter))) {
4019 flags = method->flags;
4022 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4023 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4024 if (bflags & BFLAGS_Public)
4026 } else if (bflags & BFLAGS_NonPublic) {
4027 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4028 property_accessor_nonpublic(prop->set, startklass == klass)) {
4035 if (flags & METHOD_ATTRIBUTE_STATIC) {
4036 if (bflags & BFLAGS_Static)
4037 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4040 if (bflags & BFLAGS_Instance)
4049 if (compare_func (propname, prop->name))
4053 if (g_hash_table_lookup (properties, prop))
4056 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4058 g_hash_table_insert (properties, prop, prop);
4060 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4063 g_hash_table_destroy (properties);
4066 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4067 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4068 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4070 mono_ptr_array_destroy (tmp_array);
4075 static MonoReflectionEvent *
4076 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4079 MonoClass *klass, *startklass;
4085 MONO_ARCH_SAVE_REGS;
4087 event_name = mono_string_to_utf8 (name);
4088 if (type->type->byref)
4090 klass = startklass = mono_class_from_mono_type (type->type);
4091 domain = mono_object_domain (type);
4094 if (klass->exception_type != MONO_EXCEPTION_NONE)
4095 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4098 while ((event = mono_class_get_events (klass, &iter))) {
4099 if (strcmp (event->name, event_name))
4102 method = event->add;
4104 method = event->remove;
4106 method = event->raise;
4108 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4109 if (!(bflags & BFLAGS_Public))
4112 if (!(bflags & BFLAGS_NonPublic))
4114 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4118 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4119 if (!(bflags & BFLAGS_Static))
4121 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4124 if (!(bflags & BFLAGS_Instance))
4128 if (!(bflags & BFLAGS_NonPublic))
4131 g_free (event_name);
4132 return mono_event_get_object (domain, startklass, event);
4135 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4138 g_free (event_name);
4143 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4146 static MonoClass *System_Reflection_EventInfo;
4147 MonoClass *startklass, *klass;
4154 MonoPtrArray tmp_array;
4156 MONO_ARCH_SAVE_REGS;
4158 mono_ptr_array_init (tmp_array, 4);
4160 if (!System_Reflection_EventInfo)
4161 System_Reflection_EventInfo = mono_class_from_name (
4162 mono_defaults.corlib, "System.Reflection", "EventInfo");
4164 domain = mono_object_domain (type);
4165 if (type->type->byref)
4166 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4167 klass = startklass = mono_class_from_mono_type (type->type);
4170 if (klass->exception_type != MONO_EXCEPTION_NONE)
4171 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4174 while ((event = mono_class_get_events (klass, &iter))) {
4176 method = event->add;
4178 method = event->remove;
4180 method = event->raise;
4182 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4183 if (bflags & BFLAGS_Public)
4185 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4186 if (bflags & BFLAGS_NonPublic)
4191 if (bflags & BFLAGS_NonPublic)
4197 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4198 if (bflags & BFLAGS_Static)
4199 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4202 if (bflags & BFLAGS_Instance)
4207 if (bflags & BFLAGS_Instance)
4211 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4213 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4216 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4218 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4219 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4221 mono_ptr_array_destroy (tmp_array);
4226 static MonoReflectionType *
4227 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4235 MONO_ARCH_SAVE_REGS;
4238 mono_raise_exception (mono_get_exception_argument_null ("name"));
4240 domain = ((MonoObject *)type)->vtable->domain;
4241 if (type->type->byref)
4243 klass = mono_class_from_mono_type (type->type);
4244 str = mono_string_to_utf8 (name);
4247 if (klass->exception_type != MONO_EXCEPTION_NONE)
4248 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4251 * If a nested type is generic, return its generic type definition.
4252 * Note that this means that the return value is essentially a
4253 * nested type of the generic type definition of @klass.
4255 * A note in MSDN claims that a generic type definition can have
4256 * nested types that aren't generic. In any case, the container of that
4257 * nested type would be the generic type definition.
4259 if (klass->generic_class)
4260 klass = klass->generic_class->container_class;
4263 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4265 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4266 if (bflags & BFLAGS_Public)
4269 if (bflags & BFLAGS_NonPublic)
4274 if (strcmp (nested->name, str) == 0){
4276 return mono_type_get_object (domain, &nested->byval_arg);
4279 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4286 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4295 MonoPtrArray tmp_array;
4297 MONO_ARCH_SAVE_REGS;
4299 domain = ((MonoObject *)type)->vtable->domain;
4300 if (type->type->byref)
4301 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4302 klass = mono_class_from_mono_type (type->type);
4303 if (klass->exception_type != MONO_EXCEPTION_NONE)
4304 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4307 * If a nested type is generic, return its generic type definition.
4308 * Note that this means that the return value is essentially the set
4309 * of nested types of the generic type definition of @klass.
4311 * A note in MSDN claims that a generic type definition can have
4312 * nested types that aren't generic. In any case, the container of that
4313 * nested type would be the generic type definition.
4315 if (klass->generic_class)
4316 klass = klass->generic_class->container_class;
4318 mono_ptr_array_init (tmp_array, 1);
4320 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4322 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4323 if (bflags & BFLAGS_Public)
4326 if (bflags & BFLAGS_NonPublic)
4331 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4332 mono_ptr_array_append (tmp_array, member);
4335 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4337 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4338 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4340 mono_ptr_array_destroy (tmp_array);
4345 static MonoReflectionType*
4346 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4349 MonoType *type = NULL;
4350 MonoTypeNameParse info;
4351 gboolean type_resolve;
4353 MONO_ARCH_SAVE_REGS;
4355 /* On MS.NET, this does not fire a TypeResolve event */
4356 type_resolve = TRUE;
4357 str = mono_string_to_utf8 (name);
4358 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4359 if (!mono_reflection_parse_type (str, &info)) {
4361 mono_reflection_free_type_info (&info);
4362 if (throwOnError) /* uhm: this is a parse error, though... */
4363 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4364 /*g_print ("failed parse\n");*/
4368 if (info.assembly.name) {
4370 mono_reflection_free_type_info (&info);
4372 /* 1.0 and 2.0 throw different exceptions */
4373 if (mono_defaults.generic_ilist_class)
4374 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4376 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4381 if (module != NULL) {
4383 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4388 if (assembly->assembly->dynamic) {
4389 /* Enumerate all modules */
4390 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4394 if (abuilder->modules) {
4395 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4396 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4397 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4403 if (!type && abuilder->loaded_modules) {
4404 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4405 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4406 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4413 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4415 mono_reflection_free_type_info (&info);
4417 MonoException *e = NULL;
4420 e = mono_get_exception_type_load (name, NULL);
4422 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4423 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4425 mono_loader_clear_error ();
4428 mono_raise_exception (e);
4433 if (type->type == MONO_TYPE_CLASS) {
4434 MonoClass *klass = mono_type_get_class (type);
4436 if (mono_is_security_manager_active () && !klass->exception_type)
4437 /* Some security problems are detected during generic vtable construction */
4438 mono_class_setup_vtable (klass);
4439 /* need to report exceptions ? */
4440 if (throwOnError && klass->exception_type) {
4441 /* report SecurityException (or others) that occured when loading the assembly */
4442 MonoException *exc = mono_class_get_exception_for_failure (klass);
4443 mono_loader_clear_error ();
4444 mono_raise_exception (exc);
4445 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4450 /* g_print ("got it\n"); */
4451 return mono_type_get_object (mono_object_domain (assembly), type);
4455 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4458 gchar *shadow_ini_file;
4461 /* Check for shadow-copied assembly */
4462 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4463 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4465 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4466 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4472 g_free (shadow_ini_file);
4473 if (content != NULL) {
4476 *filename = content;
4484 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4486 MonoDomain *domain = mono_object_domain (assembly);
4487 MonoAssembly *mass = assembly->assembly;
4488 MonoString *res = NULL;
4493 MONO_ARCH_SAVE_REGS;
4495 if (g_path_is_absolute (mass->image->name)) {
4496 absolute = g_strdup (mass->image->name);
4497 dirname = g_path_get_dirname (absolute);
4499 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4500 dirname = g_strdup (mass->basedir);
4503 replace_shadow_path (domain, dirname, &absolute);
4508 for (i = strlen (absolute) - 1; i >= 0; i--)
4509 if (absolute [i] == '\\')
4514 uri = g_filename_to_uri (absolute, NULL, NULL);
4516 const char *prepend = "file://";
4518 if (*absolute == '/' && *(absolute + 1) == '/') {
4521 prepend = "file:///";
4524 uri = g_strconcat (prepend, absolute, NULL);
4528 res = mono_string_new (domain, uri);
4536 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4538 MonoAssembly *mass = assembly->assembly;
4540 MONO_ARCH_SAVE_REGS;
4542 return mass->in_gac;
4545 static MonoReflectionAssembly*
4546 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4550 MonoImageOpenStatus status;
4552 MONO_ARCH_SAVE_REGS;
4554 name = mono_string_to_utf8 (mname);
4555 res = mono_assembly_load_with_partial_name (name, &status);
4561 return mono_assembly_get_object (mono_domain_get (), res);
4565 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4567 MonoDomain *domain = mono_object_domain (assembly);
4570 MONO_ARCH_SAVE_REGS;
4572 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4578 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4580 MONO_ARCH_SAVE_REGS;
4582 return assembly->assembly->ref_only;
4586 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4588 MonoDomain *domain = mono_object_domain (assembly);
4590 MONO_ARCH_SAVE_REGS;
4592 return mono_string_new (domain, assembly->assembly->image->version);
4595 static MonoReflectionMethod*
4596 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4598 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4600 MONO_ARCH_SAVE_REGS;
4604 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4607 static MonoReflectionModule*
4608 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4610 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4614 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4616 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4617 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4621 MONO_ARCH_SAVE_REGS;
4623 for (i = 0; i < table->rows; ++i) {
4624 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4625 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4631 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4633 static MonoClass *System_Version = NULL;
4634 static MonoMethod *create_version = NULL;
4638 if (!System_Version) {
4639 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4640 g_assert (System_Version);
4643 if (!create_version) {
4644 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4645 create_version = mono_method_desc_search_in_class (desc, System_Version);
4646 g_assert (create_version);
4647 mono_method_desc_free (desc);
4653 args [3] = &revision;
4654 result = mono_object_new (domain, System_Version);
4655 mono_runtime_invoke (create_version, result, args, NULL);
4661 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4663 static MonoClass *System_Reflection_AssemblyName;
4665 MonoDomain *domain = mono_object_domain (assembly);
4667 static MonoMethod *create_culture = NULL;
4668 MonoImage *image = assembly->assembly->image;
4671 MONO_ARCH_SAVE_REGS;
4673 if (!System_Reflection_AssemblyName)
4674 System_Reflection_AssemblyName = mono_class_from_name (
4675 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4677 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4680 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4682 if (count > 0 && !create_culture) {
4683 MonoMethodDesc *desc = mono_method_desc_new (
4684 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4685 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4686 g_assert (create_culture);
4687 mono_method_desc_free (desc);
4690 for (i = 0; i < count; i++) {
4691 MonoReflectionAssemblyName *aname;
4692 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4694 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4696 aname = (MonoReflectionAssemblyName *) mono_object_new (
4697 domain, System_Reflection_AssemblyName);
4699 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4701 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4702 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4703 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4704 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4705 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4706 aname->versioncompat = 1; /* SameMachine (default) */
4707 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4708 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4710 if (create_culture) {
4712 MonoBoolean assembly_ref = 1;
4713 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4714 args [1] = &assembly_ref;
4715 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4718 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4719 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4720 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4722 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4723 /* public key token isn't copied - the class library will
4724 automatically generate it from the public key if required */
4725 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4726 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4728 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4729 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4732 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4735 /* note: this function doesn't return the codebase on purpose (i.e. it can
4736 be used under partial trust as path information isn't present). */
4738 mono_array_setref (result, i, aname);
4749 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4751 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4753 mono_array_setref (info->res, info->idx, name);
4758 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4760 MonoImage *img = assembly->assembly->image;
4765 MONO_ARCH_SAVE_REGS;
4767 mono_image_lock (img);
4768 mono_image_init_name_cache (img);
4771 len = g_hash_table_size (img->name_cache);
4772 mono_image_unlock (img);
4774 /*we can't create objects holding the image lock */
4775 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4777 mono_image_lock (img);
4778 /*len might have changed, create a new array*/
4779 if (len != g_hash_table_size (img->name_cache))
4784 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4785 mono_image_unlock (img);
4790 /* move this in some file in mono/util/ */
4792 g_concat_dir_and_file (const char *dir, const char *file)
4794 g_return_val_if_fail (dir != NULL, NULL);
4795 g_return_val_if_fail (file != NULL, NULL);
4798 * If the directory name doesn't have a / on the end, we need
4799 * to add one so we get a proper path to the file
4801 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4802 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4804 return g_strconcat (dir, file, NULL);
4808 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4810 char *n = mono_string_to_utf8 (name);
4811 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4813 guint32 cols [MONO_MANIFEST_SIZE];
4814 guint32 impl, file_idx;
4818 MONO_ARCH_SAVE_REGS;
4820 for (i = 0; i < table->rows; ++i) {
4821 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4822 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4823 if (strcmp (val, n) == 0)
4827 if (i == table->rows)
4830 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4833 * this code should only be called after obtaining the
4834 * ResourceInfo and handling the other cases.
4836 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4837 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4839 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4844 module = assembly->assembly->image;
4846 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4848 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4852 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4854 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4856 guint32 cols [MONO_MANIFEST_SIZE];
4857 guint32 file_cols [MONO_FILE_SIZE];
4861 MONO_ARCH_SAVE_REGS;
4863 n = mono_string_to_utf8 (name);
4864 for (i = 0; i < table->rows; ++i) {
4865 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4866 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4867 if (strcmp (val, n) == 0)
4871 if (i == table->rows)
4874 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4875 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4878 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4879 case MONO_IMPLEMENTATION_FILE:
4880 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4881 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4882 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4883 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4884 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4885 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4888 info->location = RESOURCE_LOCATION_EMBEDDED;
4891 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4892 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4893 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4894 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4895 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4896 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4898 mono_raise_exception (ex);
4900 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4902 /* Obtain info recursively */
4903 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4904 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4907 case MONO_IMPLEMENTATION_EXP_TYPE:
4908 g_assert_not_reached ();
4917 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4919 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4920 MonoArray *result = NULL;
4925 MONO_ARCH_SAVE_REGS;
4927 /* check hash if needed */
4929 n = mono_string_to_utf8 (name);
4930 for (i = 0; i < table->rows; ++i) {
4931 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4932 if (strcmp (val, n) == 0) {
4935 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4936 fn = mono_string_new (mono_object_domain (assembly), n);
4938 return (MonoObject*)fn;
4946 for (i = 0; i < table->rows; ++i) {
4947 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4951 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4954 for (i = 0; i < table->rows; ++i) {
4955 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4956 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4957 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4958 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4963 return (MonoObject*)result;
4967 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4969 MonoDomain *domain = mono_domain_get();
4972 int i, j, file_count = 0;
4973 MonoImage **modules;
4974 guint32 module_count, real_module_count;
4975 MonoTableInfo *table;
4976 guint32 cols [MONO_FILE_SIZE];
4977 MonoImage *image = assembly->assembly->image;
4979 g_assert (image != NULL);
4980 g_assert (!assembly->assembly->dynamic);
4982 table = &image->tables [MONO_TABLE_FILE];
4983 file_count = table->rows;
4985 modules = image->modules;
4986 module_count = image->module_count;
4988 real_module_count = 0;
4989 for (i = 0; i < module_count; ++i)
4991 real_module_count ++;
4993 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4994 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4996 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4998 for (i = 0; i < module_count; ++i)
5000 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
5004 for (i = 0; i < file_count; ++i, ++j) {
5005 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5006 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5007 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
5009 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5011 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5012 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
5014 mono_array_setref (res, j, mono_module_get_object (domain, m));
5021 static MonoReflectionMethod*
5022 ves_icall_GetCurrentMethod (void)
5024 MonoMethod *m = mono_method_get_last_managed ();
5026 MONO_ARCH_SAVE_REGS;
5028 return mono_method_get_object (mono_domain_get (), m, NULL);
5033 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5036 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5037 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5038 //method is inflated, we should inflate it on the other class
5039 MonoGenericContext ctx;
5040 ctx.method_inst = inflated->context.method_inst;
5041 ctx.class_inst = inflated->context.class_inst;
5042 if (klass->generic_class)
5043 ctx.class_inst = klass->generic_class->context.class_inst;
5044 else if (klass->generic_container)
5045 ctx.class_inst = klass->generic_container->context.class_inst;
5046 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
5049 mono_class_setup_methods (method->klass);
5050 for (i = 0; i < method->klass->method.count; ++i) {
5051 if (method->klass->methods [i] == method) {
5056 mono_class_setup_methods (klass);
5057 g_assert (offset >= 0 && offset < klass->method.count);
5058 return klass->methods [offset];
5061 static MonoReflectionMethod*
5062 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5066 klass = mono_class_from_mono_type (type);
5067 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5069 if (method->klass != klass)
5070 method = mono_method_get_equivalent_method (method, klass);
5072 klass = method->klass;
5073 return mono_method_get_object (mono_domain_get (), method, klass);
5076 static MonoReflectionMethod*
5077 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5079 return mono_method_get_object (mono_domain_get (), method, NULL);
5082 static MonoReflectionMethodBody*
5083 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5085 return mono_method_body_get_object (mono_domain_get (), method);
5088 static MonoReflectionAssembly*
5089 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5091 MonoMethod *dest = NULL;
5093 MONO_ARCH_SAVE_REGS;
5095 mono_stack_walk_no_il (get_executing, &dest);
5096 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5100 static MonoReflectionAssembly*
5101 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5103 MonoDomain* domain = mono_domain_get ();
5105 MONO_ARCH_SAVE_REGS;
5107 if (!domain->entry_assembly)
5110 return mono_assembly_get_object (domain, domain->entry_assembly);
5113 static MonoReflectionAssembly*
5114 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5119 MONO_ARCH_SAVE_REGS;
5122 mono_stack_walk_no_il (get_executing, &dest);
5124 mono_stack_walk_no_il (get_caller, &dest);
5127 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5131 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5132 gboolean assembly_qualified)
5134 MonoDomain *domain = mono_object_domain (object);
5135 MonoTypeNameFormat format;
5139 MONO_ARCH_SAVE_REGS;
5141 format = assembly_qualified ?
5142 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5143 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5145 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5147 name = mono_type_get_name_full (object->type, format);
5151 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5156 res = mono_string_new (domain, name);
5163 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5165 static MonoMethod *create_culture = NULL;
5168 const char *pkey_ptr;
5170 MonoBoolean assembly_ref = 0;
5172 MONO_ARCH_SAVE_REGS;
5174 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5175 aname->major = name->major;
5176 aname->minor = name->minor;
5177 aname->build = name->build;
5178 aname->flags = name->flags;
5179 aname->revision = name->revision;
5180 aname->hashalg = name->hash_alg;
5181 aname->versioncompat = 1; /* SameMachine (default) */
5183 if (by_default_version)
5184 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5187 if (absolute != NULL && *absolute != '\0') {
5188 const gchar *prepend = "file://";
5191 codebase = g_strdup (absolute);
5196 for (i = strlen (codebase) - 1; i >= 0; i--)
5197 if (codebase [i] == '\\')
5200 if (*codebase == '/' && *(codebase + 1) == '/') {
5203 prepend = "file:///";
5207 result = g_strconcat (prepend, codebase, NULL);
5213 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5217 if (!create_culture) {
5218 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5219 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5220 g_assert (create_culture);
5221 mono_method_desc_free (desc);
5224 if (name->culture) {
5225 args [0] = mono_string_new (domain, name->culture);
5226 args [1] = &assembly_ref;
5227 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5230 if (name->public_key) {
5231 pkey_ptr = (char*)name->public_key;
5232 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5234 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5235 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5236 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5237 } else if (default_publickey) {
5238 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5239 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5242 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5243 if (name->public_key_token [0]) {
5247 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5248 p = mono_array_addr (aname->keyToken, char, 0);
5250 for (i = 0, j = 0; i < 8; i++) {
5251 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5252 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5255 } else if (default_token) {
5256 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5261 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5263 MonoDomain *domain = mono_object_domain (assembly);
5264 MonoAssembly *mass = assembly->assembly;
5268 name = g_strdup_printf (
5269 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5271 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5272 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5273 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5274 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5276 res = mono_string_new (domain, name);
5283 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5286 MonoAssembly *mass = assembly->assembly;
5288 MONO_ARCH_SAVE_REGS;
5290 if (g_path_is_absolute (mass->image->name)) {
5291 fill_reflection_assembly_name (mono_object_domain (assembly),
5292 aname, &mass->aname, mass->image->name, TRUE,
5293 TRUE, mono_framework_version () >= 2);
5296 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5298 fill_reflection_assembly_name (mono_object_domain (assembly),
5299 aname, &mass->aname, absolute, TRUE, TRUE,
5300 mono_framework_version () >= 2);
5306 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5309 MonoImageOpenStatus status = MONO_IMAGE_OK;
5312 MonoAssemblyName name;
5315 MONO_ARCH_SAVE_REGS;
5317 filename = mono_string_to_utf8 (fname);
5319 dirname = g_path_get_dirname (filename);
5320 replace_shadow_path (mono_domain_get (), dirname, &filename);
5323 image = mono_image_open (filename, &status);
5329 if (status == MONO_IMAGE_IMAGE_INVALID)
5330 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5332 exc = mono_get_exception_file_not_found2 (NULL, fname);
5333 mono_raise_exception (exc);
5336 res = mono_assembly_fill_assembly_name (image, &name);
5338 mono_image_close (image);
5340 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5343 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5344 TRUE, mono_framework_version () == 1,
5345 mono_framework_version () >= 2);
5348 mono_image_close (image);
5352 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5353 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5355 MonoBoolean result = FALSE;
5356 MonoDeclSecurityEntry entry;
5358 /* SecurityAction.RequestMinimum */
5359 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5360 *minimum = entry.blob;
5361 *minLength = entry.size;
5364 /* SecurityAction.RequestOptional */
5365 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5366 *optional = entry.blob;
5367 *optLength = entry.size;
5370 /* SecurityAction.RequestRefuse */
5371 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5372 *refused = entry.blob;
5373 *refLength = entry.size;
5381 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5385 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5387 guint32 attrs, visibility;
5389 /* we start the count from 1 because we skip the special type <Module> */
5392 for (i = 1; i < tdef->rows; ++i) {
5393 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5394 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5395 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5399 count = tdef->rows - 1;
5401 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5402 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5404 for (i = 1; i < tdef->rows; ++i) {
5405 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5406 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5407 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5408 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5410 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5412 MonoLoaderError *error;
5415 error = mono_loader_get_last_error ();
5416 g_assert (error != NULL);
5418 ex = mono_loader_error_prepare_exception (error);
5419 mono_array_setref (*exceptions, count, ex);
5421 if (mono_loader_get_last_error ())
5422 mono_loader_clear_error ();
5431 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5433 MonoArray *res = NULL;
5434 MonoArray *exceptions = NULL;
5435 MonoImage *image = NULL;
5436 MonoTableInfo *table = NULL;
5439 int i, len, ex_count;
5441 MONO_ARCH_SAVE_REGS;
5443 domain = mono_object_domain (assembly);
5445 g_assert (!assembly->assembly->dynamic);
5446 image = assembly->assembly->image;
5447 table = &image->tables [MONO_TABLE_FILE];
5448 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5450 /* Append data from all modules in the assembly */
5451 for (i = 0; i < table->rows; ++i) {
5452 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5453 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5456 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5457 /* Append the new types to the end of the array */
5458 if (mono_array_length (res2) > 0) {
5460 MonoArray *res3, *ex3;
5462 len1 = mono_array_length (res);
5463 len2 = mono_array_length (res2);
5465 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5466 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5467 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5470 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5471 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5472 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5479 /* the ReflectionTypeLoadException must have all the types (Types property),
5480 * NULL replacing types which throws an exception. The LoaderException must
5481 * contain all exceptions for NULL items.
5484 len = mono_array_length (res);
5487 for (i = 0; i < len; i++) {
5488 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5492 klass = mono_type_get_class (t->type);
5493 if ((klass != NULL) && klass->exception_type) {
5494 /* keep the class in the list */
5495 list = g_list_append (list, klass);
5496 /* and replace Type with NULL */
5497 mono_array_setref (res, i, NULL);
5504 if (list || ex_count) {
5506 MonoException *exc = NULL;
5507 MonoArray *exl = NULL;
5508 int j, length = g_list_length (list) + ex_count;
5510 mono_loader_clear_error ();
5512 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5513 /* Types for which mono_class_get () succeeded */
5514 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5515 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5516 mono_array_setref (exl, i, exc);
5518 /* Types for which it don't */
5519 for (j = 0; j < mono_array_length (exceptions); ++j) {
5520 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5522 g_assert (i < length);
5523 mono_array_setref (exl, i, exc);
5530 exc = mono_get_exception_reflection_type_load (res, exl);
5531 mono_loader_clear_error ();
5532 mono_raise_exception (exc);
5539 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5541 MonoAssemblyName aname;
5542 MonoDomain *domain = mono_object_domain (name);
5544 gboolean is_version_defined;
5545 gboolean is_token_defined;
5547 aname.public_key = NULL;
5548 val = mono_string_to_utf8 (assname);
5549 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5550 g_free ((guint8*) aname.public_key);
5555 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5556 FALSE, is_token_defined);
5558 mono_assembly_name_free (&aname);
5559 g_free ((guint8*) aname.public_key);
5565 static MonoReflectionType*
5566 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5568 MonoDomain *domain = mono_object_domain (module);
5571 MONO_ARCH_SAVE_REGS;
5573 g_assert (module->image);
5575 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5576 /* These images do not have a global type */
5579 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5580 return mono_type_get_object (domain, &klass->byval_arg);
5584 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5586 /*if (module->image)
5587 mono_image_close (module->image);*/
5591 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5593 MonoDomain *domain = mono_object_domain (module);
5595 MONO_ARCH_SAVE_REGS;
5597 g_assert (module->image);
5598 return mono_string_new (domain, module->image->guid);
5602 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5604 #ifdef PLATFORM_WIN32
5605 if (module->image && module->image->is_module_handle)
5606 return module->image->raw_data;
5609 return (gpointer) (-1);
5613 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5615 if (image->dynamic) {
5616 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5617 *pe_kind = dyn->pe_kind;
5618 *machine = dyn->machine;
5621 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5622 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5627 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5629 return (image->md_version_major << 16) | (image->md_version_minor);
5633 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5635 MonoArray *exceptions;
5638 MONO_ARCH_SAVE_REGS;
5641 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5643 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5644 for (i = 0; i < mono_array_length (exceptions); ++i) {
5645 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5647 mono_raise_exception (ex);
5654 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5656 guint32 cols [MONO_MEMBERREF_SIZE];
5658 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5659 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5660 mono_metadata_decode_blob_size (sig, &sig);
5661 return (*sig != 0x6);
5665 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5668 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5669 mono_array_addr (type_args, MonoType*, 0));
5671 context->class_inst = NULL;
5673 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5674 mono_array_addr (method_args, MonoType*, 0));
5676 context->method_inst = NULL;
5680 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5683 int table = mono_metadata_token_table (token);
5684 int index = mono_metadata_token_index (token);
5685 MonoGenericContext context;
5687 *error = ResolveTokenError_Other;
5689 /* Validate token */
5690 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5691 (table != MONO_TABLE_TYPESPEC)) {
5692 *error = ResolveTokenError_BadTable;
5696 if (image->dynamic) {
5697 if (type_args || method_args)
5698 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5699 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5702 return &klass->byval_arg;
5705 if ((index <= 0) || (index > image->tables [table].rows)) {
5706 *error = ResolveTokenError_OutOfRange;
5710 init_generic_context_from_args (&context, type_args, method_args);
5711 klass = mono_class_get_full (image, token, &context);
5713 if (mono_loader_get_last_error ())
5714 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5717 return &klass->byval_arg;
5723 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5725 int table = mono_metadata_token_table (token);
5726 int index = mono_metadata_token_index (token);
5727 MonoGenericContext context;
5730 *error = ResolveTokenError_Other;
5732 /* Validate token */
5733 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5734 (table != MONO_TABLE_MEMBERREF)) {
5735 *error = ResolveTokenError_BadTable;
5739 if (image->dynamic) {
5740 if (type_args || method_args)
5741 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5742 /* FIXME: validate memberref token type */
5743 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5746 if ((index <= 0) || (index > image->tables [table].rows)) {
5747 *error = ResolveTokenError_OutOfRange;
5750 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5751 *error = ResolveTokenError_BadTable;
5755 init_generic_context_from_args (&context, type_args, method_args);
5756 method = mono_get_method_full (image, token, NULL, &context);
5758 if (mono_loader_get_last_error ())
5759 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5765 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5767 int index = mono_metadata_token_index (token);
5769 *error = ResolveTokenError_Other;
5771 /* Validate token */
5772 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5773 *error = ResolveTokenError_BadTable;
5778 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5780 if ((index <= 0) || (index >= image->heap_us.size)) {
5781 *error = ResolveTokenError_OutOfRange;
5785 /* FIXME: What to do if the index points into the middle of a string ? */
5787 return mono_ldstr (mono_domain_get (), image, index);
5790 static MonoClassField*
5791 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5794 int table = mono_metadata_token_table (token);
5795 int index = mono_metadata_token_index (token);
5796 MonoGenericContext context;
5797 MonoClassField *field;
5799 *error = ResolveTokenError_Other;
5801 /* Validate token */
5802 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5803 *error = ResolveTokenError_BadTable;
5807 if (image->dynamic) {
5808 if (type_args || method_args)
5809 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5810 /* FIXME: validate memberref token type */
5811 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5814 if ((index <= 0) || (index > image->tables [table].rows)) {
5815 *error = ResolveTokenError_OutOfRange;
5818 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5819 *error = ResolveTokenError_BadTable;
5823 init_generic_context_from_args (&context, type_args, method_args);
5824 field = mono_field_from_token (image, token, &klass, &context);
5826 if (mono_loader_get_last_error ())
5827 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5834 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5836 int table = mono_metadata_token_table (token);
5838 *error = ResolveTokenError_Other;
5841 case MONO_TABLE_TYPEDEF:
5842 case MONO_TABLE_TYPEREF:
5843 case MONO_TABLE_TYPESPEC: {
5844 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5846 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5850 case MONO_TABLE_METHOD:
5851 case MONO_TABLE_METHODSPEC: {
5852 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5854 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5858 case MONO_TABLE_FIELD: {
5859 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5861 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5865 case MONO_TABLE_MEMBERREF:
5866 if (mono_metadata_memberref_is_method (image, token)) {
5867 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5869 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5874 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5876 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5883 *error = ResolveTokenError_BadTable;
5890 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5892 int table = mono_metadata_token_table (token);
5893 int idx = mono_metadata_token_index (token);
5894 MonoTableInfo *tables = image->tables;
5899 *error = ResolveTokenError_OutOfRange;
5901 /* FIXME: Support other tables ? */
5902 if (table != MONO_TABLE_STANDALONESIG)
5908 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5911 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5913 ptr = mono_metadata_blob_heap (image, sig);
5914 len = mono_metadata_decode_blob_size (ptr, &ptr);
5916 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5917 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5921 static MonoReflectionType*
5922 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5925 int isbyref = 0, rank;
5926 char *str = mono_string_to_utf8 (smodifiers);
5929 MONO_ARCH_SAVE_REGS;
5931 klass = mono_class_from_mono_type (tb->type.type);
5933 /* logic taken from mono_reflection_parse_type(): keep in sync */
5937 if (isbyref) { /* only one level allowed by the spec */
5944 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5947 klass = mono_ptr_class_get (&klass->byval_arg);
5948 mono_class_init (klass);
5959 else if (*p != '*') { /* '*' means unknown lower bound */
5970 klass = mono_array_class_get (klass, rank);
5971 mono_class_init (klass);
5978 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5982 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5987 MONO_ARCH_SAVE_REGS;
5990 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5995 static MonoReflectionType *
5996 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5998 MonoClass *klass, *aklass;
6000 MONO_ARCH_SAVE_REGS;
6002 klass = mono_class_from_mono_type (type->type);
6003 if (rank == 0) //single dimentional array
6004 aklass = mono_array_class_get (klass, 1);
6006 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6008 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
6011 static MonoReflectionType *
6012 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6016 MONO_ARCH_SAVE_REGS;
6018 klass = mono_class_from_mono_type (type->type);
6020 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
6023 static MonoReflectionType *
6024 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6028 MONO_ARCH_SAVE_REGS;
6030 pklass = mono_ptr_class_get (type->type);
6032 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
6036 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6037 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6039 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6040 MonoObject *delegate;
6042 MonoMethod *method = info->method;
6044 MONO_ARCH_SAVE_REGS;
6046 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6048 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
6049 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6053 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6055 if (method->dynamic) {
6056 /* Creating a trampoline would leak memory */
6057 func = mono_compile_method (method);
6059 func = mono_create_ftnptr (mono_domain_get (),
6060 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6063 mono_delegate_ctor_with_method (delegate, target, func, method);
6069 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6071 /* Reset the invoke impl to the default one */
6072 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6076 * Magic number to convert a time which is relative to
6077 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6079 #define EPOCH_ADJUST ((guint64)62135596800LL)
6082 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6084 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6086 #ifdef PLATFORM_WIN32
6087 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6089 convert_to_absolute_date(SYSTEMTIME *date)
6091 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6092 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6093 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6094 /* from the calendar FAQ */
6095 int a = (14 - date->wMonth) / 12;
6096 int y = date->wYear - a;
6097 int m = date->wMonth + 12 * a - 2;
6098 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6100 /* d is now the day of the week for the first of the month (0 == Sunday) */
6102 int day_of_week = date->wDayOfWeek;
6104 /* set day_in_month to the first day in the month which falls on day_of_week */
6105 int day_in_month = 1 + (day_of_week - d);
6106 if (day_in_month <= 0)
6109 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6110 date->wDay = day_in_month + (date->wDay - 1) * 7;
6111 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6116 #ifndef PLATFORM_WIN32
6118 * Return's the offset from GMT of a local time.
6120 * tm is a local time
6121 * t is the same local time as seconds.
6124 gmt_offset(struct tm *tm, time_t t)
6126 #if defined (HAVE_TM_GMTOFF)
6127 return tm->tm_gmtoff;
6132 g.tm_isdst = tm->tm_isdst;
6134 return (int)difftime(t, t2);
6139 * This is heavily based on zdump.c from glibc 2.2.
6141 * * data[0]: start of daylight saving time (in DateTime ticks).
6142 * * data[1]: end of daylight saving time (in DateTime ticks).
6143 * * data[2]: utcoffset (in TimeSpan ticks).
6144 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6145 * * name[0]: name of this timezone when not daylight saving.
6146 * * name[1]: name of this timezone when daylight saving.
6148 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6149 * the class library allows years between 1 and 9999.
6151 * Returns true on success and zero on failure.
6154 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6156 #ifndef PLATFORM_WIN32
6157 MonoDomain *domain = mono_domain_get ();
6158 struct tm start, tt;
6162 int is_daylight = 0, day;
6165 MONO_ARCH_SAVE_REGS;
6167 MONO_CHECK_ARG_NULL (data);
6168 MONO_CHECK_ARG_NULL (names);
6170 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6171 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6174 * no info is better than crashing: we'll need our own tz data
6175 * to make this work properly, anyway. The range is probably
6176 * reduced to 1970 .. 2037 because that is what mktime is
6177 * guaranteed to support (we get into an infinite loop
6181 memset (&start, 0, sizeof (start));
6184 start.tm_year = year-1900;
6186 t = mktime (&start);
6188 if ((year < 1970) || (year > 2037) || (t == -1)) {
6190 tt = *localtime (&t);
6191 strftime (tzone, sizeof (tzone), "%Z", &tt);
6192 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6193 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6197 gmtoff = gmt_offset (&start, t);
6199 /* For each day of the year, calculate the tm_gmtoff. */
6200 for (day = 0; day < 365; day++) {
6203 tt = *localtime (&t);
6205 /* Daylight saving starts or ends here. */
6206 if (gmt_offset (&tt, t) != gmtoff) {
6210 /* Try to find the exact hour when daylight saving starts/ends. */
6214 tt1 = *localtime (&t1);
6215 } while (gmt_offset (&tt1, t1) != gmtoff);
6217 /* Try to find the exact minute when daylight saving starts/ends. */
6220 tt1 = *localtime (&t1);
6221 } while (gmt_offset (&tt1, t1) == gmtoff);
6223 strftime (tzone, sizeof (tzone), "%Z", &tt);
6225 /* Write data, if we're already in daylight saving, we're done. */
6227 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6228 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6231 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6232 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6236 /* This is only set once when we enter daylight saving. */
6237 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6238 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6240 gmtoff = gmt_offset (&tt, t);
6245 strftime (tzone, sizeof (tzone), "%Z", &tt);
6246 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6247 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6248 mono_array_set ((*data), gint64, 0, 0);
6249 mono_array_set ((*data), gint64, 1, 0);
6250 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6251 mono_array_set ((*data), gint64, 3, 0);
6256 MonoDomain *domain = mono_domain_get ();
6257 TIME_ZONE_INFORMATION tz_info;
6262 tz_id = GetTimeZoneInformation (&tz_info);
6263 if (tz_id == TIME_ZONE_ID_INVALID)
6266 MONO_CHECK_ARG_NULL (data);
6267 MONO_CHECK_ARG_NULL (names);
6269 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6270 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6272 for (i = 0; i < 32; ++i)
6273 if (!tz_info.DaylightName [i])
6275 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6276 for (i = 0; i < 32; ++i)
6277 if (!tz_info.StandardName [i])
6279 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6281 if ((year <= 1601) || (year > 30827)) {
6283 * According to MSDN, the MS time functions can't handle dates outside
6289 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6290 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6291 tz_info.StandardDate.wYear = year;
6292 convert_to_absolute_date(&tz_info.StandardDate);
6293 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6298 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6299 tz_info.DaylightDate.wYear = year;
6300 convert_to_absolute_date(&tz_info.DaylightDate);
6301 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6306 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6308 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6309 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6316 ves_icall_System_Object_obj_address (MonoObject *this)
6318 MONO_ARCH_SAVE_REGS;
6325 static inline gint32
6326 mono_array_get_byte_length (MonoArray *array)
6332 klass = array->obj.vtable->klass;
6334 if (array->bounds == NULL)
6335 length = array->max_length;
6338 for (i = 0; i < klass->rank; ++ i)
6339 length *= array->bounds [i].length;
6342 switch (klass->element_class->byval_arg.type) {
6345 case MONO_TYPE_BOOLEAN:
6349 case MONO_TYPE_CHAR:
6357 return length * sizeof (gpointer);
6368 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6370 MONO_ARCH_SAVE_REGS;
6372 return mono_array_get_byte_length (array);
6376 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6378 MONO_ARCH_SAVE_REGS;
6380 return mono_array_get (array, gint8, idx);
6384 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6386 MONO_ARCH_SAVE_REGS;
6388 mono_array_set (array, gint8, idx, value);
6392 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6394 guint8 *src_buf, *dest_buf;
6396 MONO_ARCH_SAVE_REGS;
6398 /* watch out for integer overflow */
6399 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6402 src_buf = (guint8 *)src->vector + src_offset;
6403 dest_buf = (guint8 *)dest->vector + dest_offset;
6406 memcpy (dest_buf, src_buf, count);
6408 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6414 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6416 MonoDomain *domain = mono_object_domain (this);
6418 MonoRealProxy *rp = ((MonoRealProxy *)this);
6419 MonoTransparentProxy *tp;
6423 MONO_ARCH_SAVE_REGS;
6425 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6426 tp = (MonoTransparentProxy*) res;
6428 MONO_OBJECT_SETREF (tp, rp, rp);
6429 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6430 klass = mono_class_from_mono_type (type);
6432 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6433 tp->remote_class = mono_remote_class (domain, class_name, klass);
6435 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6439 static MonoReflectionType *
6440 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6442 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6445 /* System.Environment */
6448 ves_icall_System_Environment_get_UserName (void)
6450 MONO_ARCH_SAVE_REGS;
6452 /* using glib is more portable */
6453 return mono_string_new (mono_domain_get (), g_get_user_name ());
6458 ves_icall_System_Environment_get_MachineName (void)
6460 #if defined (PLATFORM_WIN32)
6465 len = MAX_COMPUTERNAME_LENGTH + 1;
6466 buf = g_new (gunichar2, len);
6469 if (GetComputerName (buf, (PDWORD) &len))
6470 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6474 #elif !defined(DISABLE_SOCKETS)
6478 if (gethostname (buf, sizeof (buf)) == 0)
6479 result = mono_string_new (mono_domain_get (), buf);
6485 return mono_string_new (mono_domain_get (), "mono");
6490 ves_icall_System_Environment_get_Platform (void)
6492 #if defined (PLATFORM_WIN32)
6495 #elif defined(__MACH__)
6497 if (mono_framework_version () < 2)
6501 // For compatibility with our client code, this will be 4 for a while.
6502 // We will eventually move to 6 to match .NET, but it requires all client
6503 // code to be updated and the documentation everywhere to be updated
6509 if (mono_framework_version () < 2)
6516 ves_icall_System_Environment_get_NewLine (void)
6518 MONO_ARCH_SAVE_REGS;
6520 #if defined (PLATFORM_WIN32)
6521 return mono_string_new (mono_domain_get (), "\r\n");
6523 return mono_string_new (mono_domain_get (), "\n");
6528 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6533 MONO_ARCH_SAVE_REGS;
6538 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6539 value = g_getenv (utf8_name);
6546 return mono_string_new (mono_domain_get (), value);
6550 * There is no standard way to get at environ.
6553 #ifndef __MINGW32_VERSION
6555 /* Apple defines this in crt_externs.h but doesn't provide that header for
6556 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6557 * in fact exist on all implementations (so far)
6559 gchar ***_NSGetEnviron(void);
6560 #define environ (*_NSGetEnviron())
6569 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6571 #ifdef PLATFORM_WIN32
6580 env_strings = GetEnvironmentStrings();
6583 env_string = env_strings;
6584 while (*env_string != '\0') {
6585 /* weird case that MS seems to skip */
6586 if (*env_string != '=')
6588 while (*env_string != '\0')
6594 domain = mono_domain_get ();
6595 names = mono_array_new (domain, mono_defaults.string_class, n);
6599 env_string = env_strings;
6600 while (*env_string != '\0') {
6601 /* weird case that MS seems to skip */
6602 if (*env_string != '=') {
6603 equal_str = wcschr(env_string, '=');
6604 g_assert(equal_str);
6605 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6606 mono_array_setref (names, n, str);
6609 while (*env_string != '\0')
6614 FreeEnvironmentStrings (env_strings);
6626 MONO_ARCH_SAVE_REGS;
6629 for (e = environ; *e != 0; ++ e)
6632 domain = mono_domain_get ();
6633 names = mono_array_new (domain, mono_defaults.string_class, n);
6636 for (e = environ; *e != 0; ++ e) {
6637 parts = g_strsplit (*e, "=", 2);
6639 str = mono_string_new (domain, *parts);
6640 mono_array_setref (names, n, str);
6653 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6655 #if !GLIB_CHECK_VERSION(2,4,0)
6656 #define g_setenv(a,b,c) setenv(a,b,c)
6657 #define g_unsetenv(a) unsetenv(a)
6661 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6663 #ifdef PLATFORM_WIN32
6664 gunichar2 *utf16_name, *utf16_value;
6666 gchar *utf8_name, *utf8_value;
6669 MONO_ARCH_SAVE_REGS;
6671 #ifdef PLATFORM_WIN32
6672 utf16_name = mono_string_to_utf16 (name);
6673 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6674 SetEnvironmentVariable (utf16_name, NULL);
6675 g_free (utf16_name);
6679 utf16_value = mono_string_to_utf16 (value);
6681 SetEnvironmentVariable (utf16_name, utf16_value);
6683 g_free (utf16_name);
6684 g_free (utf16_value);
6686 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6688 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6689 g_unsetenv (utf8_name);
6694 utf8_value = mono_string_to_utf8 (value);
6695 g_setenv (utf8_name, utf8_value, TRUE);
6698 g_free (utf8_value);
6703 ves_icall_System_Environment_Exit (int result)
6705 MONO_ARCH_SAVE_REGS;
6707 mono_threads_set_shutting_down ();
6709 mono_runtime_set_shutting_down ();
6711 /* Suspend all managed threads since the runtime is going away */
6712 mono_thread_suspend_all_other_threads ();
6714 mono_runtime_quit ();
6716 /* we may need to do some cleanup here... */
6721 ves_icall_System_Environment_GetGacPath (void)
6723 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6727 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6729 #if defined (PLATFORM_WIN32)
6730 #ifndef CSIDL_FLAG_CREATE
6731 #define CSIDL_FLAG_CREATE 0x8000
6734 WCHAR path [MAX_PATH];
6735 /* Create directory if no existing */
6736 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6740 return mono_string_new_utf16 (mono_domain_get (), path, len);
6743 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6745 return mono_string_new (mono_domain_get (), "");
6749 ves_icall_System_Environment_GetLogicalDrives (void)
6751 gunichar2 buf [128], *ptr, *dname;
6753 guint initial_size = 127, size = 128;
6756 MonoString *drivestr;
6757 MonoDomain *domain = mono_domain_get ();
6760 MONO_ARCH_SAVE_REGS;
6765 while (size > initial_size) {
6766 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6767 if (size > initial_size) {
6770 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6771 initial_size = size;
6785 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6790 while (*u16) { u16++; len ++; }
6791 drivestr = mono_string_new_utf16 (domain, dname, len);
6792 mono_array_setref (result, ndrives++, drivestr);
6803 ves_icall_System_Environment_InternalGetHome (void)
6805 MONO_ARCH_SAVE_REGS;
6807 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6810 static const char *encodings [] = {
6812 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6813 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6814 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6816 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6817 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6818 "x_unicode_2_0_utf_7",
6820 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6821 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6823 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6826 "unicodefffe", "utf_16be",
6833 * Returns the internal codepage, if the value of "int_code_page" is
6834 * 1 at entry, and we can not compute a suitable code page number,
6835 * returns the code page as a string
6838 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6843 char *codepage = NULL;
6845 int want_name = *int_code_page;
6848 *int_code_page = -1;
6849 MONO_ARCH_SAVE_REGS;
6851 g_get_charset (&cset);
6852 c = codepage = strdup (cset);
6853 for (c = codepage; *c; c++){
6854 if (isascii (*c) && isalpha (*c))
6859 /* g_print ("charset: %s\n", cset); */
6861 /* handle some common aliases */
6864 for (i = 0; p != 0; ){
6865 if ((gssize) p < 7){
6867 p = encodings [++i];
6870 if (strcmp (p, codepage) == 0){
6871 *int_code_page = code;
6874 p = encodings [++i];
6877 if (strstr (codepage, "utf_8") != NULL)
6878 *int_code_page |= 0x10000000;
6881 if (want_name && *int_code_page == -1)
6882 return mono_string_new (mono_domain_get (), cset);
6888 ves_icall_System_Environment_get_HasShutdownStarted (void)
6890 if (mono_runtime_is_shutting_down ())
6893 if (mono_domain_is_unloading (mono_domain_get ()))
6900 ves_icall_System_Environment_BroadcastSettingChange (void)
6902 #ifdef PLATFORM_WIN32
6903 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6908 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6909 MonoReflectionMethod *method,
6910 MonoArray *out_args)
6912 MONO_ARCH_SAVE_REGS;
6914 mono_message_init (mono_object_domain (this), this, method, out_args);
6918 ves_icall_IsTransparentProxy (MonoObject *proxy)
6920 MONO_ARCH_SAVE_REGS;
6925 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6931 static MonoReflectionMethod *
6932 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6933 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6937 MonoMethod **vtable;
6938 MonoMethod *res = NULL;
6940 MONO_CHECK_ARG_NULL (rtype);
6941 MONO_CHECK_ARG_NULL (rmethod);
6943 method = rmethod->method;
6944 klass = mono_class_from_mono_type (rtype->type);
6946 if (MONO_CLASS_IS_INTERFACE (klass))
6949 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6952 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6953 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6959 mono_class_setup_vtable (klass);
6960 vtable = klass->vtable;
6962 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6963 int offs = mono_class_interface_offset (klass, method->klass);
6965 res = vtable [offs + method->slot];
6967 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6970 if (method->slot != -1)
6971 res = vtable [method->slot];
6977 return mono_method_get_object (mono_domain_get (), res, NULL);
6981 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6986 MONO_ARCH_SAVE_REGS;
6988 klass = mono_class_from_mono_type (type->type);
6989 vtable = mono_class_vtable (mono_domain_get (), klass);
6991 if (enable) vtable->remote = 1;
6992 else vtable->remote = 0;
6996 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7001 MONO_ARCH_SAVE_REGS;
7003 domain = mono_object_domain (type);
7004 klass = mono_class_from_mono_type (type->type);
7006 if (klass->rank >= 1) {
7007 g_assert (klass->rank == 1);
7008 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7010 /* Bypass remoting object creation check */
7011 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
7016 ves_icall_System_IO_get_temp_path (void)
7018 MONO_ARCH_SAVE_REGS;
7020 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7023 #ifndef PLATFORM_NO_DRIVEINFO
7025 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7026 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7030 ULARGE_INTEGER wapi_free_bytes_avail;
7031 ULARGE_INTEGER wapi_total_number_of_bytes;
7032 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7034 MONO_ARCH_SAVE_REGS;
7036 *error = ERROR_SUCCESS;
7037 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7038 &wapi_total_number_of_free_bytes);
7041 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7042 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7043 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7045 *free_bytes_avail = 0;
7046 *total_number_of_bytes = 0;
7047 *total_number_of_free_bytes = 0;
7048 *error = GetLastError ();
7055 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7057 MONO_ARCH_SAVE_REGS;
7059 return GetDriveType (mono_string_chars (root_path_name));
7064 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7066 MONO_ARCH_SAVE_REGS;
7068 return mono_compile_method (method);
7072 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7077 MONO_ARCH_SAVE_REGS;
7079 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7081 #if defined (PLATFORM_WIN32)
7082 /* Avoid mixing '/' and '\\' */
7085 for (i = strlen (path) - 1; i >= 0; i--)
7086 if (path [i] == '/')
7090 mcpath = mono_string_new (mono_domain_get (), path);
7097 get_bundled_machine_config (void)
7099 const gchar *machine_config;
7101 MONO_ARCH_SAVE_REGS;
7103 machine_config = mono_get_machine_config ();
7105 if (!machine_config)
7108 return mono_string_new (mono_domain_get (), machine_config);
7112 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7117 MONO_ARCH_SAVE_REGS;
7119 path = g_path_get_dirname (mono_get_config_dir ());
7121 #if defined (PLATFORM_WIN32)
7122 /* Avoid mixing '/' and '\\' */
7125 for (i = strlen (path) - 1; i >= 0; i--)
7126 if (path [i] == '/')
7130 ipath = mono_string_new (mono_domain_get (), path);
7137 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7139 MonoPEResourceDataEntry *entry;
7142 MONO_ARCH_SAVE_REGS;
7144 if (!assembly || !result || !size)
7149 image = assembly->assembly->image;
7150 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7154 *result = mono_image_rva_map (image, entry->rde_data_offset);
7159 *size = entry->rde_size;
7165 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7167 return mono_debug_using_mono_debugger ();
7171 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7173 #if defined (PLATFORM_WIN32)
7174 OutputDebugString (mono_string_chars (message));
7176 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7180 /* Only used for value types */
7182 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7187 MONO_ARCH_SAVE_REGS;
7189 domain = mono_object_domain (type);
7190 klass = mono_class_from_mono_type (type->type);
7192 if (mono_class_is_nullable (klass))
7193 /* No arguments -> null */
7196 return mono_object_new (domain, klass);
7199 static MonoReflectionMethod *
7200 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7202 MonoClass *klass, *parent;
7203 MonoMethod *method = m->method;
7204 MonoMethod *result = NULL;
7206 MONO_ARCH_SAVE_REGS;
7208 if (method->klass == NULL)
7211 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7212 MONO_CLASS_IS_INTERFACE (method->klass) ||
7213 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7216 klass = method->klass;
7217 if (klass->generic_class)
7218 klass = klass->generic_class->container_class;
7220 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7221 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7222 mono_class_setup_vtable (parent);
7223 if (parent->vtable_size <= method->slot)
7228 if (klass == method->klass)
7231 result = klass->vtable [method->slot];
7232 if (result == NULL) {
7233 /* It is an abstract method */
7234 gpointer iter = NULL;
7235 while ((result = mono_class_get_methods (klass, &iter)))
7236 if (result->slot == method->slot)
7243 return mono_method_get_object (mono_domain_get (), result, NULL);
7247 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7249 MonoMethod *method = m->method;
7251 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7256 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7258 MONO_ARCH_SAVE_REGS;
7260 iter->sig = *(MonoMethodSignature**)argsp;
7262 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7263 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7266 /* FIXME: it's not documented what start is exactly... */
7270 iter->args = argsp + sizeof (gpointer);
7271 #ifndef MONO_ARCH_REGPARMS
7273 guint32 i, arg_size;
7275 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7276 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7277 iter->args = (char*)iter->args + arg_size;
7282 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7284 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7288 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7290 guint32 i, arg_size;
7293 MONO_ARCH_SAVE_REGS;
7295 i = iter->sig->sentinelpos + iter->next_arg;
7297 g_assert (i < iter->sig->param_count);
7299 res.type = iter->sig->params [i];
7300 res.klass = mono_class_from_mono_type (res.type);
7301 res.value = iter->args;
7302 arg_size = mono_type_stack_size (res.type, &align);
7303 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7304 if (arg_size <= sizeof (gpointer)) {
7306 int padding = arg_size - mono_type_size (res.type, &dummy);
7307 res.value = (guint8*)res.value + padding;
7310 iter->args = (char*)iter->args + arg_size;
7313 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7319 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7321 guint32 i, arg_size;
7324 MONO_ARCH_SAVE_REGS;
7326 i = iter->sig->sentinelpos + iter->next_arg;
7328 g_assert (i < iter->sig->param_count);
7330 while (i < iter->sig->param_count) {
7331 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7333 res.type = iter->sig->params [i];
7334 res.klass = mono_class_from_mono_type (res.type);
7335 /* FIXME: endianess issue... */
7336 res.value = iter->args;
7337 arg_size = mono_type_stack_size (res.type, &align);
7338 iter->args = (char*)iter->args + arg_size;
7340 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7343 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7352 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7355 MONO_ARCH_SAVE_REGS;
7357 i = iter->sig->sentinelpos + iter->next_arg;
7359 g_assert (i < iter->sig->param_count);
7361 return iter->sig->params [i];
7365 mono_TypedReference_ToObject (MonoTypedRef tref)
7367 MONO_ARCH_SAVE_REGS;
7369 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7370 MonoObject** objp = tref.value;
7374 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7378 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7380 MONO_ARCH_SAVE_REGS;
7382 if (MONO_TYPE_IS_REFERENCE (type)) {
7383 MonoObject** objp = value;
7387 return mono_value_box (mono_domain_get (), klass, value);
7391 prelink_method (MonoMethod *method)
7393 const char *exc_class, *exc_arg;
7394 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7396 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7398 mono_raise_exception(
7399 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7401 /* create the wrapper, too? */
7405 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7407 MONO_ARCH_SAVE_REGS;
7408 prelink_method (method->method);
7412 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7414 MonoClass *klass = mono_class_from_mono_type (type->type);
7416 gpointer iter = NULL;
7417 MONO_ARCH_SAVE_REGS;
7419 while ((m = mono_class_get_methods (klass, &iter)))
7423 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7425 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7426 gint32 const **exponents,
7427 gunichar2 const **digitLowerTable,
7428 gunichar2 const **digitUpperTable,
7429 gint64 const **tenPowersList,
7430 gint32 const **decHexDigits)
7432 *mantissas = Formatter_MantissaBitsTable;
7433 *exponents = Formatter_TensExponentTable;
7434 *digitLowerTable = Formatter_DigitLowerTable;
7435 *digitUpperTable = Formatter_DigitUpperTable;
7436 *tenPowersList = Formatter_TenPowersList;
7437 *decHexDigits = Formatter_DecHexDigits;
7440 /* These parameters are "readonly" in corlib/System/Char.cs */
7442 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7443 guint8 const **numeric_data,
7444 gdouble const **numeric_data_values,
7445 guint16 const **to_lower_data_low,
7446 guint16 const **to_lower_data_high,
7447 guint16 const **to_upper_data_low,
7448 guint16 const **to_upper_data_high)
7450 *category_data = CategoryData;
7451 *numeric_data = NumericData;
7452 *numeric_data_values = NumericDataValues;
7453 *to_lower_data_low = ToLowerDataLow;
7454 *to_lower_data_high = ToLowerDataHigh;
7455 *to_upper_data_low = ToUpperDataLow;
7456 *to_upper_data_high = ToUpperDataHigh;
7460 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7462 return method->method->token;
7466 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7467 * and avoid useless allocations.
7470 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7474 for (i = 0; i < type->num_mods; ++i) {
7475 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7480 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7482 for (i = 0; i < type->num_mods; ++i) {
7483 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7484 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7485 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7493 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7495 MonoType *type = param->ClassImpl->type;
7496 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7497 MonoImage *image = method->method->klass->image;
7498 int pos = param->PositionImpl;
7499 MonoMethodSignature *sig = mono_method_signature (method->method);
7503 type = sig->params [pos];
7505 return type_array_from_modifiers (image, type, optional);
7509 get_property_type (MonoProperty *prop)
7511 MonoMethodSignature *sig;
7513 sig = mono_method_signature (prop->get);
7515 } else if (prop->set) {
7516 sig = mono_method_signature (prop->set);
7517 return sig->params [sig->param_count - 1];
7523 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7525 MonoType *type = get_property_type (property->property);
7526 MonoImage *image = property->klass->image;
7530 return type_array_from_modifiers (image, type, optional);
7534 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7536 MonoCustomAttrInfo *cinfo;
7539 cinfo = mono_reflection_get_custom_attrs_info (obj);
7542 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7544 mono_custom_attrs_free (cinfo);
7549 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7551 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7553 if (mono_loader_get_last_error ()) {
7554 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7555 g_assert_not_reached ();
7564 ves_icall_Mono_Runtime_GetDisplayName (void)
7566 static const char display_name_str [] = "Mono " VERSION;
7567 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7568 return display_name;
7572 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7574 MonoString *message;
7578 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7579 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7582 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7584 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7592 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7593 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7594 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7595 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7596 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7597 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7598 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7599 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7603 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7608 gunichar2 last, prev_last, prev2_last;
7616 last = prev_last = 0, prev2_last = 0;
7617 for (i = 0; i < ilength; i++) {
7619 if (c >= sizeof (dbase64)) {
7620 exc = mono_exception_from_name_msg (mono_get_corlib (),
7621 "System", "FormatException",
7622 "Invalid character found.");
7623 mono_raise_exception (exc);
7624 } else if (isspace (c)) {
7627 prev2_last = prev_last;
7633 olength = ilength - ignored;
7635 if (allowWhitespaceOnly && olength == 0) {
7636 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7639 if ((olength & 3) != 0 || olength <= 0) {
7640 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7641 "FormatException", "Invalid length.");
7642 mono_raise_exception (exc);
7645 if (prev2_last == '=') {
7646 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7647 mono_raise_exception (exc);
7650 olength = (olength * 3) / 4;
7654 if (prev_last == '=')
7657 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7658 res_ptr = mono_array_addr (result, guchar, 0);
7659 for (i = 0; i < ilength; ) {
7662 for (k = 0; k < 4 && i < ilength;) {
7668 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7669 exc = mono_exception_from_name_msg (mono_get_corlib (),
7670 "System", "FormatException",
7671 "Invalid character found.");
7672 mono_raise_exception (exc);
7677 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7679 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7681 *res_ptr++ = (b [2] << 6) | b [3];
7683 while (i < ilength && isspace (start [i]))
7691 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7693 MONO_ARCH_SAVE_REGS;
7695 return base64_to_byte_array (mono_string_chars (str),
7696 mono_string_length (str), allowWhitespaceOnly);
7700 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7702 MONO_ARCH_SAVE_REGS;
7704 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7708 #define ICALL_TYPE(id,name,first)
7709 #define ICALL(id,name,func) Icall_ ## id,
7712 #include "metadata/icall-def.h"
7718 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7719 #define ICALL(id,name,func)
7721 #include "metadata/icall-def.h"
7727 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7728 #define ICALL(id,name,func)
7730 guint16 first_icall;
7733 static const IcallTypeDesc
7734 icall_type_descs [] = {
7735 #include "metadata/icall-def.h"
7739 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7742 #define ICALL_TYPE(id,name,first)
7745 #ifdef HAVE_ARRAY_ELEM_INIT
7746 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7747 #define MSGSTRFIELD1(line) str##line
7749 static const struct msgstrtn_t {
7750 #define ICALL(id,name,func)
7752 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7753 #include "metadata/icall-def.h"
7755 } icall_type_names_str = {
7756 #define ICALL_TYPE(id,name,first) (name),
7757 #include "metadata/icall-def.h"
7760 static const guint16 icall_type_names_idx [] = {
7761 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7762 #include "metadata/icall-def.h"
7765 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7767 static const struct msgstr_t {
7769 #define ICALL_TYPE(id,name,first)
7770 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7771 #include "metadata/icall-def.h"
7773 } icall_names_str = {
7774 #define ICALL(id,name,func) (name),
7775 #include "metadata/icall-def.h"
7778 static const guint16 icall_names_idx [] = {
7779 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7780 #include "metadata/icall-def.h"
7783 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7789 #define ICALL_TYPE(id,name,first) name,
7790 #define ICALL(id,name,func)
7791 static const char* const
7792 icall_type_names [] = {
7793 #include "metadata/icall-def.h"
7797 #define icall_type_name_get(id) (icall_type_names [(id)])
7801 #define ICALL_TYPE(id,name,first)
7802 #define ICALL(id,name,func) name,
7803 static const char* const
7805 #include "metadata/icall-def.h"
7808 #define icall_name_get(id) icall_names [(id)]
7810 #endif /* !HAVE_ARRAY_ELEM_INIT */
7814 #define ICALL_TYPE(id,name,first)
7815 #define ICALL(id,name,func) func,
7816 static const gconstpointer
7817 icall_functions [] = {
7818 #include "metadata/icall-def.h"
7822 static GHashTable *icall_hash = NULL;
7823 static GHashTable *jit_icall_hash_name = NULL;
7824 static GHashTable *jit_icall_hash_addr = NULL;
7827 mono_icall_init (void)
7831 /* check that tables are sorted: disable in release */
7834 const char *prev_class = NULL;
7835 const char *prev_method;
7837 for (i = 0; i < Icall_type_num; ++i) {
7838 const IcallTypeDesc *desc;
7841 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7842 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7843 prev_class = icall_type_name_get (i);
7844 desc = &icall_type_descs [i];
7845 num_icalls = icall_desc_num_icalls (desc);
7846 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7847 for (j = 0; j < num_icalls; ++j) {
7848 const char *methodn = icall_name_get (desc->first_icall + j);
7849 if (prev_method && strcmp (prev_method, methodn) >= 0)
7850 g_print ("method %s should come before method %s\n", methodn, prev_method);
7851 prev_method = methodn;
7856 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7860 mono_icall_cleanup (void)
7862 g_hash_table_destroy (icall_hash);
7863 g_hash_table_destroy (jit_icall_hash_name);
7864 g_hash_table_destroy (jit_icall_hash_addr);
7868 mono_add_internal_call (const char *name, gconstpointer method)
7870 mono_loader_lock ();
7872 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7874 mono_loader_unlock ();
7877 #ifdef HAVE_ARRAY_ELEM_INIT
7879 compare_method_imap (const void *key, const void *elem)
7881 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7882 return strcmp (key, method_name);
7886 find_method_icall (const IcallTypeDesc *imap, const char *name)
7888 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7891 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7895 compare_class_imap (const void *key, const void *elem)
7897 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7898 return strcmp (key, class_name);
7901 static const IcallTypeDesc*
7902 find_class_icalls (const char *name)
7904 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7907 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7912 compare_method_imap (const void *key, const void *elem)
7914 const char** method_name = (const char**)elem;
7915 return strcmp (key, *method_name);
7919 find_method_icall (const IcallTypeDesc *imap, const char *name)
7921 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7924 return (gpointer)icall_functions [(nameslot - icall_names)];
7928 compare_class_imap (const void *key, const void *elem)
7930 const char** class_name = (const char**)elem;
7931 return strcmp (key, *class_name);
7934 static const IcallTypeDesc*
7935 find_class_icalls (const char *name)
7937 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7940 return &icall_type_descs [nameslot - icall_type_names];
7946 * we should probably export this as an helper (handle nested types).
7947 * Returns the number of chars written in buf.
7950 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7952 int nspacelen, cnamelen;
7953 nspacelen = strlen (klass->name_space);
7954 cnamelen = strlen (klass->name);
7955 if (nspacelen + cnamelen + 2 > bufsize)
7958 memcpy (buf, klass->name_space, nspacelen);
7959 buf [nspacelen ++] = '.';
7961 memcpy (buf + nspacelen, klass->name, cnamelen);
7962 buf [nspacelen + cnamelen] = 0;
7963 return nspacelen + cnamelen;
7967 mono_lookup_internal_call (MonoMethod *method)
7972 int typelen = 0, mlen, siglen;
7974 const IcallTypeDesc *imap;
7976 g_assert (method != NULL);
7978 if (method->is_inflated)
7979 method = ((MonoMethodInflated *) method)->declaring;
7981 if (method->klass->nested_in) {
7982 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7986 mname [pos++] = '/';
7989 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7995 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8000 imap = find_class_icalls (mname);
8002 mname [typelen] = ':';
8003 mname [typelen + 1] = ':';
8005 mlen = strlen (method->name);
8006 memcpy (mname + typelen + 2, method->name, mlen);
8007 sigstart = mname + typelen + 2 + mlen;
8010 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8011 siglen = strlen (tmpsig);
8012 if (typelen + mlen + siglen + 6 > sizeof (mname))
8015 memcpy (sigstart + 1, tmpsig, siglen);
8016 sigstart [siglen + 1] = ')';
8017 sigstart [siglen + 2] = 0;
8020 mono_loader_lock ();
8022 res = g_hash_table_lookup (icall_hash, mname);
8024 mono_loader_unlock ();
8027 /* try without signature */
8029 res = g_hash_table_lookup (icall_hash, mname);
8031 mono_loader_unlock ();
8035 /* it wasn't found in the static call tables */
8037 mono_loader_unlock ();
8040 res = find_method_icall (imap, sigstart - mlen);
8042 mono_loader_unlock ();
8045 /* try _with_ signature */
8047 res = find_method_icall (imap, sigstart - mlen);
8049 mono_loader_unlock ();
8053 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8054 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8055 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8056 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8057 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");
8058 g_print ("If you see other errors or faults after this message they are probably related\n");
8059 g_print ("and you need to fix your mono install first.\n");
8061 mono_loader_unlock ();
8067 type_from_typename (char *typename)
8069 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8071 if (!strcmp (typename, "int"))
8072 klass = mono_defaults.int_class;
8073 else if (!strcmp (typename, "ptr"))
8074 klass = mono_defaults.int_class;
8075 else if (!strcmp (typename, "void"))
8076 klass = mono_defaults.void_class;
8077 else if (!strcmp (typename, "int32"))
8078 klass = mono_defaults.int32_class;
8079 else if (!strcmp (typename, "uint32"))
8080 klass = mono_defaults.uint32_class;
8081 else if (!strcmp (typename, "int8"))
8082 klass = mono_defaults.sbyte_class;
8083 else if (!strcmp (typename, "uint8"))
8084 klass = mono_defaults.byte_class;
8085 else if (!strcmp (typename, "int16"))
8086 klass = mono_defaults.int16_class;
8087 else if (!strcmp (typename, "uint16"))
8088 klass = mono_defaults.uint16_class;
8089 else if (!strcmp (typename, "long"))
8090 klass = mono_defaults.int64_class;
8091 else if (!strcmp (typename, "ulong"))
8092 klass = mono_defaults.uint64_class;
8093 else if (!strcmp (typename, "float"))
8094 klass = mono_defaults.single_class;
8095 else if (!strcmp (typename, "double"))
8096 klass = mono_defaults.double_class;
8097 else if (!strcmp (typename, "object"))
8098 klass = mono_defaults.object_class;
8099 else if (!strcmp (typename, "obj"))
8100 klass = mono_defaults.object_class;
8101 else if (!strcmp (typename, "string"))
8102 klass = mono_defaults.string_class;
8103 else if (!strcmp (typename, "bool"))
8104 klass = mono_defaults.boolean_class;
8105 else if (!strcmp (typename, "boolean"))
8106 klass = mono_defaults.boolean_class;
8108 g_error ("%s", typename);
8109 g_assert_not_reached ();
8111 return &klass->byval_arg;
8114 MonoMethodSignature*
8115 mono_create_icall_signature (const char *sigstr)
8120 MonoMethodSignature *res;
8122 mono_loader_lock ();
8123 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8125 mono_loader_unlock ();
8129 parts = g_strsplit (sigstr, " ", 256);
8138 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8141 #ifdef PLATFORM_WIN32
8143 * Under windows, the default pinvoke calling convention is STDCALL but
8146 res->call_convention = MONO_CALL_C;
8149 res->ret = type_from_typename (parts [0]);
8150 for (i = 1; i < len; ++i) {
8151 res->params [i - 1] = type_from_typename (parts [i]);
8156 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8158 mono_loader_unlock ();
8164 mono_find_jit_icall_by_name (const char *name)
8166 MonoJitICallInfo *info;
8167 g_assert (jit_icall_hash_name);
8169 mono_loader_lock ();
8170 info = g_hash_table_lookup (jit_icall_hash_name, name);
8171 mono_loader_unlock ();
8176 mono_find_jit_icall_by_addr (gconstpointer addr)
8178 MonoJitICallInfo *info;
8179 g_assert (jit_icall_hash_addr);
8181 mono_loader_lock ();
8182 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8183 mono_loader_unlock ();
8189 * mono_get_jit_icall_info:
8191 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8192 * caller should access it while holding the loader lock.
8195 mono_get_jit_icall_info (void)
8197 return jit_icall_hash_name;
8201 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8203 mono_loader_lock ();
8204 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8205 mono_loader_unlock ();
8209 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8211 MonoJitICallInfo *info;
8216 mono_loader_lock ();
8218 if (!jit_icall_hash_name) {
8219 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8220 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8223 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8224 g_warning ("jit icall already defined \"%s\"\n", name);
8225 g_assert_not_reached ();
8228 info = g_new0 (MonoJitICallInfo, 1);
8235 info->wrapper = func;
8237 info->wrapper = NULL;
8240 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8241 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8243 mono_loader_unlock ();