Merge pull request #4723 from lambdageek/bug-54485
[mono.git] / mono / metadata / class.c
1 /**
2  * \file
3  * Class management for the Mono runtime
4  *
5  * Author:
6  *   Miguel de Icaza (miguel@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/tabledefs.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/class-internals.h>
31 #include <mono/metadata/object.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-endian.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/security-manager.h>
38 #include <mono/metadata/security-core-clr.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/utils/mono-counters.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/mono-logger-internals.h>
47 #include <mono/utils/mono-memory-model.h>
48 #include <mono/utils/atomic.h>
49 #include <mono/utils/bsearch.h>
50 #include <mono/utils/checked-build.h>
51
52 MonoStats mono_stats;
53
54 gboolean mono_print_vtable = FALSE;
55 gboolean mono_align_small_structs = FALSE;
56
57 /* Statistics */
58 guint32 inflated_classes_size, inflated_methods_size;
59 guint32 classes_size, class_ext_size, class_ext_count;
60 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61
62 /* Low level lock which protects data structures in this module */
63 static mono_mutex_t classes_mutex;
64
65 /* Function supplied by the runtime to find classes by name using information from the AOT file */
66 static MonoGetClassFromName get_class_from_name = NULL;
67
68 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
69 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
70 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
71 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
72 static int generic_array_methods (MonoClass *klass);
73 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
74
75 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
76 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
77 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
78 static guint32 mono_field_resolve_flags (MonoClassField *field);
79 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
80 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81
82 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
83
84
85 /*
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
87
88 Given the following type hierarchy:
89
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
93 class Input<T> {}
94
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded 
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
106
107 */
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
114
115 static MonoNativeTlsKey init_pending_tls_id;
116
117 static inline void
118 classes_lock (void)
119 {
120         mono_locks_os_acquire (&classes_mutex, ClassesLock);
121 }
122
123 static inline void
124 classes_unlock (void)
125 {
126         mono_locks_os_release (&classes_mutex, ClassesLock);
127 }
128
129 /* 
130  * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
131 */
132 static void
133 enable_gclass_recording (void)
134 {
135         ++record_gclass_instantiation;
136 }
137
138 /* 
139  * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
140 */
141 static void
142 disable_gclass_recording (gclass_record_func func, void *user_data)
143 {
144         GSList **head = &gclass_recorded_list;
145
146         g_assert (record_gclass_instantiation > 0);
147         --record_gclass_instantiation;
148
149         while (*head) {
150                 GSList *node = *head;
151                 if (func ((MonoClass*)node->data, user_data)) {
152                         *head = node->next;
153                         g_slist_free_1 (node);
154                 } else {
155                         head = &node->next;
156                 }
157         }
158
159         /* We automatically discard all recorded gclasses when disabled. */
160         if (!record_gclass_instantiation && gclass_recorded_list) {
161                 g_slist_free (gclass_recorded_list);
162                 gclass_recorded_list = NULL;
163         }
164 }
165
166 /**
167  * mono_class_from_typeref:
168  * \param image a MonoImage
169  * \param type_token a TypeRef token
170  *
171  * Creates the \c MonoClass* structure representing the type defined by
172  * the typeref token valid inside \p image.
173  * \returns The \c MonoClass* representing the typeref token, or NULL if it could
174  * not be loaded.
175  */
176 MonoClass *
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
178 {
179         MonoError error;
180         MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
182         return klass;
183 }
184
185 /**
186  * mono_class_from_typeref_checked:
187  * \param image a MonoImage
188  * \param type_token a TypeRef token
189  * \param error error return code, if any.
190  *
191  * Creates the \c MonoClass* structure representing the type defined by
192  * the typeref token valid inside \p image.
193  *
194  * \returns The \c MonoClass* representing the typeref token, NULL if it could
195  * not be loaded with the \p error value filled with the information about the
196  * error.
197  */
198 MonoClass *
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
200 {
201         guint32 cols [MONO_TYPEREF_SIZE];
202         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
203         guint32 idx;
204         const char *name, *nspace;
205         MonoClass *res = NULL;
206         MonoImage *module;
207
208         error_init (error);
209
210         if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
211                 return NULL;
212
213         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
214
215         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
217
218         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220         case MONO_RESOLUTION_SCOPE_MODULE:
221                 /*
222                 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223                 This is not the observed behavior of existing implementations.
224                 The defacto behavior is that it's just a typedef in disguise.
225                 */
226                 /* a typedef in disguise */
227                 res = mono_class_from_name_checked (image, nspace, name, error);
228                 goto done;
229
230         case MONO_RESOLUTION_SCOPE_MODULEREF:
231                 module = mono_image_load_module_checked (image, idx, error);
232                 if (module)
233                         res = mono_class_from_name_checked (module, nspace, name, error);
234                 goto done;
235
236         case MONO_RESOLUTION_SCOPE_TYPEREF: {
237                 MonoClass *enclosing;
238                 GList *tmp;
239
240                 if (idx == mono_metadata_token_index (type_token)) {
241                         mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
242                         return NULL;
243                 }
244
245                 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error); 
246                 return_val_if_nok (error, NULL);
247
248                 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
249                 if (enclosing->nested_classes_inited && nested_classes) {
250                         /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
251                         for (tmp = nested_classes; tmp; tmp = tmp->next) {
252                                 res = (MonoClass *)tmp->data;
253                                 if (strcmp (res->name, name) == 0)
254                                         return res;
255                         }
256                 } else {
257                         /* Don't call mono_class_init as we might've been called by it recursively */
258                         int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
259                         while (i) {
260                                 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
261                                 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
262                                 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
263
264                                 if (strcmp (nname, name) == 0)
265                                         return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
266
267                                 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
268                         }
269                 }
270                 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
271                 goto done;
272         }
273         case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
274                 break;
275         }
276
277         if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
278                 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
279                 return NULL;
280         }
281
282         if (!image->references || !image->references [idx - 1])
283                 mono_assembly_load_reference (image, idx - 1);
284         g_assert (image->references [idx - 1]);
285
286         /* If the assembly did not load, register this as a type load exception */
287         if (image->references [idx - 1] == REFERENCE_MISSING){
288                 MonoAssemblyName aname;
289                 char *human_name;
290                 
291                 mono_assembly_get_assemblyref (image, idx - 1, &aname);
292                 human_name = mono_stringify_assembly_name (&aname);
293                 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
294                 return NULL;
295         }
296
297         res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
298
299 done:
300         /* Generic case, should be avoided for when a better error is possible. */
301         if (!res && mono_error_ok (error)) {
302                 char *name = mono_class_name_from_token (image, type_token);
303                 char *assembly = mono_assembly_name_from_token (image, type_token);
304                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (from typeref, class/assembly %s, %s)", type_token, name, assembly);
305         }
306         return res;
307 }
308
309
310 static void *
311 mono_image_memdup (MonoImage *image, void *data, guint size)
312 {
313         void *res = mono_image_alloc (image, size);
314         memcpy (res, data, size);
315         return res;
316 }
317         
318 /* Copy everything mono_metadata_free_array free. */
319 MonoArrayType *
320 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
321 {
322         if (image) {
323                 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
324                 if (a->sizes)
325                         a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
326                 if (a->lobounds)
327                         a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
328         } else {
329                 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
330                 if (a->sizes)
331                         a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
332                 if (a->lobounds)
333                         a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
334         }
335         return a;
336 }
337
338 /* Copy everything mono_metadata_free_method_signature free. */
339 MonoMethodSignature*
340 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
341 {
342         int i;
343         
344         sig = mono_metadata_signature_dup_full (image, sig);
345         
346         sig->ret = mono_metadata_type_dup (image, sig->ret);
347         for (i = 0; i < sig->param_count; ++i)
348                 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
349         
350         return sig;
351 }
352
353 static void
354 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
355 {
356         MonoAssembly *ta = klass->image->assembly;
357         char *name;
358
359         name = mono_stringify_assembly_name (&ta->aname);
360         g_string_append_printf (str, ", %s", name);
361         g_free (name);
362 }
363
364 static inline void
365 mono_type_name_check_byref (MonoType *type, GString *str)
366 {
367         if (type->byref)
368                 g_string_append_c (str, '&');
369 }
370
371 /**
372  * mono_identifier_escape_type_name_chars:
373  * \param str a destination string
374  * \param identifier an IDENTIFIER in internal form
375  *
376  * \returns \p str
377  *
378  * The displayed form of the identifier is appended to str.
379  *
380  * The displayed form of an identifier has the characters ,+&*[]\
381  * that have special meaning in type names escaped with a preceeding
382  * backslash (\) character.
383  */
384 static GString*
385 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
386 {
387         if (!identifier)
388                 return str;
389
390         size_t n = str->len;
391         // reserve space for common case: there will be no escaped characters.
392         g_string_set_size(str, n + strlen(identifier));
393         g_string_set_size(str, n);
394
395         for (const char* s = identifier; *s != 0 ; s++) {
396                 switch (*s) {
397                 case ',':
398                 case '+':
399                 case '&':
400                 case '*':
401                 case '[':
402                 case ']':
403                 case '\\':
404                         g_string_append_c (str, '\\');
405                         g_string_append_c (str, *s);
406                         break;
407                 default:
408                         g_string_append_c (str, *s);
409                         break;
410                 }
411         }
412         return str;
413 }
414
415 static void
416 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
417                             MonoTypeNameFormat format)
418 {
419         MonoClass *klass;
420         
421         switch (type->type) {
422         case MONO_TYPE_ARRAY: {
423                 int i, rank = type->data.array->rank;
424                 MonoTypeNameFormat nested_format;
425
426                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428
429                 mono_type_get_name_recurse (
430                         &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
431                 g_string_append_c (str, '[');
432                 if (rank == 1)
433                         g_string_append_c (str, '*');
434                 for (i = 1; i < rank; i++)
435                         g_string_append_c (str, ',');
436                 g_string_append_c (str, ']');
437                 
438                 mono_type_name_check_byref (type, str);
439
440                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
441                         _mono_type_get_assembly_name (type->data.array->eklass, str);
442                 break;
443         }
444         case MONO_TYPE_SZARRAY: {
445                 MonoTypeNameFormat nested_format;
446
447                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
448                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
449
450                 mono_type_get_name_recurse (
451                         &type->data.klass->byval_arg, str, FALSE, nested_format);
452                 g_string_append (str, "[]");
453                 
454                 mono_type_name_check_byref (type, str);
455
456                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
457                         _mono_type_get_assembly_name (type->data.klass, str);
458                 break;
459         }
460         case MONO_TYPE_PTR: {
461                 MonoTypeNameFormat nested_format;
462
463                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
464                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
465
466                 mono_type_get_name_recurse (
467                         type->data.type, str, FALSE, nested_format);
468                 g_string_append_c (str, '*');
469
470                 mono_type_name_check_byref (type, str);
471
472                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
473                         _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
474                 break;
475         }
476         case MONO_TYPE_VAR:
477         case MONO_TYPE_MVAR:
478                 if (!mono_generic_param_info (type->data.generic_param))
479                         g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
480                 else
481                         g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
482
483                 mono_type_name_check_byref (type, str);
484
485                 break;
486         default:
487                 klass = mono_class_from_mono_type (type);
488                 if (klass->nested_in) {
489                         mono_type_get_name_recurse (
490                                 &klass->nested_in->byval_arg, str, TRUE, format);
491                         if (format == MONO_TYPE_NAME_FORMAT_IL)
492                                 g_string_append_c (str, '.');
493                         else
494                                 g_string_append_c (str, '+');
495                 } else if (*klass->name_space) {
496                         if (format == MONO_TYPE_NAME_FORMAT_IL)
497                                 g_string_append (str, klass->name_space);
498                         else
499                                 mono_identifier_escape_type_name_chars (str, klass->name_space);
500                         g_string_append_c (str, '.');
501                 }
502                 if (format == MONO_TYPE_NAME_FORMAT_IL) {
503                         char *s = strchr (klass->name, '`');
504                         int len = s ? s - klass->name : strlen (klass->name);
505                         g_string_append_len (str, klass->name, len);
506                 } else {
507                         mono_identifier_escape_type_name_chars (str, klass->name);
508                 }
509                 if (is_recursed)
510                         break;
511                 if (mono_class_is_ginst (klass)) {
512                         MonoGenericClass *gclass = mono_class_get_generic_class (klass);
513                         MonoGenericInst *inst = gclass->context.class_inst;
514                         MonoTypeNameFormat nested_format;
515                         int i;
516
517                         nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
518                                 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
519
520                         if (format == MONO_TYPE_NAME_FORMAT_IL)
521                                 g_string_append_c (str, '<');
522                         else
523                                 g_string_append_c (str, '[');
524                         for (i = 0; i < inst->type_argc; i++) {
525                                 MonoType *t = inst->type_argv [i];
526
527                                 if (i)
528                                         g_string_append_c (str, ',');
529                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531                                         g_string_append_c (str, '[');
532                                 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
533                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535                                         g_string_append_c (str, ']');
536                         }
537                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
538                                 g_string_append_c (str, '>');
539                         else
540                                 g_string_append_c (str, ']');
541                 } else if (mono_class_is_gtd (klass) &&
542                            (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
543                            (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
544                         int i;
545
546                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
547                                 g_string_append_c (str, '<');
548                         else
549                                 g_string_append_c (str, '[');
550                         for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
551                                 if (i)
552                                         g_string_append_c (str, ',');
553                                 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
554                         }
555                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
556                                 g_string_append_c (str, '>');
557                         else
558                                 g_string_append_c (str, ']');
559                 }
560
561                 mono_type_name_check_byref (type, str);
562
563                 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
564                     (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
565                         _mono_type_get_assembly_name (klass, str);
566                 break;
567         }
568 }
569
570 /**
571  * mono_type_get_name_full:
572  * \param type a type
573  * \param format the format for the return string.
574  *
575  * 
576  * \returns The string representation in a number of formats:
577  *
578  * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
579  * returned in the format required by \c System.Reflection, this is the
580  * inverse of mono_reflection_parse_type().
581  *
582  * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
583  * be used by the IL assembler.
584  *
585  * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
586  *
587  * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
588  */
589 char*
590 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
591 {
592         GString* result;
593
594         result = g_string_new ("");
595
596         mono_type_get_name_recurse (type, result, FALSE, format);
597
598         return g_string_free (result, FALSE);
599 }
600
601 /**
602  * mono_type_get_full_name:
603  * \param class a class
604  *
605  * \returns The string representation for type as required by System.Reflection.
606  * The inverse of mono_reflection_parse_type().
607  */
608 char *
609 mono_type_get_full_name (MonoClass *klass)
610 {
611         return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
612 }
613
614 /**
615  * mono_type_get_name:
616  * \param type a type
617  * \returns The string representation for type as it would be represented in IL code.
618  */
619 char*
620 mono_type_get_name (MonoType *type)
621 {
622         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
623 }
624
625 /**
626  * mono_type_get_underlying_type:
627  * \param type a type
628  * \returns The \c MonoType for the underlying integer type if \p type
629  * is an enum and byref is false, otherwise the type itself.
630  */
631 MonoType*
632 mono_type_get_underlying_type (MonoType *type)
633 {
634         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
635                 return mono_class_enum_basetype (type->data.klass);
636         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
637                 return mono_class_enum_basetype (type->data.generic_class->container_class);
638         return type;
639 }
640
641 /**
642  * mono_class_is_open_constructed_type:
643  * \param type a type
644  *
645  * \returns TRUE if type represents a generics open constructed type.
646  * IOW, not all type parameters required for the instantiation have
647  * been provided or it's a generic type definition.
648  *
649  * An open constructed type means it's a non realizable type. Not to
650  * be mixed up with an abstract type - we can't cast or dispatch to
651  * an open type, for example.
652  */
653 gboolean
654 mono_class_is_open_constructed_type (MonoType *t)
655 {
656         switch (t->type) {
657         case MONO_TYPE_VAR:
658         case MONO_TYPE_MVAR:
659                 return TRUE;
660         case MONO_TYPE_SZARRAY:
661                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
662         case MONO_TYPE_ARRAY:
663                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
664         case MONO_TYPE_PTR:
665                 return mono_class_is_open_constructed_type (t->data.type);
666         case MONO_TYPE_GENERICINST:
667                 return t->data.generic_class->context.class_inst->is_open;
668         case MONO_TYPE_CLASS:
669         case MONO_TYPE_VALUETYPE:
670                 return mono_class_is_gtd (t->data.klass);
671         default:
672                 return FALSE;
673         }
674 }
675
676 /*
677 This is a simple function to catch the most common bad instances of generic types.
678 Specially those that might lead to further failures in the runtime.
679 */
680 static gboolean
681 is_valid_generic_argument (MonoType *type)
682 {
683         switch (type->type) {
684         case MONO_TYPE_VOID:
685         //case MONO_TYPE_TYPEDBYREF:
686                 return FALSE;
687         default:
688                 return TRUE;
689         }
690 }
691
692 static MonoType*
693 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
694 {
695         error_init (error);
696
697         switch (type->type) {
698         case MONO_TYPE_MVAR: {
699                 MonoType *nt;
700                 int num = mono_type_get_generic_param_num (type);
701                 MonoGenericInst *inst = context->method_inst;
702                 if (!inst)
703                         return NULL;
704                 if (num >= inst->type_argc) {
705                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706                         mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
707                                 num, info ? info->name : "", inst->type_argc);
708                         return NULL;
709                 }
710
711                 if (!is_valid_generic_argument (inst->type_argv [num])) {
712                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
713                         mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
714                                 num, info ? info->name : "", inst->type_argv [num]->type);
715                         return NULL;                    
716                 }
717                 /*
718                  * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
719                  * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
720                  * ->byref and ->attrs from @type are propagated to the returned type.
721                  */
722                 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
723                 nt->byref = type->byref;
724                 nt->attrs = type->attrs;
725                 return nt;
726         }
727         case MONO_TYPE_VAR: {
728                 MonoType *nt;
729                 int num = mono_type_get_generic_param_num (type);
730                 MonoGenericInst *inst = context->class_inst;
731                 if (!inst)
732                         return NULL;
733                 if (num >= inst->type_argc) {
734                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735                         mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
736                                 num, info ? info->name : "", inst->type_argc);
737                         return NULL;
738                 }
739                 if (!is_valid_generic_argument (inst->type_argv [num])) {
740                         MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
741                         mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
742                                 num, info ? info->name : "", inst->type_argv [num]->type);
743                         return NULL;                    
744                 }
745                 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
746                 nt->byref = type->byref;
747                 nt->attrs = type->attrs;
748                 return nt;
749         }
750         case MONO_TYPE_SZARRAY: {
751                 MonoClass *eclass = type->data.klass;
752                 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
753                 if (!inflated || !mono_error_ok (error))
754                         return NULL;
755                 nt = mono_metadata_type_dup (image, type);
756                 nt->data.klass = mono_class_from_mono_type (inflated);
757                 mono_metadata_free_type (inflated);
758                 return nt;
759         }
760         case MONO_TYPE_ARRAY: {
761                 MonoClass *eclass = type->data.array->eklass;
762                 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
763                 if (!inflated || !mono_error_ok (error))
764                         return NULL;
765                 nt = mono_metadata_type_dup (image, type);
766                 nt->data.array->eklass = mono_class_from_mono_type (inflated);
767                 mono_metadata_free_type (inflated);
768                 return nt;
769         }
770         case MONO_TYPE_GENERICINST: {
771                 MonoGenericClass *gclass = type->data.generic_class;
772                 MonoGenericInst *inst;
773                 MonoType *nt;
774                 if (!gclass->context.class_inst->is_open)
775                         return NULL;
776
777                 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
778                 return_val_if_nok (error, NULL);
779
780                 if (inst != gclass->context.class_inst)
781                         gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
782
783                 if (gclass == type->data.generic_class)
784                         return NULL;
785
786                 nt = mono_metadata_type_dup (image, type);
787                 nt->data.generic_class = gclass;
788                 return nt;
789         }
790         case MONO_TYPE_CLASS:
791         case MONO_TYPE_VALUETYPE: {
792                 MonoClass *klass = type->data.klass;
793                 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
794                 MonoGenericInst *inst;
795                 MonoGenericClass *gclass = NULL;
796                 MonoType *nt;
797
798                 if (!container)
799                         return NULL;
800
801                 /* We can't use context->class_inst directly, since it can have more elements */
802                 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
803                 return_val_if_nok (error, NULL);
804
805                 if (inst == container->context.class_inst)
806                         return NULL;
807
808                 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
809
810                 nt = mono_metadata_type_dup (image, type);
811                 nt->type = MONO_TYPE_GENERICINST;
812                 nt->data.generic_class = gclass;
813                 return nt;
814         }
815         default:
816                 return NULL;
817         }
818         return NULL;
819 }
820
821 MonoGenericContext *
822 mono_generic_class_get_context (MonoGenericClass *gclass)
823 {
824         return &gclass->context;
825 }
826
827 MonoGenericContext *
828 mono_class_get_context (MonoClass *klass)
829 {
830         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
831         return gklass ? mono_generic_class_get_context (gklass) : NULL;
832 }
833
834 /*
835  * mono_class_inflate_generic_type_with_mempool:
836  * @mempool: a mempool
837  * @type: a type
838  * @context: a generics context
839  * @error: error context
840  *
841  * The same as mono_class_inflate_generic_type, but allocates the MonoType
842  * from mempool if it is non-NULL.  If it is NULL, the MonoType is
843  * allocated on the heap and is owned by the caller.
844  * The returned type can potentially be the same as TYPE, so it should not be
845  * modified by the caller, and it should be freed using mono_metadata_free_type ().
846  */
847 MonoType*
848 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
849 {
850         MonoType *inflated = NULL;
851         error_init (error);
852
853         if (context)
854                 inflated = inflate_generic_type (image, type, context, error);
855         return_val_if_nok (error, NULL);
856
857         if (!inflated) {
858                 MonoType *shared = mono_metadata_get_shared_type (type);
859
860                 if (shared) {
861                         return shared;
862                 } else {
863                         return mono_metadata_type_dup (image, type);
864                 }
865         }
866
867         mono_stats.inflated_type_count++;
868         return inflated;
869 }
870
871 /**
872  * mono_class_inflate_generic_type:
873  * \param type a type
874  * \param context a generics context
875  * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
876  *
877  * If \p type is a generic type and \p context is not NULL, instantiate it using the 
878  * generics context \p context.
879  *
880  * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
881  * on the heap and is owned by the caller. Returns NULL on error.
882  */
883 MonoType*
884 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
885 {
886         MonoError error;
887         MonoType *result;
888         result = mono_class_inflate_generic_type_checked (type, context, &error);
889         mono_error_cleanup (&error);
890         return result;
891 }
892
893 /*
894  * mono_class_inflate_generic_type:
895  * @type: a type
896  * @context: a generics context
897  * @error: error context to use
898  *
899  * If @type is a generic type and @context is not NULL, instantiate it using the 
900  * generics context @context.
901  *
902  * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
903  * on the heap and is owned by the caller.
904  */
905 MonoType*
906 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
907 {
908         return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
909 }
910
911 /*
912  * mono_class_inflate_generic_type_no_copy:
913  *
914  *   Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
915  * was done.
916  */
917 static MonoType*
918 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
919 {
920         MonoType *inflated = NULL; 
921
922         error_init (error);
923         if (context) {
924                 inflated = inflate_generic_type (image, type, context, error);
925                 return_val_if_nok (error, NULL);
926         }
927
928         if (!inflated)
929                 return type;
930
931         mono_stats.inflated_type_count++;
932         return inflated;
933 }
934
935 /*
936  * mono_class_inflate_generic_class:
937  *
938  *   Inflate the class @gklass with @context. Set @error on failure.
939  */
940 MonoClass*
941 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
942 {
943         MonoClass *res;
944         MonoType *inflated;
945
946         inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
947         return_val_if_nok (error, NULL);
948
949         res = mono_class_from_mono_type (inflated);
950         mono_metadata_free_type (inflated);
951
952         return res;
953 }
954
955 static MonoGenericContext
956 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
957 {
958         MonoGenericInst *class_inst = NULL;
959         MonoGenericInst *method_inst = NULL;
960         MonoGenericContext res = { NULL, NULL };
961
962         error_init (error);
963
964         if (context->class_inst) {
965                 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
966                 if (!mono_error_ok (error))
967                         goto fail;
968         }
969
970         if (context->method_inst) {
971                 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
972                 if (!mono_error_ok (error))
973                         goto fail;
974         }
975
976         res.class_inst = class_inst;
977         res.method_inst = method_inst;
978 fail:
979         return res;
980 }
981
982 /**
983  * mono_class_inflate_generic_method:
984  * \param method a generic method
985  * \param context a generics context
986  *
987  * Instantiate the generic method \p method using the generics context \p context.
988  *
989  * \returns The new instantiated method
990  */
991 MonoMethod *
992 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
993 {
994         return mono_class_inflate_generic_method_full (method, NULL, context);
995 }
996
997 MonoMethod *
998 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
999 {
1000         return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1001 }
1002
1003 /**
1004  * mono_class_inflate_generic_method_full:
1005  *
1006  * Instantiate method \p method with the generic context \p context.
1007  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1008  *         Use mono_method_signature() and mono_method_get_header() to get the correct values.
1009  */
1010 MonoMethod*
1011 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1012 {
1013         MonoError error;
1014         MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1015         if (!mono_error_ok (&error))
1016                 /*FIXME do proper error handling - on this case, kill this function. */
1017                 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error)); 
1018
1019         return res;
1020 }
1021
1022 /**
1023  * mono_class_inflate_generic_method_full_checked:
1024  * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1025  */
1026 MonoMethod*
1027 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1028 {
1029         MonoMethod *result;
1030         MonoMethodInflated *iresult, *cached;
1031         MonoMethodSignature *sig;
1032         MonoGenericContext tmp_context;
1033
1034         error_init (error);
1035
1036         /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1037         while (method->is_inflated) {
1038                 MonoGenericContext *method_context = mono_method_get_context (method);
1039                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1040
1041                 tmp_context = inflate_generic_context (method_context, context, error);
1042                 return_val_if_nok (error, NULL);
1043
1044                 context = &tmp_context;
1045
1046                 if (mono_metadata_generic_context_equal (method_context, context))
1047                         return method;
1048
1049                 method = imethod->declaring;
1050         }
1051
1052         /*
1053          * A method only needs to be inflated if the context has argument for which it is
1054          * parametric. Eg:
1055          * 
1056          * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1057          * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1058          * 
1059          */
1060         if (!((method->is_generic && context->method_inst) || 
1061                 (mono_class_is_gtd (method->klass) && context->class_inst)))
1062                 return method;
1063
1064         iresult = g_new0 (MonoMethodInflated, 1);
1065         iresult->context = *context;
1066         iresult->declaring = method;
1067
1068         if (!context->method_inst && method->is_generic)
1069                 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1070
1071         if (!context->class_inst) {
1072                 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1073                 if (mono_class_is_gtd (iresult->declaring->klass))
1074                         iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1075         }
1076         /* This can happen with some callers like mono_object_get_virtual_method () */
1077         if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1078                 iresult->context.class_inst = NULL;
1079
1080         MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1081
1082         // check cache
1083         mono_image_set_lock (set);
1084         cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1085         mono_image_set_unlock (set);
1086
1087         if (cached) {
1088                 g_free (iresult);
1089                 return (MonoMethod*)cached;
1090         }
1091
1092         mono_stats.inflated_method_count++;
1093
1094         inflated_methods_size += sizeof (MonoMethodInflated);
1095
1096         sig = mono_method_signature (method);
1097         if (!sig) {
1098                 char *name = mono_type_get_full_name (method->klass);
1099                 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1100                 g_free (name);
1101                 goto fail;
1102         }
1103
1104         if (sig->pinvoke) {
1105                 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1106         } else {
1107                 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1108         }
1109
1110         result = (MonoMethod *) iresult;
1111         result->is_inflated = TRUE;
1112         result->is_generic = FALSE;
1113         result->sre_method = FALSE;
1114         result->signature = NULL;
1115
1116         if (method->wrapper_type) {
1117                 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1118                 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1119                 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1120
1121                 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1122                 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1123         }
1124
1125         if (iresult->context.method_inst) {
1126                 /* Set the generic_container of the result to the generic_container of method */
1127                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1128
1129                 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1130                         result->is_generic = 1;
1131                         mono_method_set_generic_container (result, generic_container);
1132                 }
1133         }
1134
1135         if (klass_hint) {
1136                 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1137                 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1138                         klass_hint = NULL;
1139         }
1140
1141         if (mono_class_is_gtd (method->klass))
1142                 result->klass = klass_hint;
1143
1144         if (!result->klass) {
1145                 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1146                 if (!mono_error_ok (error)) 
1147                         goto fail;
1148
1149                 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1150                 if (inflated)
1151                         mono_metadata_free_type (inflated);
1152         }
1153
1154         /*
1155          * FIXME: This should hold, but it doesn't:
1156          *
1157          * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1158          *              mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1159          *      g_assert (result->is_generic);
1160          * }
1161          *
1162          * Fixing this here causes other things to break, hence a very
1163          * ugly hack in mini-trampolines.c - see
1164          * is_generic_method_definition().
1165          */
1166
1167         // check cache
1168         mono_image_set_lock (set);
1169         cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1170         if (!cached) {
1171                 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1172                 iresult->owner = set;
1173                 cached = iresult;
1174         }
1175         mono_image_set_unlock (set);
1176
1177         return (MonoMethod*)cached;
1178
1179 fail:
1180         g_free (iresult);
1181         return NULL;
1182 }
1183
1184 /**
1185  * mono_get_inflated_method:
1186  *
1187  * Obsolete.  We keep it around since it's mentioned in the public API.
1188  */
1189 MonoMethod*
1190 mono_get_inflated_method (MonoMethod *method)
1191 {
1192         return method;
1193 }
1194
1195 /*
1196  * mono_method_get_context_general:
1197  * @method: a method
1198  * @uninflated: handle uninflated methods?
1199  *
1200  * Returns the generic context of a method or NULL if it doesn't have
1201  * one.  For an inflated method that's the context stored in the
1202  * method.  Otherwise it's in the method's generic container or in the
1203  * generic container of the method's class.
1204  */
1205 MonoGenericContext*
1206 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1207 {
1208         if (method->is_inflated) {
1209                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1210                 return &imethod->context;
1211         }
1212         if (!uninflated)
1213                 return NULL;
1214         if (method->is_generic)
1215                 return &(mono_method_get_generic_container (method)->context);
1216         if (mono_class_is_gtd (method->klass))
1217                 return &mono_class_get_generic_container (method->klass)->context;
1218         return NULL;
1219 }
1220
1221 /*
1222  * mono_method_get_context:
1223  * @method: a method
1224  *
1225  * Returns the generic context for method if it's inflated, otherwise
1226  * NULL.
1227  */
1228 MonoGenericContext*
1229 mono_method_get_context (MonoMethod *method)
1230 {
1231         return mono_method_get_context_general (method, FALSE);
1232 }
1233
1234 /*
1235  * mono_method_get_generic_container:
1236  *
1237  *   Returns the generic container of METHOD, which should be a generic method definition.
1238  * Returns NULL if METHOD is not a generic method definition.
1239  * LOCKING: Acquires the loader lock.
1240  */
1241 MonoGenericContainer*
1242 mono_method_get_generic_container (MonoMethod *method)
1243 {
1244         MonoGenericContainer *container;
1245
1246         if (!method->is_generic)
1247                 return NULL;
1248
1249         container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1250         g_assert (container);
1251
1252         return container;
1253 }
1254
1255 /*
1256  * mono_method_set_generic_container:
1257  *
1258  *   Sets the generic container of METHOD to CONTAINER.
1259  * LOCKING: Acquires the image lock.
1260  */
1261 void
1262 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1263 {
1264         g_assert (method->is_generic);
1265
1266         mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1267 }
1268
1269 /** 
1270  * mono_class_find_enum_basetype:
1271  * \param class The enum class
1272  *
1273  *   Determine the basetype of an enum by iterating through its fields. We do this
1274  * in a separate function since it is cheaper than calling mono_class_setup_fields.
1275  */
1276 static MonoType*
1277 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1278 {
1279         MonoGenericContainer *container = NULL;
1280         MonoImage *m = klass->image;
1281         const int top = mono_class_get_field_count (klass);
1282         int i, first_field_idx;
1283
1284         g_assert (klass->enumtype);
1285
1286         error_init (error);
1287
1288         container = mono_class_try_get_generic_container (klass);
1289         if (mono_class_is_ginst (klass)) {
1290                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1291
1292                 container = mono_class_get_generic_container (gklass);
1293                 g_assert (container);
1294         }
1295
1296         /*
1297          * Fetch all the field information.
1298          */
1299         first_field_idx = mono_class_get_first_field_idx (klass);
1300         for (i = 0; i < top; i++){
1301                 const char *sig;
1302                 guint32 cols [MONO_FIELD_SIZE];
1303                 int idx = first_field_idx + i;
1304                 MonoType *ftype;
1305
1306                 /* first_field_idx and idx points into the fieldptr table */
1307                 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1308
1309                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1310                         continue;
1311
1312                 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1313                         mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1314                         goto fail;
1315                 }
1316
1317                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1318                 mono_metadata_decode_value (sig, &sig);
1319                 /* FIELD signature == 0x06 */
1320                 if (*sig != 0x06) {
1321                         mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1322                         goto fail;
1323                 }
1324
1325                 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1326                 if (!ftype)
1327                         goto fail;
1328
1329                 if (mono_class_is_ginst (klass)) {
1330                         //FIXME do we leak here?
1331                         ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1332                         if (!mono_error_ok (error))
1333                                 goto fail;
1334                         ftype->attrs = cols [MONO_FIELD_FLAGS];
1335                 }
1336
1337                 return ftype;
1338         }
1339         mono_error_set_type_load_class (error, klass, "Could not find base type");
1340
1341 fail:
1342         return NULL;
1343 }
1344
1345 /*
1346  * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1347  */
1348 static gboolean
1349 mono_type_has_exceptions (MonoType *type)
1350 {
1351         switch (type->type) {
1352         case MONO_TYPE_CLASS:
1353         case MONO_TYPE_VALUETYPE:
1354         case MONO_TYPE_SZARRAY:
1355                 return mono_class_has_failure (type->data.klass);
1356         case MONO_TYPE_ARRAY:
1357                 return mono_class_has_failure (type->data.array->eklass);
1358         case MONO_TYPE_GENERICINST:
1359                 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1360         default:
1361                 return FALSE;
1362         }
1363 }
1364
1365 void
1366 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1367 {
1368         g_assert (mono_class_has_failure (klass));
1369         MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1370         mono_error_set_from_boxed (oerror, box);
1371 }
1372
1373 /*
1374  * mono_class_alloc:
1375  *
1376  *   Allocate memory for some data belonging to CLASS, either from its image's mempool,
1377  * or from the heap.
1378  */
1379 gpointer
1380 mono_class_alloc (MonoClass *klass, int size)
1381 {
1382         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1383         if (gklass)
1384                 return mono_image_set_alloc (gklass->owner, size);
1385         else
1386                 return mono_image_alloc (klass->image, size);
1387 }
1388
1389 gpointer
1390 mono_class_alloc0 (MonoClass *klass, int size)
1391 {
1392         gpointer res;
1393
1394         res = mono_class_alloc (klass, size);
1395         memset (res, 0, size);
1396         return res;
1397 }
1398
1399 #define mono_class_new0(klass,struct_type, n_structs)           \
1400     ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1401
1402 /**
1403  * mono_class_setup_basic_field_info:
1404  * \param class The class to initialize
1405  *
1406  * Initializes the following fields in MonoClass:
1407  * * klass->fields (only field->parent and field->name)
1408  * * klass->field.count
1409  * * klass->first_field_idx
1410  * LOCKING: Acquires the loader lock
1411  */
1412 static void
1413 mono_class_setup_basic_field_info (MonoClass *klass)
1414 {
1415         MonoGenericClass *gklass;
1416         MonoClassField *field;
1417         MonoClassField *fields;
1418         MonoClass *gtd;
1419         MonoImage *image;
1420         int i, top;
1421
1422         if (klass->fields)
1423                 return;
1424
1425         gklass = mono_class_try_get_generic_class (klass);
1426         gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1427         image = klass->image;
1428
1429
1430         if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1431                 /*
1432                  * This happens when a generic instance of an unfinished generic typebuilder
1433                  * is used as an element type for creating an array type. We can't initialize
1434                  * the fields of this class using the fields of gklass, since gklass is not
1435                  * finished yet, fields could be added to it later.
1436                  */
1437                 return;
1438         }
1439
1440         if (gtd) {
1441                 mono_class_setup_basic_field_info (gtd);
1442
1443                 mono_loader_lock ();
1444                 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1445                 mono_loader_unlock ();
1446         }
1447
1448         top = mono_class_get_field_count (klass);
1449
1450         fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1451
1452         /*
1453          * Fetch all the field information.
1454          */
1455         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1456         for (i = 0; i < top; i++) {
1457                 field = &fields [i];
1458                 field->parent = klass;
1459
1460                 if (gtd) {
1461                         field->name = mono_field_get_name (&gtd->fields [i]);
1462                 } else {
1463                         int idx = first_field_idx + i;
1464                         /* first_field_idx and idx points into the fieldptr table */
1465                         guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1466                         /* The name is needed for fieldrefs */
1467                         field->name = mono_metadata_string_heap (image, name_idx);
1468                 }
1469         }
1470
1471         mono_memory_barrier ();
1472
1473         mono_loader_lock ();
1474         if (!klass->fields)
1475                 klass->fields = fields;
1476         mono_loader_unlock ();
1477 }
1478
1479 /**
1480  * mono_class_set_failure_causedby_class:
1481  * \param klass the class that is failing
1482  * \param caused_by the class that caused the failure
1483  * \param msg Why \p klass is failing.
1484  * 
1485  * If \p caused_by has a failure, sets a TypeLoadException failure on
1486  * \p klass with message "\p msg, due to: {\p caused_by message}".
1487  *
1488  * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1489  */
1490 static gboolean
1491 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1492 {
1493         if (mono_class_has_failure (caused_by)) {
1494                 MonoError cause_error;
1495                 error_init (&cause_error);
1496                 mono_error_set_for_class_failure (&cause_error, caused_by);
1497                 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1498                 mono_error_cleanup (&cause_error);
1499                 return TRUE;
1500         } else {
1501                 return FALSE;
1502         }
1503 }
1504
1505
1506 /** 
1507  * mono_class_setup_fields:
1508  * \p klass The class to initialize
1509  *
1510  * Initializes klass->fields, computes class layout and sizes.
1511  * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1512  * Sets the following fields in \p klass:
1513  *  - all the fields initialized by mono_class_init_sizes ()
1514  *  - element_class/cast_class (for enums)
1515  *  - field->type/offset for all fields
1516  *  - fields_inited
1517  *
1518  * LOCKING: Acquires the loader lock.
1519  */
1520 void
1521 mono_class_setup_fields (MonoClass *klass)
1522 {
1523         MonoError error;
1524         MonoImage *m = klass->image;
1525         int top;
1526         guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1527         int i;
1528         guint32 real_size = 0;
1529         guint32 packing_size = 0;
1530         int instance_size;
1531         gboolean explicit_size;
1532         MonoClassField *field;
1533         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1534         MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1535
1536         if (klass->fields_inited)
1537                 return;
1538
1539         if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1540                 /*
1541                  * This happens when a generic instance of an unfinished generic typebuilder
1542                  * is used as an element type for creating an array type. We can't initialize
1543                  * the fields of this class using the fields of gklass, since gklass is not
1544                  * finished yet, fields could be added to it later.
1545                  */
1546                 return;
1547         }
1548
1549         mono_class_setup_basic_field_info (klass);
1550         top = mono_class_get_field_count (klass);
1551
1552         if (gtd) {
1553                 mono_class_setup_fields (gtd);
1554                 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1555                         return;
1556         }
1557
1558         instance_size = 0;
1559         if (klass->parent) {
1560                 /* For generic instances, klass->parent might not have been initialized */
1561                 mono_class_init (klass->parent);
1562                 mono_class_setup_fields (klass->parent);
1563                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1564                         return;
1565                 instance_size = klass->parent->instance_size;
1566         } else {
1567                 instance_size = sizeof (MonoObject);
1568         }
1569
1570         /* Get the real size */
1571         explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1572         if (explicit_size)
1573                 instance_size += real_size;
1574
1575         /*
1576          * This function can recursively call itself.
1577          * Prevent infinite recursion by using a list in TLS.
1578          */
1579         GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1580         if (g_slist_find (init_list, klass))
1581                 return;
1582         init_list = g_slist_prepend (init_list, klass);
1583         mono_native_tls_set_value (setup_fields_tls_id, init_list);
1584
1585         /*
1586          * Fetch all the field information.
1587          */
1588         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1589         for (i = 0; i < top; i++) {
1590                 int idx = first_field_idx + i;
1591                 field = &klass->fields [i];
1592
1593                 if (!field->type) {
1594                         mono_field_resolve_type (field, &error);
1595                         if (!mono_error_ok (&error)) {
1596                                 /*mono_field_resolve_type already failed class*/
1597                                 mono_error_cleanup (&error);
1598                                 break;
1599                         }
1600                         if (!field->type)
1601                                 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1602                         g_assert (field->type);
1603                 }
1604
1605                 if (mono_field_is_deleted (field))
1606                         continue;
1607                 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1608                         guint32 uoffset;
1609                         mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1610                         int offset = uoffset;
1611
1612                         if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1613                                 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1614                                 break;
1615                         }
1616                         if (offset < -1) { /*-1 is used to encode special static fields */
1617                                 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1618                                 break;
1619                         }
1620                         if (mono_class_is_gtd (klass)) {
1621                                 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1622                                 break;
1623                         }
1624                 }
1625                 if (mono_type_has_exceptions (field->type)) {
1626                         char *class_name = mono_type_get_full_name (klass);
1627                         char *type_name = mono_type_full_name (field->type);
1628
1629                         mono_class_set_type_load_failure (klass, "");
1630                         g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1631                         g_free (class_name);
1632                         g_free (type_name);
1633                         break;
1634                 }
1635                 /* The def_value of fields is compute lazily during vtable creation */
1636         }
1637
1638         if (!mono_class_has_failure (klass)) {
1639                 mono_loader_lock ();
1640                 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1641                 mono_loader_unlock ();
1642         }
1643
1644         init_list = g_slist_remove (init_list, klass);
1645         mono_native_tls_set_value (setup_fields_tls_id, init_list);
1646 }
1647
1648 static void
1649 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1650 {
1651         if (cached_info) {
1652                 mono_loader_lock ();
1653                 klass->instance_size = cached_info->instance_size;
1654                 klass->sizes.class_size = cached_info->class_size;
1655                 klass->packing_size = cached_info->packing_size;
1656                 klass->min_align = cached_info->min_align;
1657                 klass->blittable = cached_info->blittable;
1658                 klass->has_references = cached_info->has_references;
1659                 klass->has_static_refs = cached_info->has_static_refs;
1660                 klass->no_special_static_fields = cached_info->no_special_static_fields;
1661                 mono_loader_unlock ();
1662         }
1663         else {
1664                 if (!klass->size_inited)
1665                         mono_class_setup_fields (klass);
1666         }
1667 }
1668 /*
1669
1670  * mono_class_init_sizes:
1671  *
1672  *   Initializes the size related fields of @klass without loading all field data if possible.
1673  * Sets the following fields in @klass:
1674  * - instance_size
1675  * - sizes.class_size
1676  * - packing_size
1677  * - min_align
1678  * - blittable
1679  * - has_references
1680  * - has_static_refs
1681  * - size_inited
1682  * Can fail the class.
1683  *
1684  * LOCKING: Acquires the loader lock.
1685  */
1686 static void
1687 mono_class_init_sizes (MonoClass *klass)
1688 {
1689         MonoCachedClassInfo cached_info;
1690         gboolean has_cached_info;
1691
1692         if (klass->size_inited)
1693                 return;
1694
1695         has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1696
1697         init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1698 }
1699
1700 /*
1701  * mono_type_get_basic_type_from_generic:
1702  * @type: a type
1703  *
1704  * Returns a closed type corresponding to the possibly open type
1705  * passed to it.
1706  */
1707 MonoType*
1708 mono_type_get_basic_type_from_generic (MonoType *type)
1709 {
1710         /* When we do generic sharing we let type variables stand for reference/primitive types. */
1711         if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1712                 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1713                 return &mono_defaults.object_class->byval_arg;
1714         return type;
1715 }
1716
1717 static gboolean
1718 class_has_references (MonoClass *klass)
1719 {
1720         mono_class_init_sizes (klass);
1721
1722         /*
1723          * has_references is not set if this is called recursively, but this is not a problem since this is only used
1724          * during field layout, and instance fields are initialized before static fields, and instance fields can't
1725          * embed themselves.
1726          */
1727         return klass->has_references;
1728 }
1729
1730 static gboolean
1731 type_has_references (MonoClass *klass, MonoType *ftype)
1732 {
1733         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1734                 return TRUE;
1735         if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1736                 MonoGenericParam *gparam = ftype->data.generic_param;
1737
1738                 if (gparam->gshared_constraint)
1739                         return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1740         }
1741         return FALSE;
1742 }
1743
1744 /*
1745  * mono_class_layout_fields:
1746  * @class: a class
1747  * @base_instance_size: base instance size
1748  * @packing_size:
1749  *
1750  * This contains the common code for computing the layout of classes and sizes.
1751  * This should only be called from mono_class_setup_fields () and
1752  * typebuilder_setup_fields ().
1753  *
1754  * LOCKING: Acquires the loader lock
1755  */
1756 void
1757 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1758 {
1759         int i;
1760         const int top = mono_class_get_field_count (klass);
1761         guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1762         guint32 pass, passes, real_size;
1763         gboolean gc_aware_layout = FALSE;
1764         gboolean has_static_fields = FALSE;
1765         gboolean has_references = FALSE;
1766         gboolean has_static_refs = FALSE;
1767         MonoClassField *field;
1768         gboolean blittable;
1769         int instance_size = base_instance_size;
1770         int class_size, min_align;
1771         int *field_offsets;
1772         gboolean *fields_has_references;
1773
1774         /*
1775          * We want to avoid doing complicated work inside locks, so we compute all the required
1776          * information and write it to @klass inside a lock.
1777          */
1778         if (klass->fields_inited)
1779                 return;
1780
1781         if ((packing_size & 0xffffff00) != 0) {
1782                 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1783                 return;
1784         }
1785
1786         if (klass->parent) {
1787                 min_align = klass->parent->min_align;
1788                 /* we use | since it may have been set already */
1789                 has_references = klass->has_references | klass->parent->has_references;
1790         } else {
1791                 min_align = 1;
1792         }
1793         /* We can't really enable 16 bytes alignment until the GC supports it.
1794         The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1795         boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1796         Bug #506144 is an example of this issue.
1797
1798          if (klass->simd_type)
1799                 min_align = 16;
1800          */
1801
1802         /*
1803          * When we do generic sharing we need to have layout
1804          * information for open generic classes (either with a generic
1805          * context containing type variables or with a generic
1806          * container), so we don't return in that case anymore.
1807          */
1808
1809         if (klass->enumtype) {
1810                 for (i = 0; i < top; i++) {
1811                         field = &klass->fields [i];
1812                         if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1813                                 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1814                                 break;
1815                         }
1816                 }
1817
1818                 if (!mono_class_enum_basetype (klass)) {
1819                         mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1820                         return;
1821                 }
1822         }
1823
1824         /*
1825          * Enable GC aware auto layout: in this mode, reference
1826          * fields are grouped together inside objects, increasing collector 
1827          * performance.
1828          * Requires that all classes whose layout is known to native code be annotated
1829          * with [StructLayout (LayoutKind.Sequential)]
1830          * Value types have gc_aware_layout disabled by default, as per
1831          * what the default is for other runtimes.
1832          */
1833          /* corlib is missing [StructLayout] directives in many places */
1834         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1835                 if (!klass->valuetype)
1836                         gc_aware_layout = TRUE;
1837         }
1838
1839         /* Compute klass->blittable */
1840         blittable = TRUE;
1841         if (klass->parent)
1842                 blittable = klass->parent->blittable;
1843         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1844                 blittable = FALSE;
1845         for (i = 0; i < top; i++) {
1846                 field = &klass->fields [i];
1847
1848                 if (mono_field_is_deleted (field))
1849                         continue;
1850                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1851                         continue;
1852                 if (blittable) {
1853                         if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1854                                 blittable = FALSE;
1855                         } else {
1856                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
1857                                 if (field_class) {
1858                                         mono_class_setup_fields (field_class);
1859                                         if (mono_class_has_failure (field_class)) {
1860                                                 MonoError field_error;
1861                                                 error_init (&field_error);
1862                                                 mono_error_set_for_class_failure (&field_error, field_class);
1863                                                 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1864                                                 mono_error_cleanup (&field_error);
1865                                                 break;
1866                                         }
1867                                 }
1868                                 if (!field_class || !field_class->blittable)
1869                                         blittable = FALSE;
1870                         }
1871                 }
1872                 if (klass->enumtype)
1873                         blittable = klass->element_class->blittable;
1874         }
1875         if (mono_class_has_failure (klass))
1876                 return;
1877         if (klass == mono_defaults.string_class)
1878                 blittable = FALSE;
1879
1880         /* Compute klass->has_references */
1881         /* 
1882          * Process non-static fields first, since static fields might recursively
1883          * refer to the class itself.
1884          */
1885         for (i = 0; i < top; i++) {
1886                 MonoType *ftype;
1887
1888                 field = &klass->fields [i];
1889
1890                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1891                         ftype = mono_type_get_underlying_type (field->type);
1892                         ftype = mono_type_get_basic_type_from_generic (ftype);
1893                         if (type_has_references (klass, ftype))
1894                                 has_references = TRUE;
1895                 }
1896         }
1897
1898         /*
1899          * Compute field layout and total size (not considering static fields)
1900          */
1901         field_offsets = g_new0 (int, top);
1902         fields_has_references = g_new0 (gboolean, top);
1903         int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1904         switch (layout) {
1905         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1906         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1907                 if (gc_aware_layout)
1908                         passes = 2;
1909                 else
1910                         passes = 1;
1911
1912                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1913                         passes = 1;
1914
1915                 if (klass->parent) {
1916                         mono_class_setup_fields (klass->parent);
1917                         if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1918                                 return;
1919                         real_size = klass->parent->instance_size;
1920                 } else {
1921                         real_size = sizeof (MonoObject);
1922                 }
1923
1924                 for (pass = 0; pass < passes; ++pass) {
1925                         for (i = 0; i < top; i++){
1926                                 gint32 align;
1927                                 guint32 size;
1928                                 MonoType *ftype;
1929
1930                                 field = &klass->fields [i];
1931
1932                                 if (mono_field_is_deleted (field))
1933                                         continue;
1934                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1935                                         continue;
1936
1937                                 ftype = mono_type_get_underlying_type (field->type);
1938                                 ftype = mono_type_get_basic_type_from_generic (ftype);
1939                                 if (gc_aware_layout) {
1940                                         fields_has_references [i] = type_has_references (klass, ftype);
1941                                         if (fields_has_references [i]) {
1942                                                 if (pass == 1)
1943                                                         continue;
1944                                         } else {
1945                                                 if (pass == 0)
1946                                                         continue;
1947                                         }
1948                                 }
1949
1950                                 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1951                                         (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1952                                         /* This field is a hack inserted by MCS to empty structures */
1953                                         continue;
1954                                 }
1955
1956                                 size = mono_type_size (field->type, &align);
1957                         
1958                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1959                                 align = packing_size ? MIN (packing_size, align): align;
1960                                 /* if the field has managed references, we need to force-align it
1961                                  * see bug #77788
1962                                  */
1963                                 if (type_has_references (klass, ftype))
1964                                         align = MAX (align, sizeof (gpointer));
1965
1966                                 min_align = MAX (align, min_align);
1967                                 field_offsets [i] = real_size;
1968                                 if (align) {
1969                                         field_offsets [i] += align - 1;
1970                                         field_offsets [i] &= ~(align - 1);
1971                                 }
1972                                 /*TypeBuilders produce all sort of weird things*/
1973                                 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1974                                 real_size = field_offsets [i] + size;
1975                         }
1976
1977                         /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1978                         if (klass->simd_type)
1979                                 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1980                         instance_size = MAX (real_size, instance_size);
1981        
1982                         if (instance_size & (min_align - 1)) {
1983                                 instance_size += min_align - 1;
1984                                 instance_size &= ~(min_align - 1);
1985                         }
1986                 }
1987                 break;
1988         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1989                 guint8 *ref_bitmap;
1990
1991                 real_size = 0;
1992                 for (i = 0; i < top; i++) {
1993                         gint32 align;
1994                         guint32 size;
1995                         MonoType *ftype;
1996
1997                         field = &klass->fields [i];
1998
1999                         /*
2000                          * There must be info about all the fields in a type if it
2001                          * uses explicit layout.
2002                          */
2003                         if (mono_field_is_deleted (field))
2004                                 continue;
2005                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2006                                 continue;
2007
2008                         size = mono_type_size (field->type, &align);
2009                         align = packing_size ? MIN (packing_size, align): align;
2010                         min_align = MAX (align, min_align);
2011
2012                         if (sre) {
2013                                 /* Already set by typebuilder_setup_fields () */
2014                                 field_offsets [i] = field->offset + sizeof (MonoObject);
2015                         } else {
2016                                 int idx = first_field_idx + i;
2017                                 guint32 offset;
2018                                 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2019                                 field_offsets [i] = offset + sizeof (MonoObject);
2020                         }
2021                         ftype = mono_type_get_underlying_type (field->type);
2022                         ftype = mono_type_get_basic_type_from_generic (ftype);
2023                         if (type_has_references (klass, ftype)) {
2024                                 if (field_offsets [i] % sizeof (gpointer)) {
2025                                         mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2026                                 }
2027                         }
2028
2029                         /*
2030                          * Calc max size.
2031                          */
2032                         real_size = MAX (real_size, size + field_offsets [i]);
2033                 }
2034
2035                 if (klass->has_references) {
2036                         ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2037
2038                         /* Check for overlapping reference and non-reference fields */
2039                         for (i = 0; i < top; i++) {
2040                                 MonoType *ftype;
2041
2042                                 field = &klass->fields [i];
2043
2044                                 if (mono_field_is_deleted (field))
2045                                         continue;
2046                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2047                                         continue;
2048                                 ftype = mono_type_get_underlying_type (field->type);
2049                                 if (MONO_TYPE_IS_REFERENCE (ftype))
2050                                         ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2051                         }
2052                         for (i = 0; i < top; i++) {
2053                                 field = &klass->fields [i];
2054
2055                                 if (mono_field_is_deleted (field))
2056                                         continue;
2057                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2058                                         continue;
2059
2060                                 // FIXME: Too much code does this
2061 #if 0
2062                                 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2063                                         mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2064                                 }
2065 #endif
2066                         }
2067                         g_free (ref_bitmap);
2068                 }
2069
2070                 instance_size = MAX (real_size, instance_size);
2071                 if (instance_size & (min_align - 1)) {
2072                         instance_size += min_align - 1;
2073                         instance_size &= ~(min_align - 1);
2074                 }
2075                 break;
2076         }
2077         }
2078
2079         if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2080                 /*
2081                  * This leads to all kinds of problems with nested structs, so only
2082                  * enable it when a MONO_DEBUG property is set.
2083                  *
2084                  * For small structs, set min_align to at least the struct size to improve
2085                  * performance, and since the JIT memset/memcpy code assumes this and generates 
2086                  * unaligned accesses otherwise. See #78990 for a testcase.
2087                  */
2088                 if (mono_align_small_structs && top) {
2089                         if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2090                                 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2091                 }
2092         }
2093
2094         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2095                 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2096         else if (klass->byval_arg.type == MONO_TYPE_PTR)
2097                 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2098
2099         /* Publish the data */
2100         mono_loader_lock ();
2101         if (klass->instance_size && !klass->image->dynamic) {
2102                 /* Might be already set using cached info */
2103                 if (klass->instance_size != instance_size) {
2104                         /* Emit info to help debugging */
2105                         g_print ("%s\n", mono_class_full_name (klass));
2106                         g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2107                         g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2108                         g_print ("%d %d\n", klass->min_align, min_align);
2109                         for (i = 0; i < top; ++i) {
2110                                 field = &klass->fields [i];
2111                                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2112                                         printf ("  %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2113                         }
2114                 }
2115                 g_assert (klass->instance_size == instance_size);
2116         } else {
2117                 klass->instance_size = instance_size;
2118         }
2119         klass->blittable = blittable;
2120         klass->has_references = has_references;
2121         klass->packing_size = packing_size;
2122         klass->min_align = min_align;
2123         for (i = 0; i < top; ++i) {
2124                 field = &klass->fields [i];
2125                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2126                         klass->fields [i].offset = field_offsets [i];
2127         }
2128
2129         mono_memory_barrier ();
2130         klass->size_inited = 1;
2131         mono_loader_unlock ();
2132
2133         /*
2134          * Compute static field layout and size
2135          * Static fields can reference the class itself, so this has to be
2136          * done after instance_size etc. are initialized.
2137          */
2138         class_size = 0;
2139         for (i = 0; i < top; i++) {
2140                 gint32 align;
2141                 guint32 size;
2142
2143                 field = &klass->fields [i];
2144                         
2145                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2146                         continue;
2147                 if (mono_field_is_deleted (field))
2148                         continue;
2149
2150                 if (mono_type_has_exceptions (field->type)) {
2151                         mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2152                         break;
2153                 }
2154
2155                 has_static_fields = TRUE;
2156
2157                 size = mono_type_size (field->type, &align);
2158                 field_offsets [i] = class_size;
2159                 /*align is always non-zero here*/
2160                 field_offsets [i] += align - 1;
2161                 field_offsets [i] &= ~(align - 1);
2162                 class_size = field_offsets [i] + size;
2163         }
2164
2165         if (has_static_fields && class_size == 0)
2166                 /* Simplify code which depends on class_size != 0 if the class has static fields */
2167                 class_size = 8;
2168
2169         /* Compute klass->has_static_refs */
2170         has_static_refs = FALSE;
2171         for (i = 0; i < top; i++) {
2172                 MonoType *ftype;
2173
2174                 field = &klass->fields [i];
2175
2176                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2177                         ftype = mono_type_get_underlying_type (field->type);
2178                         ftype = mono_type_get_basic_type_from_generic (ftype);
2179                         if (type_has_references (klass, ftype))
2180                                 has_static_refs = TRUE;
2181                 }
2182         }
2183
2184         /*valuetypes can't be neither bigger than 1Mb or empty. */
2185         if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2186                 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2187
2188         /* Publish the data */
2189         mono_loader_lock ();
2190         if (!klass->rank)
2191                 klass->sizes.class_size = class_size;
2192         klass->has_static_refs = has_static_refs;
2193         for (i = 0; i < top; ++i) {
2194                 field = &klass->fields [i];
2195
2196                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2197                         field->offset = field_offsets [i];
2198         }
2199
2200         mono_memory_barrier ();
2201         klass->fields_inited = 1;
2202         mono_loader_unlock ();
2203
2204         g_free (field_offsets);
2205         g_free (fields_has_references);
2206 }
2207
2208 static MonoMethod*
2209 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2210 {
2211         MonoMethod *method;
2212
2213         method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2214         method->klass = klass;
2215         method->flags = METHOD_ATTRIBUTE_PUBLIC;
2216         method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2217         method->signature = sig;
2218         method->name = name;
2219         method->slot = -1;
2220         /* .ctor */
2221         if (name [0] == '.') {
2222                 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2223         } else {
2224                 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2225         }
2226         return method;
2227 }
2228
2229 /*
2230  * mono_class_setup_methods:
2231  * @class: a class
2232  *
2233  *   Initializes the 'methods' array in CLASS.
2234  * Calling this method should be avoided if possible since it allocates a lot 
2235  * of long-living MonoMethod structures.
2236  * Methods belonging to an interface are assigned a sequential slot starting
2237  * from 0.
2238  *
2239  * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2240  */
2241 void
2242 mono_class_setup_methods (MonoClass *klass)
2243 {
2244         int i, count;
2245         MonoMethod **methods;
2246
2247         if (klass->methods)
2248                 return;
2249
2250         if (mono_class_is_ginst (klass)) {
2251                 MonoError error;
2252                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2253
2254                 mono_class_init (gklass);
2255                 if (!mono_class_has_failure (gklass))
2256                         mono_class_setup_methods (gklass);
2257                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2258                         return;
2259
2260                 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2261                 count = mono_class_get_method_count (gklass);
2262                 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2263
2264                 for (i = 0; i < count; i++) {
2265                         methods [i] = mono_class_inflate_generic_method_full_checked (
2266                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2267                         if (!mono_error_ok (&error)) {
2268                                 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2269                                 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2270
2271                                 g_free (method);
2272                                 mono_error_cleanup (&error);
2273                                 return;                         
2274                         }
2275                 }
2276         } else if (klass->rank) {
2277                 MonoError error;
2278                 MonoMethod *amethod;
2279                 MonoMethodSignature *sig;
2280                 int count_generic = 0, first_generic = 0;
2281                 int method_num = 0;
2282                 gboolean jagged_ctor = FALSE;
2283
2284                 count = 3 + (klass->rank > 1? 2: 1);
2285
2286                 mono_class_setup_interfaces (klass, &error);
2287                 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2288
2289                 if (klass->rank == 1 && klass->element_class->rank) {
2290                         jagged_ctor = TRUE;
2291                         count ++;
2292                 }
2293
2294                 if (klass->interface_count) {
2295                         count_generic = generic_array_methods (klass);
2296                         first_generic = count;
2297                         count += klass->interface_count * count_generic;
2298                 }
2299
2300                 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2301
2302                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2303                 sig->ret = &mono_defaults.void_class->byval_arg;
2304                 sig->pinvoke = TRUE;
2305                 sig->hasthis = TRUE;
2306                 for (i = 0; i < klass->rank; ++i)
2307                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2308
2309                 amethod = create_array_method (klass, ".ctor", sig);
2310                 methods [method_num++] = amethod;
2311                 if (klass->rank > 1) {
2312                         sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2313                         sig->ret = &mono_defaults.void_class->byval_arg;
2314                         sig->pinvoke = TRUE;
2315                         sig->hasthis = TRUE;
2316                         for (i = 0; i < klass->rank * 2; ++i)
2317                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2318
2319                         amethod = create_array_method (klass, ".ctor", sig);
2320                         methods [method_num++] = amethod;
2321                 }
2322
2323                 if (jagged_ctor) {
2324                         /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2325                         sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2326                         sig->ret = &mono_defaults.void_class->byval_arg;
2327                         sig->pinvoke = TRUE;
2328                         sig->hasthis = TRUE;
2329                         for (i = 0; i < klass->rank + 1; ++i)
2330                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2331                         amethod = create_array_method (klass, ".ctor", sig);
2332                         methods [method_num++] = amethod;
2333                 }
2334
2335                 /* element Get (idx11, [idx2, ...]) */
2336                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2337                 sig->ret = &klass->element_class->byval_arg;
2338                 sig->pinvoke = TRUE;
2339                 sig->hasthis = TRUE;
2340                 for (i = 0; i < klass->rank; ++i)
2341                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2342                 amethod = create_array_method (klass, "Get", sig);
2343                 methods [method_num++] = amethod;
2344                 /* element& Address (idx11, [idx2, ...]) */
2345                 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2346                 sig->ret = &klass->element_class->this_arg;
2347                 sig->pinvoke = TRUE;
2348                 sig->hasthis = TRUE;
2349                 for (i = 0; i < klass->rank; ++i)
2350                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2351                 amethod = create_array_method (klass, "Address", sig);
2352                 methods [method_num++] = amethod;
2353                 /* void Set (idx11, [idx2, ...], element) */
2354                 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2355                 sig->ret = &mono_defaults.void_class->byval_arg;
2356                 sig->pinvoke = TRUE;
2357                 sig->hasthis = TRUE;
2358                 for (i = 0; i < klass->rank; ++i)
2359                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2360                 sig->params [i] = &klass->element_class->byval_arg;
2361                 amethod = create_array_method (klass, "Set", sig);
2362                 methods [method_num++] = amethod;
2363
2364                 GHashTable *cache = g_hash_table_new (NULL, NULL);
2365                 for (i = 0; i < klass->interface_count; i++)
2366                         setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2367                 g_hash_table_destroy (cache);
2368         } else if (mono_class_has_static_metadata (klass)) {
2369                 MonoError error;
2370                 int first_idx = mono_class_get_first_method_idx (klass);
2371
2372                 count = mono_class_get_method_count (klass);
2373                 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2374                 for (i = 0; i < count; ++i) {
2375                         int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2376                         methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2377                         if (!methods [i]) {
2378                                 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2379                                 mono_error_cleanup (&error);
2380                         }
2381                 }
2382         } else {
2383                 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2384                 count = 0;
2385         }
2386
2387         if (MONO_CLASS_IS_INTERFACE (klass)) {
2388                 int slot = 0;
2389                 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2390                 for (i = 0; i < count; ++i) {
2391                         if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2392                                 methods [i]->slot = slot++;
2393                 }
2394         }
2395
2396         mono_image_lock (klass->image);
2397
2398         if (!klass->methods) {
2399                 mono_class_set_method_count (klass, count);
2400
2401                 /* Needed because of the double-checking locking pattern */
2402                 mono_memory_barrier ();
2403
2404                 klass->methods = methods;
2405         }
2406
2407         mono_image_unlock (klass->image);
2408 }
2409
2410 /*
2411  * mono_class_get_method_by_index:
2412  *
2413  *   Returns klass->methods [index], initializing klass->methods if neccesary.
2414  *
2415  * LOCKING: Acquires the loader lock.
2416  */
2417 MonoMethod*
2418 mono_class_get_method_by_index (MonoClass *klass, int index)
2419 {
2420         MonoError error;
2421
2422         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2423         /* Avoid calling setup_methods () if possible */
2424         if (gklass && !klass->methods) {
2425                 MonoMethod *m;
2426
2427                 m = mono_class_inflate_generic_method_full_checked (
2428                                 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2429                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2430                 /*
2431                  * If setup_methods () is called later for this class, no duplicates are created,
2432                  * since inflate_generic_method guarantees that only one instance of a method
2433                  * is created for each context.
2434                  */
2435                 /*
2436                 mono_class_setup_methods (klass);
2437                 g_assert (m == klass->methods [index]);
2438                 */
2439                 return m;
2440         } else {
2441                 mono_class_setup_methods (klass);
2442                 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2443                         return NULL;
2444                 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2445                 return klass->methods [index];
2446         }
2447 }       
2448
2449 /*
2450  * mono_class_get_inflated_method:
2451  *
2452  *   Given an inflated class CLASS and a method METHOD which should be a method of
2453  * CLASS's generic definition, return the inflated method corresponding to METHOD.
2454  */
2455 MonoMethod*
2456 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2457 {
2458         MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2459         int i, mcount;
2460
2461         g_assert (method->klass == gklass);
2462
2463         mono_class_setup_methods (gklass);
2464         g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2465
2466         mcount = mono_class_get_method_count (gklass);
2467         for (i = 0; i < mcount; ++i) {
2468                 if (gklass->methods [i] == method) {
2469                         if (klass->methods) {
2470                                 return klass->methods [i];
2471                         } else {
2472                                 MonoError error;
2473                                 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2474                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2475                                 return result;
2476                         }
2477                 }
2478         }
2479
2480         return NULL;
2481 }       
2482
2483 /*
2484  * mono_class_get_vtable_entry:
2485  *
2486  *   Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2487  * LOCKING: Acquires the loader lock.
2488  */
2489 MonoMethod*
2490 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2491 {
2492         MonoMethod *m;
2493
2494         if (klass->rank == 1) {
2495                 /* 
2496                  * szarrays do not overwrite any methods of Array, so we can avoid
2497                  * initializing their vtables in some cases.
2498                  */
2499                 mono_class_setup_vtable (klass->parent);
2500                 if (offset < klass->parent->vtable_size)
2501                         return klass->parent->vtable [offset];
2502         }
2503
2504         if (mono_class_is_ginst (klass)) {
2505                 MonoError error;
2506                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2507                 mono_class_setup_vtable (gklass);
2508                 m = gklass->vtable [offset];
2509
2510                 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2511                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2512         } else {
2513                 mono_class_setup_vtable (klass);
2514                 if (mono_class_has_failure (klass))
2515                         return NULL;
2516                 m = klass->vtable [offset];
2517         }
2518
2519         return m;
2520 }
2521
2522 /*
2523  * mono_class_get_vtable_size:
2524  *
2525  *   Return the vtable size for KLASS.
2526  */
2527 int
2528 mono_class_get_vtable_size (MonoClass *klass)
2529 {
2530         mono_class_setup_vtable (klass);
2531
2532         return klass->vtable_size;
2533 }
2534
2535 /*
2536  * mono_class_setup_properties:
2537  *
2538  *   Initialize klass->ext.property and klass->ext.properties.
2539  *
2540  * This method can fail the class.
2541  */
2542 static void
2543 mono_class_setup_properties (MonoClass *klass)
2544 {
2545         guint startm, endm, i, j;
2546         guint32 cols [MONO_PROPERTY_SIZE];
2547         MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2548         MonoProperty *properties;
2549         guint32 last;
2550         int first, count;
2551         MonoClassPropertyInfo *info;
2552
2553         info = mono_class_get_property_info (klass);
2554         if (info)
2555                 return;
2556
2557         if (mono_class_is_ginst (klass)) {
2558                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2559
2560                 mono_class_init (gklass);
2561                 mono_class_setup_properties (gklass);
2562                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2563                         return;
2564
2565                 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2566                 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2567
2568                 for (i = 0; i < ginfo->count; i++) {
2569                         MonoError error;
2570                         MonoProperty *prop = &properties [i];
2571
2572                         *prop = ginfo->properties [i];
2573
2574                         if (prop->get)
2575                                 prop->get = mono_class_inflate_generic_method_full_checked (
2576                                         prop->get, klass, mono_class_get_context (klass), &error);
2577                         if (prop->set)
2578                                 prop->set = mono_class_inflate_generic_method_full_checked (
2579                                         prop->set, klass, mono_class_get_context (klass), &error);
2580
2581                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2582                         prop->parent = klass;
2583                 }
2584
2585                 first = ginfo->first;
2586                 count = ginfo->count;
2587         } else {
2588                 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2589                 count = last - first;
2590
2591                 if (count) {
2592                         mono_class_setup_methods (klass);
2593                         if (mono_class_has_failure (klass))
2594                                 return;
2595                 }
2596
2597                 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2598                 for (i = first; i < last; ++i) {
2599                         mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2600                         properties [i - first].parent = klass;
2601                         properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2602                         properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2603
2604                         startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2605                         int first_idx = mono_class_get_first_method_idx (klass);
2606                         for (j = startm; j < endm; ++j) {
2607                                 MonoMethod *method;
2608
2609                                 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2610
2611                                 if (klass->image->uncompressed_metadata) {
2612                                         MonoError error;
2613                                         /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2614                                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2615                                         mono_error_cleanup (&error); /* FIXME don't swallow this error */
2616                                 } else {
2617                                         method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2618                                 }
2619
2620                                 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2621                                 case METHOD_SEMANTIC_SETTER:
2622                                         properties [i - first].set = method;
2623                                         break;
2624                                 case METHOD_SEMANTIC_GETTER:
2625                                         properties [i - first].get = method;
2626                                         break;
2627                                 default:
2628                                         break;
2629                                 }
2630                         }
2631                 }
2632         }
2633
2634         info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2635         info->first = first;
2636         info->count = count;
2637         info->properties = properties;
2638         mono_memory_barrier ();
2639
2640         /* This might leak 'info' which was allocated from the image mempool */
2641         mono_class_set_property_info (klass, info);
2642 }
2643
2644 static MonoMethod**
2645 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2646 {
2647         MonoMethod **om, **retval;
2648         int count;
2649
2650         for (om = methods, count = 0; *om; ++om, ++count)
2651                 ;
2652
2653         retval = g_new0 (MonoMethod*, count + 1);
2654         count = 0;
2655         for (om = methods, count = 0; *om; ++om, ++count) {
2656                 MonoError error;
2657                 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2658                 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2659         }
2660
2661         return retval;
2662 }
2663
2664 /*This method can fail the class.*/
2665 static void
2666 mono_class_setup_events (MonoClass *klass)
2667 {
2668         int first, count;
2669         guint startm, endm, i, j;
2670         guint32 cols [MONO_EVENT_SIZE];
2671         MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2672         guint32 last;
2673         MonoEvent *events;
2674
2675         MonoClassEventInfo *info = mono_class_get_event_info (klass);
2676         if (info)
2677                 return;
2678
2679         if (mono_class_is_ginst (klass)) {
2680                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2681                 MonoGenericContext *context = NULL;
2682
2683                 mono_class_setup_events (gklass);
2684                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2685                         return;
2686
2687                 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2688                 first = ginfo->first;
2689                 count = ginfo->count;
2690
2691                 events = mono_class_new0 (klass, MonoEvent, count);
2692
2693                 if (count)
2694                         context = mono_class_get_context (klass);
2695
2696                 for (i = 0; i < count; i++) {
2697                         MonoError error;
2698                         MonoEvent *event = &events [i];
2699                         MonoEvent *gevent = &ginfo->events [i];
2700
2701                         error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2702
2703                         event->parent = klass;
2704                         event->name = gevent->name;
2705                         event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2706                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2707                         event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2708                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2709                         event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2710                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2711
2712 #ifndef MONO_SMALL_CONFIG
2713                         event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2714 #endif
2715                         event->attrs = gevent->attrs;
2716                 }
2717         } else {
2718                 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2719                 count = last - first;
2720
2721                 if (count) {
2722                         mono_class_setup_methods (klass);
2723                         if (mono_class_has_failure (klass)) {
2724                                 return;
2725                         }
2726                 }
2727
2728                 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2729                 for (i = first; i < last; ++i) {
2730                         MonoEvent *event = &events [i - first];
2731
2732                         mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2733                         event->parent = klass;
2734                         event->attrs = cols [MONO_EVENT_FLAGS];
2735                         event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2736
2737                         startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2738                         int first_idx = mono_class_get_first_method_idx (klass);
2739                         for (j = startm; j < endm; ++j) {
2740                                 MonoMethod *method;
2741
2742                                 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2743
2744                                 if (klass->image->uncompressed_metadata) {
2745                                         MonoError error;
2746                                         /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2747                                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2748                                         mono_error_cleanup (&error); /* FIXME don't swallow this error */
2749                                 } else {
2750                                         method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2751                                 }
2752
2753                                 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2754                                 case METHOD_SEMANTIC_ADD_ON:
2755                                         event->add = method;
2756                                         break;
2757                                 case METHOD_SEMANTIC_REMOVE_ON:
2758                                         event->remove = method;
2759                                         break;
2760                                 case METHOD_SEMANTIC_FIRE:
2761                                         event->raise = method;
2762                                         break;
2763                                 case METHOD_SEMANTIC_OTHER: {
2764 #ifndef MONO_SMALL_CONFIG
2765                                         int n = 0;
2766
2767                                         if (event->other == NULL) {
2768                                                 event->other = g_new0 (MonoMethod*, 2);
2769                                         } else {
2770                                                 while (event->other [n])
2771                                                         n++;
2772                                                 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2773                                         }
2774                                         event->other [n] = method;
2775                                         /* NULL terminated */
2776                                         event->other [n + 1] = NULL;
2777 #endif
2778                                         break;
2779                                 }
2780                                 default:
2781                                         break;
2782                                 }
2783                         }
2784                 }
2785         }
2786
2787         info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2788         info->events = events;
2789         info->first = first;
2790         info->count = count;
2791
2792         mono_memory_barrier ();
2793
2794         mono_class_set_event_info (klass, info);
2795 }
2796
2797 /*
2798  * Global pool of interface IDs, represented as a bitset.
2799  * LOCKING: Protected by the classes lock.
2800  */
2801 static MonoBitSet *global_interface_bitset = NULL;
2802
2803 /*
2804  * mono_unload_interface_ids:
2805  * @bitset: bit set of interface IDs
2806  *
2807  * When an image is unloaded, the interface IDs associated with
2808  * the image are put back in the global pool of IDs so the numbers
2809  * can be reused.
2810  */
2811 void
2812 mono_unload_interface_ids (MonoBitSet *bitset)
2813 {
2814         classes_lock ();
2815         mono_bitset_sub (global_interface_bitset, bitset);
2816         classes_unlock ();
2817 }
2818
2819 void
2820 mono_unload_interface_id (MonoClass *klass)
2821 {
2822         if (global_interface_bitset && klass->interface_id) {
2823                 classes_lock ();
2824                 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2825                 classes_unlock ();
2826         }
2827 }
2828
2829 /**
2830  * mono_get_unique_iid:
2831  * \param klass interface
2832  *
2833  * Assign a unique integer ID to the interface represented by \p klass.
2834  * The ID will positive and as small as possible.
2835  * LOCKING: Acquires the classes lock.
2836  * \returns The new ID.
2837  */
2838 static guint32
2839 mono_get_unique_iid (MonoClass *klass)
2840 {
2841         int iid;
2842         
2843         g_assert (MONO_CLASS_IS_INTERFACE (klass));
2844
2845         classes_lock ();
2846
2847         if (!global_interface_bitset) {
2848                 global_interface_bitset = mono_bitset_new (128, 0);
2849         }
2850
2851         iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2852         if (iid < 0) {
2853                 int old_size = mono_bitset_size (global_interface_bitset);
2854                 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2855                 mono_bitset_free (global_interface_bitset);
2856                 global_interface_bitset = new_set;
2857                 iid = old_size;
2858         }
2859         mono_bitset_set (global_interface_bitset, iid);
2860         /* set the bit also in the per-image set */
2861         if (!mono_class_is_ginst (klass)) {
2862                 if (klass->image->interface_bitset) {
2863                         if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2864                                 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2865                                 mono_bitset_free (klass->image->interface_bitset);
2866                                 klass->image->interface_bitset = new_set;
2867                         }
2868                 } else {
2869                         klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2870                 }
2871                 mono_bitset_set (klass->image->interface_bitset, iid);
2872         }
2873
2874         classes_unlock ();
2875
2876 #ifndef MONO_SMALL_CONFIG
2877         if (mono_print_vtable) {
2878                 int generic_id;
2879                 char *type_name = mono_type_full_name (&klass->byval_arg);
2880                 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2881                 if (gklass && !gklass->context.class_inst->is_open) {
2882                         generic_id = gklass->context.class_inst->id;
2883                         g_assert (generic_id != 0);
2884                 } else {
2885                         generic_id = 0;
2886                 }
2887                 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2888                 g_free (type_name);
2889         }
2890 #endif
2891
2892         /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2893          * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2894         g_assert (iid < INT_MAX);
2895         return iid;
2896 }
2897
2898 static void
2899 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2900 {
2901         int i;
2902         MonoClass *ic;
2903
2904         mono_class_setup_interfaces (klass, error);
2905         return_if_nok (error);
2906
2907         for (i = 0; i < klass->interface_count; i++) {
2908                 ic = klass->interfaces [i];
2909
2910                 if (*res == NULL)
2911                         *res = g_ptr_array_new ();
2912                 if (*ifaces == NULL)
2913                         *ifaces = g_hash_table_new (NULL, NULL);
2914                 if (g_hash_table_lookup (*ifaces, ic))
2915                         continue;
2916                 g_ptr_array_add (*res, ic);
2917                 g_hash_table_insert (*ifaces, ic, ic);
2918                 mono_class_init (ic);
2919                 if (mono_class_has_failure (ic)) {
2920                         mono_error_set_type_load_class (error, ic, "Error Loading class");
2921                         return;
2922                 }
2923
2924                 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2925                 return_if_nok (error);
2926         }
2927 }
2928
2929 GPtrArray*
2930 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2931 {
2932         GPtrArray *res = NULL;
2933         GHashTable *ifaces = NULL;
2934
2935         collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2936         if (ifaces)
2937                 g_hash_table_destroy (ifaces);
2938         if (!mono_error_ok (error)) {
2939                 if (res)
2940                         g_ptr_array_free (res, TRUE);
2941                 return NULL;
2942         }
2943         return res;
2944 }
2945
2946 static int
2947 compare_interface_ids (const void *p_key, const void *p_element)
2948 {
2949         const MonoClass *key = (const MonoClass *)p_key;
2950         const MonoClass *element = *(const MonoClass **)p_element;
2951         
2952         return (key->interface_id - element->interface_id);
2953 }
2954
2955 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2956 int
2957 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2958 {
2959         MonoClass **result = (MonoClass **)mono_binary_search (
2960                         itf,
2961                         klass->interfaces_packed,
2962                         klass->interface_offsets_count,
2963                         sizeof (MonoClass *),
2964                         compare_interface_ids);
2965         if (result) {
2966                 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2967         } else {
2968                 return -1;
2969         }
2970 }
2971
2972 /**
2973  * mono_class_interface_offset_with_variance:
2974  * 
2975  * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2976  * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2977  *
2978  * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2979  *
2980  * FIXME figure out MS disambiguation rules and fix this function.
2981  */
2982 int
2983 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2984 {
2985         int i = mono_class_interface_offset (klass, itf);
2986         *non_exact_match = FALSE;
2987         if (i >= 0)
2988                 return i;
2989         
2990         if (itf->is_array_special_interface && klass->rank < 2) {
2991                 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2992
2993                 for (i = 0; i < klass->interface_offsets_count; i++) {
2994                         // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2995                         if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2996                                 *non_exact_match = TRUE;
2997                                 return klass->interface_offsets_packed [i];
2998                         }
2999                 }
3000         }
3001
3002         if (!mono_class_has_variant_generic_params (itf))
3003                 return -1;
3004
3005         for (i = 0; i < klass->interface_offsets_count; i++) {
3006                 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3007                         *non_exact_match = TRUE;
3008                         return klass->interface_offsets_packed [i];
3009                 }
3010         }
3011
3012         return -1;
3013 }
3014
3015 static void
3016 print_implemented_interfaces (MonoClass *klass)
3017 {
3018         char *name;
3019         MonoError error;
3020         GPtrArray *ifaces = NULL;
3021         int i;
3022         int ancestor_level = 0;
3023
3024         name = mono_type_get_full_name (klass);
3025         printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3026         g_free (name);
3027
3028         for (i = 0; i < klass->interface_offsets_count; i++)
3029                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3030                                 klass->interfaces_packed [i]->interface_id,
3031                                 klass->interface_offsets_packed [i],
3032                                 mono_class_get_method_count (klass->interfaces_packed [i]),
3033                                 klass->interfaces_packed [i]->name_space,
3034                                 klass->interfaces_packed [i]->name );
3035         printf ("Interface flags: ");
3036         for (i = 0; i <= klass->max_interface_id; i++)
3037                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3038                         printf ("(%d,T)", i);
3039                 else
3040                         printf ("(%d,F)", i);
3041         printf ("\n");
3042         printf ("Dump interface flags:");
3043 #ifdef COMPRESSED_INTERFACE_BITMAP
3044         {
3045                 const uint8_t* p = klass->interface_bitmap;
3046                 i = klass->max_interface_id;
3047                 while (i > 0) {
3048                         printf (" %d x 00 %02X", p [0], p [1]);
3049                         i -= p [0] * 8;
3050                         i -= 8;
3051                 }
3052         }
3053 #else
3054         for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3055                 printf (" %02X", klass->interface_bitmap [i]);
3056 #endif
3057         printf ("\n");
3058         while (klass != NULL) {
3059                 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3060                 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3061                 if (!mono_error_ok (&error)) {
3062                         printf ("  Type failed due to %s\n", mono_error_get_message (&error));
3063                         mono_error_cleanup (&error);
3064                 } else if (ifaces) {
3065                         for (i = 0; i < ifaces->len; i++) {
3066                                 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3067                                 printf ("  [UIID %d] interface %s\n", ic->interface_id, ic->name);
3068                                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
3069                                                 ic->interface_id,
3070                                                 mono_class_interface_offset (klass, ic),
3071                                                 mono_class_get_method_count (ic),
3072                                                 ic->name_space,
3073                                                 ic->name );
3074                         }
3075                         g_ptr_array_free (ifaces, TRUE);
3076                 }
3077                 ancestor_level ++;
3078                 klass = klass->parent;
3079         }
3080 }
3081
3082 /*
3083  * Return the number of virtual methods.
3084  * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3085  * Return -1 on failure.
3086  * FIXME It would be nice if this information could be cached somewhere.
3087  */
3088 static int
3089 count_virtual_methods (MonoClass *klass)
3090 {
3091         int i, mcount, vcount = 0;
3092         guint32 flags;
3093         klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3094
3095         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3096                 mono_class_setup_methods (klass);
3097                 if (mono_class_has_failure (klass))
3098                         return -1;
3099
3100                 mcount = mono_class_get_method_count (klass);
3101                 for (i = 0; i < mcount; ++i) {
3102                         flags = klass->methods [i]->flags;
3103                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3104                                 ++vcount;
3105                 }
3106         } else {
3107                 int first_idx = mono_class_get_first_method_idx (klass);
3108                 mcount = mono_class_get_method_count (klass);
3109                 for (i = 0; i < mcount; ++i) {
3110                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3111
3112                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3113                                 ++vcount;
3114                 }
3115         }
3116         return vcount;
3117 }
3118
3119 static int
3120 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3121 {
3122         int m, l = 0;
3123         if (!num_ifaces)
3124                 return -1;
3125         while (1) {
3126                 if (l > num_ifaces)
3127                         return -1;
3128                 m = (l + num_ifaces) / 2;
3129                 if (interfaces_full [m] == ic)
3130                         return m;
3131                 if (l == num_ifaces)
3132                         return -1;
3133                 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3134                         num_ifaces = m - 1;
3135                 } else {
3136                         l =  m + 1;
3137                 }
3138         }
3139 }
3140
3141 static mono_bool
3142 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3143 {
3144         int i = find_interface (num_ifaces, interfaces_full, ic);
3145         if (i >= 0) {
3146                 if (!force_set)
3147                         return TRUE;
3148                 interface_offsets_full [i] = offset;
3149                 return FALSE;
3150         }
3151         for (i = 0; i < num_ifaces; ++i) {
3152                 if (interfaces_full [i]) {
3153                         int end;
3154                         if (interfaces_full [i]->interface_id < ic->interface_id)
3155                                 continue;
3156                         end = i + 1;
3157                         while (end < num_ifaces && interfaces_full [end]) end++;
3158                         memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3159                         memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3160                 }
3161                 interfaces_full [i] = ic;
3162                 interface_offsets_full [i] = offset;
3163                 break;
3164         }
3165         return FALSE;
3166 }
3167
3168 #ifdef COMPRESSED_INTERFACE_BITMAP
3169
3170 /*
3171  * Compressed interface bitmap design.
3172  *
3173  * Interface bitmaps take a large amount of memory, because their size is
3174  * linear with the maximum interface id assigned in the process (each interface
3175  * is assigned a unique id as it is loaded). The number of interface classes
3176  * is high because of the many implicit interfaces implemented by arrays (we'll
3177  * need to lazy-load them in the future).
3178  * Most classes implement a very small number of interfaces, so the bitmap is
3179  * sparse. This bitmap needs to be checked by interface casts, so access to the
3180  * needed bit must be fast and doable with few jit instructions.
3181  *
3182  * The current compression format is as follows:
3183  * *) it is a sequence of one or more two-byte elements
3184  * *) the first byte in the element is the count of empty bitmap bytes
3185  * at the current bitmap position
3186  * *) the second byte in the element is an actual bitmap byte at the current
3187  * bitmap position
3188  *
3189  * As an example, the following compressed bitmap bytes:
3190  *      0x07 0x01 0x00 0x7
3191  * correspond to the following bitmap:
3192  *      0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3193  *
3194  * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3195  * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3196  * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3197  */
3198
3199 /**
3200  * mono_compress_bitmap:
3201  * \param dest destination buffer
3202  * \param bitmap bitmap buffer
3203  * \param size size of \p bitmap in bytes
3204  *
3205  * This is a mono internal function.
3206  * The \p bitmap data is compressed into a format that is small but
3207  * still searchable in few instructions by the JIT and runtime.
3208  * The compressed data is stored in the buffer pointed to by the
3209  * \p dest array. Passing a NULL value for \p dest allows to just compute
3210  * the size of the buffer.
3211  * This compression algorithm assumes the bits set in the bitmap are
3212  * few and far between, like in interface bitmaps.
3213  * \returns The size of the compressed bitmap in bytes.
3214  */
3215 int
3216 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3217 {
3218         int numz = 0;
3219         int res = 0;
3220         const uint8_t *end = bitmap + size;
3221         while (bitmap < end) {
3222                 if (*bitmap || numz == 255) {
3223                         if (dest) {
3224                                 *dest++ = numz;
3225                                 *dest++ = *bitmap;
3226                         }
3227                         res += 2;
3228                         numz = 0;
3229                         bitmap++;
3230                         continue;
3231                 }
3232                 bitmap++;
3233                 numz++;
3234         }
3235         if (numz) {
3236                 res += 2;
3237                 if (dest) {
3238                         *dest++ = numz;
3239                         *dest++ = 0;
3240                 }
3241         }
3242         return res;
3243 }
3244
3245 /**
3246  * mono_class_interface_match:
3247  * \param bitmap a compressed bitmap buffer
3248  * \param id the index to check in the bitmap
3249  *
3250  * This is a mono internal function.
3251  * Checks if a bit is set in a compressed interface bitmap. \p id must
3252  * be already checked for being smaller than the maximum id encoded in the
3253  * bitmap.
3254  *
3255  * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3256  * FALSE otherwise.
3257  */
3258 int
3259 mono_class_interface_match (const uint8_t *bitmap, int id)
3260 {
3261         while (TRUE) {
3262                 id -= bitmap [0] * 8;
3263                 if (id < 8) {
3264                         if (id < 0)
3265                                 return 0;
3266                         return bitmap [1] & (1 << id);
3267                 }
3268                 bitmap += 2;
3269                 id -= 8;
3270         }
3271 }
3272 #endif
3273
3274 /*
3275  * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3276  * LOCKING: Acquires the loader lock.
3277  */
3278 static int
3279 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3280 {
3281         MonoError error;
3282         MonoClass *k, *ic;
3283         int i, j, num_ifaces;
3284         guint32 max_iid;
3285         MonoClass **interfaces_full = NULL;
3286         int *interface_offsets_full = NULL;
3287         GPtrArray *ifaces;
3288         GPtrArray **ifaces_array = NULL;
3289         int interface_offsets_count;
3290
3291         mono_loader_lock ();
3292
3293         mono_class_setup_supertypes (klass);
3294
3295         /* compute maximum number of slots and maximum interface id */
3296         max_iid = 0;
3297         num_ifaces = 0; /* this can include duplicated ones */
3298         ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3299         for (j = 0; j < klass->idepth; j++) {
3300                 k = klass->supertypes [j];
3301                 g_assert (k);
3302                 num_ifaces += k->interface_count;
3303                 for (i = 0; i < k->interface_count; i++) {
3304                         ic = k->interfaces [i];
3305
3306                         mono_class_init (ic);
3307
3308                         if (max_iid < ic->interface_id)
3309                                 max_iid = ic->interface_id;
3310                 }
3311                 ifaces = mono_class_get_implemented_interfaces (k, &error);
3312                 if (!mono_error_ok (&error)) {
3313                         char *name = mono_type_get_full_name (k);
3314                         mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3315                         g_free (name);
3316                         mono_error_cleanup (&error);
3317                         cur_slot = -1;
3318                         goto end;
3319                 }
3320                 if (ifaces) {
3321                         num_ifaces += ifaces->len;
3322                         for (i = 0; i < ifaces->len; ++i) {
3323                                 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3324                                 if (max_iid < ic->interface_id)
3325                                         max_iid = ic->interface_id;
3326                         }
3327                         ifaces_array [j] = ifaces;
3328                 }
3329         }
3330
3331         if (MONO_CLASS_IS_INTERFACE (klass)) {
3332                 num_ifaces++;
3333                 if (max_iid < klass->interface_id)
3334                         max_iid = klass->interface_id;
3335         }
3336
3337         /* compute vtable offset for interfaces */
3338         interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3339         interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3340
3341         for (i = 0; i < num_ifaces; i++)
3342                 interface_offsets_full [i] = -1;
3343
3344         /* skip the current class */
3345         for (j = 0; j < klass->idepth - 1; j++) {
3346                 k = klass->supertypes [j];
3347                 ifaces = ifaces_array [j];
3348
3349                 if (ifaces) {
3350                         for (i = 0; i < ifaces->len; ++i) {
3351                                 int io;
3352                                 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3353                                 
3354                                 /*Force the sharing of interface offsets between parent and subtypes.*/
3355                                 io = mono_class_interface_offset (k, ic);
3356                                 g_assert (io >= 0);
3357                                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3358                         }
3359                 }
3360         }
3361
3362         g_assert (klass == klass->supertypes [klass->idepth - 1]);
3363         ifaces = ifaces_array [klass->idepth - 1];
3364         if (ifaces) {
3365                 for (i = 0; i < ifaces->len; ++i) {
3366                         int count;
3367                         ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3368                         if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3369                                 continue;
3370                         count = count_virtual_methods (ic);
3371                         if (count == -1) {
3372                                 char *name = mono_type_get_full_name (ic);
3373                                 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3374                                 g_free (name);
3375                                 cur_slot = -1;
3376                                 goto end;
3377                         }
3378                         cur_slot += count;
3379                 }
3380         }
3381
3382         if (MONO_CLASS_IS_INTERFACE (klass))
3383                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3384
3385         for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3386                 if (interface_offsets_full [i] != -1)
3387                         interface_offsets_count ++;
3388         }
3389
3390         /* Publish the data */
3391         klass->max_interface_id = max_iid;
3392         /*
3393          * We might get called multiple times:
3394          * - mono_class_init ()
3395          * - mono_class_setup_vtable ().
3396          * - mono_class_setup_interface_offsets ().
3397          * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3398          * means we have to overwrite those when called from other places (#4440).
3399          */
3400         if (klass->interfaces_packed) {
3401                 if (!overwrite)
3402                         g_assert (klass->interface_offsets_count == interface_offsets_count);
3403         } else {
3404                 uint8_t *bitmap;
3405                 int bsize;
3406                 klass->interface_offsets_count = interface_offsets_count;
3407                 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3408                 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3409                 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3410 #ifdef COMPRESSED_INTERFACE_BITMAP
3411                 bitmap = g_malloc0 (bsize);
3412 #else
3413                 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3414 #endif
3415                 for (i = 0; i < interface_offsets_count; i++) {
3416                         guint32 id = interfaces_full [i]->interface_id;
3417                         bitmap [id >> 3] |= (1 << (id & 7));
3418                         klass->interfaces_packed [i] = interfaces_full [i];
3419                         klass->interface_offsets_packed [i] = interface_offsets_full [i];
3420                 }
3421 #ifdef COMPRESSED_INTERFACE_BITMAP
3422                 i = mono_compress_bitmap (NULL, bitmap, bsize);
3423                 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3424                 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3425                 g_free (bitmap);
3426 #else
3427                 klass->interface_bitmap = bitmap;
3428 #endif
3429         }
3430 end:
3431         mono_loader_unlock ();
3432
3433         g_free (interfaces_full);
3434         g_free (interface_offsets_full);
3435         for (i = 0; i < klass->idepth; i++) {
3436                 ifaces = ifaces_array [i];
3437                 if (ifaces)
3438                         g_ptr_array_free (ifaces, TRUE);
3439         }
3440         g_free (ifaces_array);
3441         
3442         //printf ("JUST DONE: ");
3443         //print_implemented_interfaces (klass);
3444
3445         return cur_slot;
3446 }
3447
3448 /*
3449  * Setup interface offsets for interfaces. 
3450  * Initializes:
3451  * - klass->max_interface_id
3452  * - klass->interface_offsets_count
3453  * - klass->interfaces_packed
3454  * - klass->interface_offsets_packed
3455  * - klass->interface_bitmap
3456  *
3457  * This function can fail @class.
3458  */
3459 void
3460 mono_class_setup_interface_offsets (MonoClass *klass)
3461 {
3462         setup_interface_offsets (klass, 0, FALSE);
3463 }
3464
3465 /*Checks if @klass has @parent as one of it's parents type gtd
3466  *
3467  * For example:
3468  *      Foo<T>
3469  *      Bar<T> : Foo<Bar<Bar<T>>>
3470  *
3471  */
3472 static gboolean
3473 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3474 {
3475         klass = mono_class_get_generic_type_definition (klass);
3476         parent = mono_class_get_generic_type_definition (parent);
3477         mono_class_setup_supertypes (klass);
3478         mono_class_setup_supertypes (parent);
3479
3480         return klass->idepth >= parent->idepth &&
3481                 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3482 }
3483
3484 gboolean
3485 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3486 {
3487         MonoGenericInst *ginst;
3488         int i;
3489
3490         if (!mono_class_is_ginst (klass)) {
3491                 mono_class_setup_vtable_full (klass, in_setup);
3492                 return !mono_class_has_failure (klass);
3493         }
3494
3495         mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3496         if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3497                 return FALSE;
3498
3499         ginst = mono_class_get_generic_class (klass)->context.class_inst;
3500         for (i = 0; i < ginst->type_argc; ++i) {
3501                 MonoClass *arg;
3502                 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3503                         continue;
3504                 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3505                 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3506                 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3507                         continue;
3508                 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3509                         mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3510                         return FALSE;
3511                 }
3512         }
3513         return TRUE;
3514 }
3515  
3516 /*
3517  * mono_class_setup_vtable:
3518  *
3519  *   Creates the generic vtable of CLASS.
3520  * Initializes the following fields in MonoClass:
3521  * - vtable
3522  * - vtable_size
3523  * Plus all the fields initialized by setup_interface_offsets ().
3524  * If there is an error during vtable construction, klass->has_failure
3525  * is set and details are stored in a MonoErrorBoxed.
3526  *
3527  * LOCKING: Acquires the loader lock.
3528  */
3529 void
3530 mono_class_setup_vtable (MonoClass *klass)
3531 {
3532         mono_class_setup_vtable_full (klass, NULL);
3533 }
3534
3535 static void
3536 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3537 {
3538         MonoError error;
3539         MonoMethod **overrides;
3540         MonoGenericContext *context;
3541         guint32 type_token;
3542         int onum = 0;
3543         gboolean ok = TRUE;
3544
3545         if (klass->vtable)
3546                 return;
3547
3548         if (MONO_CLASS_IS_INTERFACE (klass)) {
3549                 /* This sets method->slot for all methods if this is an interface */
3550                 mono_class_setup_methods (klass);
3551                 return;
3552         }
3553
3554         if (mono_class_has_failure (klass))
3555                 return;
3556
3557         if (g_list_find (in_setup, klass))
3558                 return;
3559
3560         mono_loader_lock ();
3561
3562         if (klass->vtable) {
3563                 mono_loader_unlock ();
3564                 return;
3565         }
3566
3567         mono_stats.generic_vtable_count ++;
3568         in_setup = g_list_prepend (in_setup, klass);
3569
3570         if (mono_class_is_ginst (klass)) {
3571                 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3572                         mono_loader_unlock ();
3573                         g_list_remove (in_setup, klass);
3574                         return;
3575                 }
3576
3577                 context = mono_class_get_context (klass);
3578                 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3579         } else {
3580                 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3581                 type_token = klass->type_token;
3582         }
3583
3584         if (image_is_dynamic (klass->image)) {
3585                 /* Generic instances can have zero method overrides without causing any harm.
3586                  * This is true since we don't do layout all over again for them, we simply inflate
3587                  * the layout of the parent.
3588                  */
3589                 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3590                 if (!is_ok (&error)) {
3591                         mono_loader_unlock ();
3592                         g_list_remove (in_setup, klass);
3593                         mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3594                         mono_error_cleanup (&error);
3595                         return;
3596                 }
3597         } else {
3598                 /* The following call fails if there are missing methods in the type */
3599                 /* FIXME it's probably a good idea to avoid this for generic instances. */
3600                 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3601         }
3602
3603         if (ok)
3604                 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3605         else
3606                 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3607                 
3608         g_free (overrides);
3609
3610         mono_loader_unlock ();
3611         g_list_remove (in_setup, klass);
3612
3613         return;
3614 }
3615
3616 #define DEBUG_INTERFACE_VTABLE_CODE 0
3617 #define TRACE_INTERFACE_VTABLE_CODE 0
3618 #define VERIFY_INTERFACE_VTABLE_CODE 0
3619 #define VTABLE_SELECTOR (1)
3620
3621 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3622 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3623         if (!(VTABLE_SELECTOR)) break; \
3624         stmt;\
3625 } while (0)
3626 #else
3627 #define DEBUG_INTERFACE_VTABLE(stmt)
3628 #endif
3629
3630 #if TRACE_INTERFACE_VTABLE_CODE
3631 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3632         if (!(VTABLE_SELECTOR)) break; \
3633         stmt;\
3634 } while (0)
3635 #else
3636 #define TRACE_INTERFACE_VTABLE(stmt)
3637 #endif
3638
3639 #if VERIFY_INTERFACE_VTABLE_CODE
3640 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3641         if (!(VTABLE_SELECTOR)) break; \
3642         stmt;\
3643 } while (0)
3644 #else
3645 #define VERIFY_INTERFACE_VTABLE(stmt)
3646 #endif
3647
3648
3649 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3650 static char*
3651 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3652 {
3653         int i;
3654         char *result;
3655         GString *res = g_string_new ("");
3656         
3657         g_string_append_c (res, '(');
3658         for (i = 0; i < sig->param_count; ++i) {
3659                 if (i > 0)
3660                         g_string_append_c (res, ',');
3661                 mono_type_get_desc (res, sig->params [i], include_namespace);
3662         }
3663         g_string_append (res, ")=>");
3664         if (sig->ret != NULL) {
3665                 mono_type_get_desc (res, sig->ret, include_namespace);
3666         } else {
3667                 g_string_append (res, "NULL");
3668         }
3669         result = res->str;
3670         g_string_free (res, FALSE);
3671         return result;
3672 }
3673 static void
3674 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3675         char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3676         char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3677         printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3678         g_free (im_sig);
3679         g_free (cm_sig);
3680         
3681 }
3682
3683 #endif
3684 static gboolean
3685 is_wcf_hack_disabled (void)
3686 {
3687         static gboolean disabled;
3688         static gboolean inited = FALSE;
3689         if (!inited) {
3690                 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3691                 inited = TRUE;
3692         }
3693         return disabled;
3694 }
3695
3696 static gboolean
3697 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3698 {
3699         MonoMethodSignature *cmsig, *imsig;
3700         if (strcmp (im->name, cm->name) == 0) {
3701                 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3702                         TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3703                         return FALSE;
3704                 }
3705                 if (! slot_is_empty) {
3706                         if (require_newslot) {
3707                                 if (! interface_is_explicitly_implemented_by_class) {
3708                                         TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3709                                         return FALSE;
3710                                 }
3711                                 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3712                                         TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3713                                         return FALSE;
3714                                 }
3715                         } else {
3716                                 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3717                         }
3718                 }
3719                 cmsig = mono_method_signature (cm);
3720                 imsig = mono_method_signature (im);
3721                 if (!cmsig || !imsig) {
3722                         mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3723                         return FALSE;
3724                 }
3725
3726                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3727                         TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED  "));
3728                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3729                         TRACE_INTERFACE_VTABLE (printf ("]"));
3730                         return FALSE;
3731                 }
3732                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3733                 if (mono_security_core_clr_enabled ())
3734                         mono_security_core_clr_check_override (klass, cm, im);
3735
3736                 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3737                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3738                         char *body_name = mono_method_full_name (cm, TRUE);
3739                         char *decl_name = mono_method_full_name (im, TRUE);
3740                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3741                         g_free (body_name);
3742                         g_free (decl_name);
3743                         return FALSE;
3744                 }
3745
3746                 return TRUE;
3747         } else {
3748                 MonoClass *ic = im->klass;
3749                 const char *ic_name_space = ic->name_space;
3750                 const char *ic_name = ic->name;
3751                 char *subname;
3752                 
3753                 if (! require_newslot) {
3754                         TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3755                         return FALSE;
3756                 }
3757                 if (cm->klass->rank == 0) {
3758                         TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3759                         return FALSE;
3760                 }
3761                 cmsig = mono_method_signature (cm);
3762                 imsig = mono_method_signature (im);
3763                 if (!cmsig || !imsig) {
3764                         mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3765                         return FALSE;
3766                 }
3767
3768                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3769                         TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED  "));
3770                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3771                         TRACE_INTERFACE_VTABLE (printf ("]"));
3772                         return FALSE;
3773                 }
3774                 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3775                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3776                         return FALSE;
3777                 }
3778                 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3779                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3780                         return FALSE;
3781                 }
3782                 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
3783                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3784                         return FALSE;
3785                 }
3786                 
3787                 subname = strstr (cm->name, ic_name_space);
3788                 if (subname != cm->name) {
3789                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3790                         return FALSE;
3791                 }
3792                 subname += strlen (ic_name_space);
3793                 if (subname [0] != '.') {
3794                         TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3795                         return FALSE;
3796                 }
3797                 subname ++;
3798                 if (strstr (subname, ic_name) != subname) {
3799                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3800                         return FALSE;
3801                 }
3802                 subname += strlen (ic_name);
3803                 if (subname [0] != '.') {
3804                         TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3805                         return FALSE;
3806                 }
3807                 subname ++;
3808                 if (strcmp (subname, im->name) != 0) {
3809                         TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3810                         return FALSE;
3811                 }
3812                 
3813                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3814                 if (mono_security_core_clr_enabled ())
3815                         mono_security_core_clr_check_override (klass, cm, im);
3816
3817                 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3818                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3819                         char *body_name = mono_method_full_name (cm, TRUE);
3820                         char *decl_name = mono_method_full_name (im, TRUE);
3821                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3822                         g_free (body_name);
3823                         g_free (decl_name);
3824                         return FALSE;
3825                 }
3826                 
3827                 return TRUE;
3828         }
3829 }
3830
3831 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3832 static void
3833 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3834         MonoMethod *method = key;
3835         MonoMethod *override = value;
3836         MonoClass *method_class = mono_method_get_class (method);
3837         MonoClass *override_class = mono_method_get_class (override);
3838         
3839         printf ("  Method '%s.%s:%s' has override '%s.%s:%s'\n",
3840                         mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3841                         mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3842 }
3843 static void
3844 print_overrides (GHashTable *override_map, const char *message) {
3845         if (override_map) {
3846                 printf ("Override map \"%s\" START:\n", message);
3847                 g_hash_table_foreach (override_map, foreach_override, NULL);
3848                 printf ("Override map \"%s\" END.\n", message);
3849         } else {
3850                 printf ("Override map \"%s\" EMPTY.\n", message);
3851         }
3852 }
3853 static void
3854 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3855         char *full_name = mono_type_full_name (&klass->byval_arg);
3856         int i;
3857         int parent_size;
3858         
3859         printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3860         
3861         if (print_interfaces) {
3862                 print_implemented_interfaces (klass);
3863                 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3864         }
3865         
3866         if (klass->parent) {
3867                 parent_size = klass->parent->vtable_size;
3868         } else {
3869                 parent_size = 0;
3870         }
3871         for (i = 0; i < size; ++i) {
3872                 MonoMethod *cm = vtable [i];
3873                 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3874                 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3875
3876                 printf ("  [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3877                 g_free (cm_name);
3878         }
3879
3880         g_free (full_name);
3881 }
3882 #endif
3883
3884 #if VERIFY_INTERFACE_VTABLE_CODE
3885 static int
3886 mono_method_try_get_vtable_index (MonoMethod *method)
3887 {
3888         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3889                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3890                 if (imethod->declaring->is_generic)
3891                         return imethod->declaring->slot;
3892         }
3893         return method->slot;
3894 }
3895
3896 static void
3897 mono_class_verify_vtable (MonoClass *klass)
3898 {
3899         int i, count;
3900         char *full_name = mono_type_full_name (&klass->byval_arg);
3901
3902         printf ("*** Verifying VTable of class '%s' \n", full_name);
3903         g_free (full_name);
3904         full_name = NULL;
3905         
3906         if (!klass->methods)
3907                 return;
3908
3909         count = mono_class_method_count (klass);
3910         for (i = 0; i < count; ++i) {
3911                 MonoMethod *cm = klass->methods [i];
3912                 int slot;
3913
3914                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3915                         continue;
3916
3917                 g_free (full_name);
3918                 full_name = mono_method_full_name (cm, TRUE);
3919
3920                 slot = mono_method_try_get_vtable_index (cm);
3921                 if (slot >= 0) {
3922                         if (slot >= klass->vtable_size) {
3923                                 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3924                                 continue;
3925                         }
3926
3927                         if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3928                                 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3929                                 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3930                                 g_free (other_name);
3931                         }
3932                 } else
3933                         printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3934         }
3935         g_free (full_name);
3936 }
3937 #endif
3938
3939 static void
3940 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3941 {
3942         int index, mcount;
3943         char *method_signature;
3944         char *type_name;
3945         
3946         for (index = 0; index < onum; ++index) {
3947                 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3948                          overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3949         }
3950         method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3951         type_name = mono_type_full_name (&klass->byval_arg);
3952         mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3953                 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3954         g_free (method_signature);
3955         g_free (type_name);
3956         mono_class_setup_methods (klass);
3957         if (mono_class_has_failure (klass)) {
3958                 char *name = mono_type_get_full_name (klass);
3959                 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3960                 g_free (name);
3961                 return;
3962         }
3963         mcount = mono_class_get_method_count (klass);
3964         for (index = 0; index < mcount; ++index) {
3965                 MonoMethod *cm = klass->methods [index];
3966                 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3967
3968                 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3969                 g_free (method_signature);
3970         }
3971 }
3972
3973 static MonoMethod*
3974 mono_method_get_method_definition (MonoMethod *method)
3975 {
3976         while (method->is_inflated)
3977                 method = ((MonoMethodInflated*)method)->declaring;
3978         return method;
3979 }
3980
3981 static gboolean
3982 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3983 {
3984         int i;
3985
3986         for (i = 0; i < onum; ++i) {
3987                 MonoMethod *decl = overrides [i * 2];
3988                 MonoMethod *body = overrides [i * 2 + 1];
3989
3990                 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3991                         mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3992                         return FALSE;
3993                 }
3994
3995                 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3996                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
3997                                 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
3998                         else
3999                                 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4000                         return FALSE;
4001                 }
4002
4003                 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4004                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
4005                                 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4006                         else
4007                                 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4008                         return FALSE;
4009                 }
4010
4011                 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4012                         mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4013                         return FALSE;
4014                 }
4015
4016                 body = mono_method_get_method_definition (body);
4017                 decl = mono_method_get_method_definition (decl);
4018
4019                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4020                         char *body_name = mono_method_full_name (body, TRUE);
4021                         char *decl_name = mono_method_full_name (decl, TRUE);
4022                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4023                         g_free (body_name);
4024                         g_free (decl_name);
4025                         return FALSE;
4026                 }
4027         }
4028         return TRUE;
4029 }
4030
4031 static gboolean
4032 mono_class_need_stelemref_method (MonoClass *klass)
4033 {
4034         return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4035 }
4036
4037 static int
4038 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4039 {
4040         int dslot;
4041         dslot = mono_method_get_vtable_slot (decl);
4042         if (dslot == -1) {
4043                 mono_class_set_type_load_failure (klass, "");
4044                 return FALSE;
4045         }
4046
4047         dslot += mono_class_interface_offset (klass, decl->klass);
4048         vtable [dslot] = override;
4049         if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4050                 /*
4051                  * If override from an interface, then it is an override of a default interface method,
4052                  * don't override its slot.
4053                  */
4054                 vtable [dslot]->slot = dslot;
4055         }
4056
4057         if (mono_security_core_clr_enabled ())
4058                 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4059
4060         return TRUE;
4061 }
4062
4063 /*
4064  * LOCKING: this is supposed to be called with the loader lock held.
4065  */
4066 void
4067 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4068 {
4069         MonoError error;
4070         MonoClass *k, *ic;
4071         MonoMethod **vtable = NULL;
4072         int i, max_vtsize = 0, cur_slot = 0;
4073         guint32 max_iid;
4074         GPtrArray *ifaces = NULL;
4075         GHashTable *override_map = NULL;
4076         MonoMethod *cm;
4077 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4078         int first_non_interface_slot;
4079 #endif
4080         GSList *virt_methods = NULL, *l;
4081         int stelemref_slot = 0;
4082
4083         if (klass->vtable)
4084                 return;
4085
4086         if (overrides && !verify_class_overrides (klass, overrides, onum))
4087                 return;
4088
4089         ifaces = mono_class_get_implemented_interfaces (klass, &error);
4090         if (!mono_error_ok (&error)) {
4091                 char *name = mono_type_get_full_name (klass);
4092                 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4093                 g_free (name);
4094                 mono_error_cleanup (&error);
4095                 return;
4096         } else if (ifaces) {
4097                 for (i = 0; i < ifaces->len; i++) {
4098                         MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4099                         max_vtsize += mono_class_get_method_count (ic);
4100                 }
4101                 g_ptr_array_free (ifaces, TRUE);
4102                 ifaces = NULL;
4103         }
4104         
4105         if (klass->parent) {
4106                 mono_class_init (klass->parent);
4107                 mono_class_setup_vtable_full (klass->parent, in_setup);
4108
4109                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4110                         return;
4111
4112                 max_vtsize += klass->parent->vtable_size;
4113                 cur_slot = klass->parent->vtable_size;
4114         }
4115
4116         max_vtsize += mono_class_get_method_count (klass);
4117
4118         /*Array have a slot for stelemref*/
4119         if (mono_class_need_stelemref_method (klass)) {
4120                 stelemref_slot = cur_slot;
4121                 ++max_vtsize;
4122                 ++cur_slot;
4123         }
4124
4125         /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4126
4127         cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4128         if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4129                 return;
4130
4131         max_iid = klass->max_interface_id;
4132         DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4133
4134         /* Optimized version for generic instances */
4135         if (mono_class_is_ginst (klass)) {
4136                 MonoError error;
4137                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4138                 MonoMethod **tmp;
4139
4140                 mono_class_setup_vtable_full (gklass, in_setup);
4141                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4142                         return;
4143
4144                 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4145                 klass->vtable_size = gklass->vtable_size;
4146                 for (i = 0; i < gklass->vtable_size; ++i)
4147                         if (gklass->vtable [i]) {
4148                                 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4149                                 if (!mono_error_ok (&error)) {
4150                                         mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4151                                         mono_error_cleanup (&error);
4152                                         return;
4153                                 }
4154                                 tmp [i] = inflated;
4155                                 tmp [i]->slot = gklass->vtable [i]->slot;
4156                         }
4157                 mono_memory_barrier ();
4158                 klass->vtable = tmp;
4159
4160                 /* Have to set method->slot for abstract virtual methods */
4161                 if (klass->methods && gklass->methods) {
4162                         int mcount = mono_class_get_method_count (klass);
4163                         for (i = 0; i < mcount; ++i)
4164                                 if (klass->methods [i]->slot == -1)
4165                                         klass->methods [i]->slot = gklass->methods [i]->slot;
4166                 }
4167
4168                 return;
4169         }
4170
4171         vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4172
4173         if (klass->parent && klass->parent->vtable_size) {
4174                 MonoClass *parent = klass->parent;
4175                 int i;
4176                 
4177                 memcpy (vtable, parent->vtable,  sizeof (gpointer) * parent->vtable_size);
4178                 
4179                 // Also inherit parent interface vtables, just as a starting point.
4180                 // This is needed otherwise bug-77127.exe fails when the property methods
4181                 // have different names in the iterface and the class, because for child
4182                 // classes the ".override" information is not used anymore.
4183                 for (i = 0; i < parent->interface_offsets_count; i++) {
4184                         MonoClass *parent_interface = parent->interfaces_packed [i];
4185                         int interface_offset = mono_class_interface_offset (klass, parent_interface);
4186                         /*FIXME this is now dead code as this condition will never hold true.
4187                         Since interface offsets are inherited then the offset of an interface implemented
4188                         by a parent will never be the out of it's vtable boundary.
4189                         */
4190                         if (interface_offset >= parent->vtable_size) {
4191                                 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4192                                 int j;
4193                                 
4194                                 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4195                                 TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4196                                 int mcount = mono_class_get_method_count (parent_interface);
4197                                 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4198                                         vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4199                                         TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4200                                                         parent_interface_offset + j, parent_interface_offset, j,
4201                                                         interface_offset + j, interface_offset, j));
4202                                 }
4203                         }
4204                         
4205                 }
4206         }
4207
4208         /*Array have a slot for stelemref*/
4209         if (mono_class_need_stelemref_method (klass)) {
4210                 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4211                 if (!method->slot)
4212                         method->slot = stelemref_slot;
4213                 else
4214                         g_assert (method->slot == stelemref_slot);
4215
4216                 vtable [stelemref_slot] = method;
4217         }
4218
4219         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4220
4221         /* Process overrides from interface default methods */
4222         // FIXME: Ordering between interfaces
4223         for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4224                 ic = klass->interfaces_packed [ifindex];
4225
4226                 mono_class_setup_methods (ic);
4227                 if (mono_class_has_failure (ic))
4228                         goto fail;
4229
4230                 MonoMethod **iface_overrides;
4231                 int iface_onum;
4232                 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4233                 if (ok) {
4234                         for (int i = 0; i < iface_onum; i++) {
4235                                 MonoMethod *decl = iface_overrides [i*2];
4236                                 MonoMethod *override = iface_overrides [i*2 + 1];
4237                                 if (!apply_override (klass, vtable, decl, override))
4238                                         goto fail;
4239
4240                                 if (!override_map)
4241                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4242                                 g_hash_table_insert (override_map, decl, override);
4243                         }
4244                         g_free (iface_overrides);
4245                 }
4246         }
4247
4248         /* override interface methods */
4249         for (i = 0; i < onum; i++) {
4250                 MonoMethod *decl = overrides [i*2];
4251                 MonoMethod *override = overrides [i*2 + 1];
4252                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4253                         if (!apply_override (klass, vtable, decl, override))
4254                                 goto fail;
4255
4256                         if (!override_map)
4257                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4258                         g_hash_table_insert (override_map, decl, override);
4259                 }
4260         }
4261
4262         TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4263         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4264
4265         /*
4266          * Create a list of virtual methods to avoid calling 
4267          * mono_class_get_virtual_methods () which is slow because of the metadata
4268          * optimization.
4269          */
4270         {
4271                 gpointer iter = NULL;
4272                 MonoMethod *cm;
4273
4274                 virt_methods = NULL;
4275                 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4276                         virt_methods = g_slist_prepend (virt_methods, cm);
4277                 }
4278                 if (mono_class_has_failure (klass))
4279                         goto fail;
4280         }
4281         
4282         // Loop on all implemented interfaces...
4283         for (i = 0; i < klass->interface_offsets_count; i++) {
4284                 MonoClass *parent = klass->parent;
4285                 int ic_offset;
4286                 gboolean interface_is_explicitly_implemented_by_class;
4287                 int im_index;
4288                 
4289                 ic = klass->interfaces_packed [i];
4290                 ic_offset = mono_class_interface_offset (klass, ic);
4291
4292                 mono_class_setup_methods (ic);
4293                 if (mono_class_has_failure (ic))
4294                         goto fail;
4295                 
4296                 // Check if this interface is explicitly implemented (instead of just inherited)
4297                 if (parent != NULL) {
4298                         int implemented_interfaces_index;
4299                         interface_is_explicitly_implemented_by_class = FALSE;
4300                         for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4301                                 if (ic == klass->interfaces [implemented_interfaces_index]) {
4302                                         interface_is_explicitly_implemented_by_class = TRUE;
4303                                         break;
4304                                 }
4305                         }
4306                 } else {
4307                         interface_is_explicitly_implemented_by_class = TRUE;
4308                 }
4309                 
4310                 // Loop on all interface methods...
4311                 int mcount = mono_class_get_method_count (ic);
4312                 for (im_index = 0; im_index < mcount; im_index++) {
4313                         MonoMethod *im = ic->methods [im_index];
4314                         int im_slot = ic_offset + im->slot;
4315                         MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4316                         
4317                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
4318                                 continue;
4319
4320                         TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4321
4322                         // If there is an explicit implementation, just use it right away,
4323                         // otherwise look for a matching method
4324                         if (override_im == NULL) {
4325                                 int cm_index;
4326                                 MonoMethod *cm;
4327
4328                                 // First look for a suitable method among the class methods
4329                                 for (l = virt_methods; l; l = l->next) {
4330                                         cm = (MonoMethod *)l->data;
4331                                         TRACE_INTERFACE_VTABLE (printf ("    For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
4332                                         if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4333                                                 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4334                                                 vtable [im_slot] = cm;
4335                                                 /* Why do we need this? */
4336                                                 if (cm->slot < 0) {
4337                                                         cm->slot = im_slot;
4338                                                 }
4339                                         }
4340                                         TRACE_INTERFACE_VTABLE (printf ("\n"));
4341                                         if (mono_class_has_failure (klass))  /*Might be set by check_interface_method_override*/
4342                                                 goto fail;
4343                                 }
4344                                 
4345                                 // If the slot is still empty, look in all the inherited virtual methods...
4346                                 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4347                                         MonoClass *parent = klass->parent;
4348                                         // Reverse order, so that last added methods are preferred
4349                                         for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4350                                                 MonoMethod *cm = parent->vtable [cm_index];
4351                                                 
4352                                                 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("    For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
4353                                                 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4354                                                         TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4355                                                         vtable [im_slot] = cm;
4356                                                         /* Why do we need this? */
4357                                                         if (cm->slot < 0) {
4358                                                                 cm->slot = im_slot;
4359                                                         }
4360                                                         break;
4361                                                 }
4362                                                 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4363                                                         goto fail;
4364                                                 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4365                                         }
4366                                 }
4367
4368                                 if (vtable [im_slot] == NULL) {
4369                                         if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4370                                                 TRACE_INTERFACE_VTABLE (printf ("    Using default iface method %s.\n", mono_method_full_name (im, 1)));
4371                                                 vtable [im_slot] = im;
4372                                         }
4373                                 }
4374                         } else {
4375                                 g_assert (vtable [im_slot] == override_im);
4376                         }
4377                 }
4378         }
4379         
4380         // If the class is not abstract, check that all its interface slots are full.
4381         // The check is done here and not directly at the end of the loop above because
4382         // it can happen (for injected generic array interfaces) that the same slot is
4383         // processed multiple times (those interfaces have overlapping slots), and it
4384         // will not always be the first pass the one that fills the slot.
4385         if (!mono_class_is_abstract (klass)) {
4386                 for (i = 0; i < klass->interface_offsets_count; i++) {
4387                         int ic_offset;
4388                         int im_index;
4389                         
4390                         ic = klass->interfaces_packed [i];
4391                         ic_offset = mono_class_interface_offset (klass, ic);
4392                         
4393                         int mcount = mono_class_get_method_count (ic);
4394                         for (im_index = 0; im_index < mcount; im_index++) {
4395                                 MonoMethod *im = ic->methods [im_index];
4396                                 int im_slot = ic_offset + im->slot;
4397                                 
4398                                 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4399                                         continue;
4400
4401                                 TRACE_INTERFACE_VTABLE (printf ("      [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4402                                                 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4403                                 if (vtable [im_slot] == NULL) {
4404                                         print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4405                                         goto fail;
4406                                 }
4407                         }
4408                 }
4409         }
4410
4411         TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4412         for (l = virt_methods; l; l = l->next) {
4413                 cm = (MonoMethod *)l->data;
4414                 /*
4415                  * If the method is REUSE_SLOT, we must check in the
4416                  * base class for a method to override.
4417                  */
4418                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4419                         int slot = -1;
4420                         for (k = klass->parent; k ; k = k->parent) {
4421                                 gpointer k_iter;
4422                                 MonoMethod *m1;
4423
4424                                 k_iter = NULL;
4425                                 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4426                                         MonoMethodSignature *cmsig, *m1sig;
4427
4428                                         cmsig = mono_method_signature (cm);
4429                                         m1sig = mono_method_signature (m1);
4430
4431                                         if (!cmsig || !m1sig) {
4432                                                 /* FIXME proper error message */
4433                                                 mono_class_set_type_load_failure (klass, "");
4434                                                 return;
4435                                         }
4436
4437                                         if (!strcmp(cm->name, m1->name) && 
4438                                             mono_metadata_signature_equal (cmsig, m1sig)) {
4439
4440                                                 if (mono_security_core_clr_enabled ())
4441                                                         mono_security_core_clr_check_override (klass, cm, m1);
4442
4443                                                 slot = mono_method_get_vtable_slot (m1);
4444                                                 if (slot == -1)
4445                                                         goto fail;
4446
4447                                                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4448                                                         char *body_name = mono_method_full_name (cm, TRUE);
4449                                                         char *decl_name = mono_method_full_name (m1, TRUE);
4450                                                         mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4451                                                         g_free (body_name);
4452                                                         g_free (decl_name);
4453                                                         goto fail;
4454                                                 }
4455
4456                                                 g_assert (cm->slot < max_vtsize);
4457                                                 if (!override_map)
4458                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4459                                                 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4460                                                         mono_method_full_name (m1, 1), m1,
4461                                                         mono_method_full_name (cm, 1), cm));
4462                                                 g_hash_table_insert (override_map, m1, cm);
4463                                                 break;
4464                                         }
4465                                 }
4466                                 if (mono_class_has_failure (k))
4467                                         goto fail;
4468                                 
4469                                 if (slot >= 0) 
4470                                         break;
4471                         }
4472                         if (slot >= 0)
4473                                 cm->slot = slot;
4474                 }
4475
4476                 /*Non final newslot methods must be given a non-interface vtable slot*/
4477                 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4478                         cm->slot = -1;
4479
4480                 if (cm->slot < 0)
4481                         cm->slot = cur_slot++;
4482
4483                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4484                         vtable [cm->slot] = cm;
4485         }
4486
4487         /* override non interface methods */
4488         for (i = 0; i < onum; i++) {
4489                 MonoMethod *decl = overrides [i*2];
4490                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4491                         g_assert (decl->slot != -1);
4492                         vtable [decl->slot] = overrides [i*2 + 1];
4493                         overrides [i * 2 + 1]->slot = decl->slot;
4494                         if (!override_map)
4495                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4496                         TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", 
4497                                 mono_method_full_name (decl, 1), decl,
4498                                 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4499                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4500
4501                         if (mono_security_core_clr_enabled ())
4502                                 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4503                 }
4504         }
4505
4506         /*
4507          * If a method occupies more than one place in the vtable, and it is
4508          * overriden, then change the other occurances too.
4509          */
4510         if (override_map) {
4511                 MonoMethod *cm;
4512
4513                 for (i = 0; i < max_vtsize; ++i)
4514                         if (vtable [i]) {
4515                                 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4516
4517                                 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4518                                 if (cm)
4519                                         vtable [i] = cm;
4520                         }
4521
4522                 g_hash_table_destroy (override_map);
4523                 override_map = NULL;
4524         }
4525
4526         g_slist_free (virt_methods);
4527         virt_methods = NULL;
4528
4529         g_assert (cur_slot <= max_vtsize);
4530
4531         /* Ensure that all vtable slots are filled with concrete instance methods */
4532         if (!mono_class_is_abstract (klass)) {
4533                 for (i = 0; i < cur_slot; ++i) {
4534                         if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4535                                 char *type_name = mono_type_get_full_name (klass);
4536                                 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4537                                 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4538                                 g_free (type_name);
4539                                 g_free (method_name);
4540                                 g_free (vtable);
4541                                 return;
4542                         }
4543                 }
4544         }
4545
4546         if (mono_class_is_ginst (klass)) {
4547                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4548
4549                 mono_class_init (gklass);
4550
4551                 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4552         } else {
4553                 /* Check that the vtable_size value computed in mono_class_init () is correct */
4554                 if (klass->vtable_size)
4555                         g_assert (cur_slot == klass->vtable_size);
4556                 klass->vtable_size = cur_slot;
4557         }
4558
4559         /* Try to share the vtable with our parent. */
4560         if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4561                 mono_memory_barrier ();
4562                 klass->vtable = klass->parent->vtable;
4563         } else {
4564                 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4565                 memcpy (tmp, vtable,  sizeof (gpointer) * klass->vtable_size);
4566                 mono_memory_barrier ();
4567                 klass->vtable = tmp;
4568         }
4569
4570         DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4571         if (mono_print_vtable) {
4572                 int icount = 0;
4573
4574                 print_implemented_interfaces (klass);
4575                 
4576                 for (i = 0; i <= max_iid; i++)
4577                         if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4578                                 icount++;
4579
4580                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4581                         klass->vtable_size, icount);
4582
4583                 for (i = 0; i < cur_slot; ++i) {
4584                         MonoMethod *cm;
4585                
4586                         cm = vtable [i];
4587                         if (cm) {
4588                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4589                                         mono_method_full_name (cm, TRUE));
4590                         }
4591                 }
4592
4593
4594                 if (icount) {
4595                         printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4596                                 klass->name, max_iid);
4597         
4598                         for (i = 0; i < klass->interface_count; i++) {
4599                                 ic = klass->interfaces [i];
4600                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4601                                         mono_class_interface_offset (klass, ic),
4602                                         count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4603                         }
4604
4605                         for (k = klass->parent; k ; k = k->parent) {
4606                                 for (i = 0; i < k->interface_count; i++) {
4607                                         ic = k->interfaces [i]; 
4608                                         printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4609                                                 mono_class_interface_offset (klass, ic),
4610                                                 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4611                                 }
4612                         }
4613                 }
4614         }
4615
4616         g_free (vtable);
4617
4618         VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4619         return;
4620
4621 fail:
4622         {
4623         char *name = mono_type_get_full_name (klass);
4624         mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4625         g_free (name);
4626         g_free (vtable);
4627         if (override_map)
4628                 g_hash_table_destroy (override_map);
4629         if (virt_methods)
4630                 g_slist_free (virt_methods);
4631         }
4632 }
4633
4634 /*
4635  * mono_method_get_vtable_slot:
4636  *
4637  *   Returns method->slot, computing it if neccesary. Return -1 on failure.
4638  * LOCKING: Acquires the loader lock.
4639  *
4640  * FIXME Use proper MonoError machinery here.
4641  */
4642 int
4643 mono_method_get_vtable_slot (MonoMethod *method)
4644 {
4645         if (method->slot == -1) {
4646                 mono_class_setup_vtable (method->klass);
4647                 if (mono_class_has_failure (method->klass))
4648                         return -1;
4649                 if (method->slot == -1) {
4650                         MonoClass *gklass;
4651                         int i, mcount;
4652
4653                         if (!mono_class_is_ginst (method->klass)) {
4654                                 g_assert (method->is_inflated);
4655                                 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4656                         }
4657
4658                         /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4659                         g_assert (mono_class_is_ginst (method->klass));
4660                         gklass = mono_class_get_generic_class (method->klass)->container_class;
4661                         mono_class_setup_methods (method->klass);
4662                         g_assert (method->klass->methods);
4663                         mcount = mono_class_get_method_count (method->klass);
4664                         for (i = 0; i < mcount; ++i) {
4665                                 if (method->klass->methods [i] == method)
4666                                         break;
4667                         }
4668                         g_assert (i < mcount);
4669                         g_assert (gklass->methods);
4670                         method->slot = gklass->methods [i]->slot;
4671                 }
4672                 g_assert (method->slot != -1);
4673         }
4674         return method->slot;
4675 }
4676
4677 /**
4678  * mono_method_get_vtable_index:
4679  * \param method a method
4680  *
4681  * Returns the index into the runtime vtable to access the method or,
4682  * in the case of a virtual generic method, the virtual generic method
4683  * thunk. Returns -1 on failure.
4684  *
4685  * FIXME Use proper MonoError machinery here.
4686  */
4687 int
4688 mono_method_get_vtable_index (MonoMethod *method)
4689 {
4690         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4691                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4692                 if (imethod->declaring->is_generic)
4693                         return mono_method_get_vtable_slot (imethod->declaring);
4694         }
4695         return mono_method_get_vtable_slot (method);
4696 }
4697
4698 static MonoMethod *default_ghc = NULL;
4699 static MonoMethod *default_finalize = NULL;
4700 static int finalize_slot = -1;
4701 static int ghc_slot = -1;
4702
4703 static void
4704 initialize_object_slots (MonoClass *klass)
4705 {
4706         int i;
4707         if (default_ghc)
4708                 return;
4709         if (klass == mono_defaults.object_class) {
4710                 mono_class_setup_vtable (klass);
4711                 for (i = 0; i < klass->vtable_size; ++i) {
4712                         MonoMethod *cm = klass->vtable [i];
4713        
4714                         if (!strcmp (cm->name, "GetHashCode"))
4715                                 ghc_slot = i;
4716                         else if (!strcmp (cm->name, "Finalize"))
4717                                 finalize_slot = i;
4718                 }
4719
4720                 g_assert (ghc_slot > 0);
4721                 default_ghc = klass->vtable [ghc_slot];
4722
4723                 g_assert (finalize_slot > 0);
4724                 default_finalize = klass->vtable [finalize_slot];
4725         }
4726 }
4727
4728 typedef struct {
4729         MonoMethod *array_method;
4730         char *name;
4731 } GenericArrayMethodInfo;
4732
4733 static int generic_array_method_num = 0;
4734 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4735
4736 static int
4737 generic_array_methods (MonoClass *klass)
4738 {
4739         int i, count_generic = 0, mcount;
4740         GList *list = NULL, *tmp;
4741         if (generic_array_method_num)
4742                 return generic_array_method_num;
4743         mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4744         g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4745         mcount = mono_class_get_method_count (klass->parent);
4746         for (i = 0; i < mcount; i++) {
4747                 MonoMethod *m = klass->parent->methods [i];
4748                 if (!strncmp (m->name, "InternalArray__", 15)) {
4749                         count_generic++;
4750                         list = g_list_prepend (list, m);
4751                 }
4752         }
4753         list = g_list_reverse (list);
4754         generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4755         i = 0;
4756         for (tmp = list; tmp; tmp = tmp->next) {
4757                 const char *mname, *iname;
4758                 gchar *name;
4759                 MonoMethod *m = (MonoMethod *)tmp->data;
4760                 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4761                 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4762
4763                 generic_array_method_info [i].array_method = m;
4764                 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4765                         iname = "System.Collections.Generic.ICollection`1.";
4766                         mname = m->name + 27;
4767                 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4768                         iname = "System.Collections.Generic.IEnumerable`1.";
4769                         mname = m->name + 27;
4770                 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4771                         iname = "System.Collections.Generic.IReadOnlyList`1.";
4772                         mname = m->name + strlen (ireadonlylist_prefix);
4773                 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4774                         iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4775                         mname = m->name + strlen (ireadonlycollection_prefix);
4776                 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4777                         iname = "System.Collections.Generic.IList`1.";
4778                         mname = m->name + 15;
4779                 } else {
4780                         g_assert_not_reached ();
4781                 }
4782
4783                 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4784                 strcpy (name, iname);
4785                 strcpy (name + strlen (iname), mname);
4786                 generic_array_method_info [i].name = name;
4787                 i++;
4788         }
4789         /*g_print ("array generic methods: %d\n", count_generic);*/
4790
4791         generic_array_method_num = count_generic;
4792         g_list_free (list);
4793         return generic_array_method_num;
4794 }
4795
4796 static void
4797 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4798 {
4799         MonoGenericContext tmp_context;
4800         int i;
4801
4802         tmp_context.class_inst = NULL;
4803         tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4804         //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4805
4806         for (i = 0; i < generic_array_method_num; i++) {
4807                 MonoError error;
4808                 MonoMethod *m = generic_array_method_info [i].array_method;
4809                 MonoMethod *inflated, *helper;
4810
4811                 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4812                 mono_error_assert_ok (&error);
4813                 helper = g_hash_table_lookup (cache, inflated);
4814                 if (!helper) {
4815                         helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4816                         g_hash_table_insert (cache, inflated, helper);
4817                 }
4818                 methods [pos ++] = helper;
4819         }
4820 }
4821
4822 static char*
4823 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4824 {
4825         int null_length = strlen ("(null)");
4826         int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4827         char *s = (char *)mono_image_alloc (image, len);
4828         int result;
4829
4830         result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4831         g_assert (result == len - 1);
4832
4833         return s;
4834 }
4835
4836 /**
4837  * mono_class_init:
4838  * \param klass the class to initialize
4839  *
4840  * Compute the \c instance_size, \c class_size and other infos that cannot be 
4841  * computed at \c mono_class_get time. Also compute vtable_size if possible. 
4842  * Initializes the following fields in \p klass:
4843  * - all the fields initialized by \c mono_class_init_sizes
4844  * - has_cctor
4845  * - ghcimpl
4846  * - inited
4847  *
4848  * LOCKING: Acquires the loader lock.
4849  *
4850  * \returns TRUE on success or FALSE if there was a problem in loading
4851  * the type (incorrect assemblies, missing assemblies, methods, etc).
4852  */
4853 gboolean
4854 mono_class_init (MonoClass *klass)
4855 {
4856         int i, vtable_size = 0, array_method_count = 0;
4857         MonoCachedClassInfo cached_info;
4858         gboolean has_cached_info;
4859         gboolean locked = FALSE;
4860         gboolean ghcimpl = FALSE;
4861         gboolean has_cctor = FALSE;
4862         int first_iface_slot = 0;
4863         
4864         g_assert (klass);
4865
4866         /* Double-checking locking pattern */
4867         if (klass->inited || mono_class_has_failure (klass))
4868                 return !mono_class_has_failure (klass);
4869
4870         /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4871
4872         /*
4873          * This function can recursively call itself.
4874          */
4875         GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4876         if (g_slist_find (init_list, klass)) {
4877                 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4878                 goto leave;
4879         }
4880         init_list = g_slist_prepend (init_list, klass);
4881         mono_native_tls_set_value (init_pending_tls_id, init_list);
4882
4883         /*
4884          * We want to avoid doing complicated work inside locks, so we compute all the required
4885          * information and write it to @klass inside a lock.
4886          */
4887
4888         if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4889                 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4890                 goto leave;
4891         }
4892
4893         if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4894                 MonoClass *element_class = klass->element_class;
4895                 if (!element_class->inited) 
4896                         mono_class_init (element_class);
4897                 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4898                         goto leave;
4899         }
4900
4901         mono_stats.initialized_class_count++;
4902
4903         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4904                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4905
4906                 mono_class_init (gklass);
4907                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4908                         goto leave;
4909
4910                 mono_class_setup_interface_id (klass);
4911         }
4912
4913         if (klass->parent && !klass->parent->inited)
4914                 mono_class_init (klass->parent);
4915
4916         has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4917
4918         /* Compute instance size etc. */
4919         init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4920         if (mono_class_has_failure (klass))
4921                 goto leave;
4922
4923         mono_class_setup_supertypes (klass);
4924
4925         if (!default_ghc)
4926                 initialize_object_slots (klass);
4927
4928         /* 
4929          * Initialize the rest of the data without creating a generic vtable if possible.
4930          * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4931          * also avoid computing a generic vtable.
4932          */
4933         if (has_cached_info) {
4934                 /* AOT case */
4935                 vtable_size = cached_info.vtable_size;
4936                 ghcimpl = cached_info.ghcimpl;
4937                 has_cctor = cached_info.has_cctor;
4938         } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4939                 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4940                  * The first slot if for array with.
4941                  */
4942                 static int szarray_vtable_size[2] = { 0 };
4943
4944                 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4945
4946                 /* SZARRAY case */
4947                 if (!szarray_vtable_size [slot]) {
4948                         mono_class_setup_vtable (klass);
4949                         szarray_vtable_size [slot] = klass->vtable_size;
4950                         vtable_size = klass->vtable_size;
4951                 } else {
4952                         vtable_size = szarray_vtable_size[slot];
4953                 }
4954         } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4955                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4956
4957                 /* Generic instance case */
4958                 ghcimpl = gklass->ghcimpl;
4959                 has_cctor = gklass->has_cctor;
4960
4961                 mono_class_setup_vtable (gklass);
4962                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4963                         goto leave;
4964
4965                 vtable_size = gklass->vtable_size;
4966         } else {
4967                 /* General case */
4968
4969                 /* ghcimpl is not currently used
4970                 klass->ghcimpl = 1;
4971                 if (klass->parent) {
4972                         MonoMethod *cmethod = klass->vtable [ghc_slot];
4973                         if (cmethod->is_inflated)
4974                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4975                         if (cmethod == default_ghc) {
4976                                 klass->ghcimpl = 0;
4977                         }
4978                 }
4979                 */
4980
4981                 /* C# doesn't allow interfaces to have cctors */
4982                 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4983                         MonoMethod *cmethod = NULL;
4984
4985                         if (mono_class_is_ginst (klass)) {
4986                                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4987
4988                                 /* Generic instance case */
4989                                 ghcimpl = gklass->ghcimpl;
4990                                 has_cctor = gklass->has_cctor;
4991                         } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4992                                 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4993                                 /* The find_method function ignores the 'flags' argument */
4994                                 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4995                                         has_cctor = 1;
4996                         } else {
4997                                 mono_class_setup_methods (klass);
4998                                 if (mono_class_has_failure (klass))
4999                                         goto leave;
5000
5001                                 int mcount = mono_class_get_method_count (klass);
5002                                 for (i = 0; i < mcount; ++i) {
5003                                         MonoMethod *method = klass->methods [i];
5004                                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
5005                                                 (strcmp (".cctor", method->name) == 0)) {
5006                                                 has_cctor = 1;
5007                                                 break;
5008                                         }
5009                                 }
5010                         }
5011                 }
5012         }
5013
5014         if (klass->rank) {
5015                 array_method_count = 3 + (klass->rank > 1? 2: 1);
5016
5017                 if (klass->interface_count) {
5018                         int count_generic = generic_array_methods (klass);
5019                         array_method_count += klass->interface_count * count_generic;
5020                 }
5021         }
5022
5023         if (klass->parent) {
5024                 if (!klass->parent->vtable_size)
5025                         mono_class_setup_vtable (klass->parent);
5026                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5027                         goto leave;
5028                 g_assert (klass->parent->vtable_size);
5029                 first_iface_slot = klass->parent->vtable_size;
5030                 if (mono_class_need_stelemref_method (klass))
5031                         ++first_iface_slot;
5032         }
5033
5034         /*
5035          * Do the actual changes to @klass inside the loader lock
5036          */
5037         mono_loader_lock ();
5038         locked = TRUE;
5039
5040         if (klass->inited || mono_class_has_failure (klass)) {
5041                 mono_loader_unlock ();
5042                 /* Somebody might have gotten in before us */
5043                 return !mono_class_has_failure (klass);
5044         }
5045
5046         mono_stats.initialized_class_count++;
5047
5048         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5049                 mono_stats.generic_class_count++;
5050
5051         if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5052                 klass->nested_classes_inited = TRUE;
5053         klass->ghcimpl = ghcimpl;
5054         klass->has_cctor = has_cctor;
5055         if (vtable_size)
5056                 klass->vtable_size = vtable_size;
5057         if (has_cached_info) {
5058                 klass->has_finalize = cached_info.has_finalize;
5059                 klass->has_finalize_inited = TRUE;
5060         }
5061         if (klass->rank)
5062                 mono_class_set_method_count (klass, array_method_count);
5063
5064         mono_loader_unlock ();
5065         locked = FALSE;
5066
5067         setup_interface_offsets (klass, first_iface_slot, TRUE);
5068
5069         if (mono_security_core_clr_enabled ())
5070                 mono_security_core_clr_check_inheritance (klass);
5071
5072         if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5073                 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5074
5075         goto leave;
5076
5077  leave:
5078         init_list = g_slist_remove (init_list, klass);
5079         mono_native_tls_set_value (init_pending_tls_id, init_list);
5080
5081         if (locked)
5082                 mono_loader_unlock ();
5083
5084         /* Leave this for last */
5085         mono_loader_lock ();
5086         klass->inited = 1;
5087         mono_loader_unlock ();
5088
5089         return !mono_class_has_failure (klass);
5090 }
5091
5092 /*
5093  * mono_class_has_finalizer:
5094  *
5095  *   Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5096  * process.
5097  */
5098 gboolean
5099 mono_class_has_finalizer (MonoClass *klass)
5100 {
5101         gboolean has_finalize = FALSE;
5102
5103         if (klass->has_finalize_inited)
5104                 return klass->has_finalize;
5105
5106         /* Interfaces and valuetypes are not supposed to have finalizers */
5107         if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5108                 MonoMethod *cmethod = NULL;
5109
5110                 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5111                 } else if (mono_class_is_ginst (klass)) {
5112                         MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5113
5114                         has_finalize = mono_class_has_finalizer (gklass);
5115                 } else if (klass->parent && klass->parent->has_finalize) {
5116                         has_finalize = TRUE;
5117                 } else {
5118                         if (klass->parent) {
5119                                 /*
5120                                  * Can't search in metadata for a method named Finalize, because that
5121                                  * ignores overrides.
5122                                  */
5123                                 mono_class_setup_vtable (klass);
5124                                 if (mono_class_has_failure (klass))
5125                                         cmethod = NULL;
5126                                 else
5127                                         cmethod = klass->vtable [finalize_slot];
5128                         }
5129
5130                         if (cmethod) {
5131                                 g_assert (klass->vtable_size > finalize_slot);
5132
5133                                 if (klass->parent) {
5134                                         if (cmethod->is_inflated)
5135                                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5136                                         if (cmethod != default_finalize)
5137                                                 has_finalize = TRUE;
5138                                 }
5139                         }
5140                 }
5141         }
5142
5143         mono_loader_lock ();
5144         if (!klass->has_finalize_inited) {
5145                 klass->has_finalize = has_finalize ? 1 : 0;
5146
5147                 mono_memory_barrier ();
5148                 klass->has_finalize_inited = TRUE;
5149         }
5150         mono_loader_unlock ();
5151
5152         return klass->has_finalize;
5153 }
5154
5155 gboolean
5156 mono_is_corlib_image (MonoImage *image)
5157 {
5158         return image == mono_defaults.corlib;
5159 }
5160
5161 /*
5162  * LOCKING: this assumes the loader lock is held
5163  */
5164 void
5165 mono_class_setup_mono_type (MonoClass *klass)
5166 {
5167         const char *name = klass->name;
5168         const char *nspace = klass->name_space;
5169         gboolean is_corlib = mono_is_corlib_image (klass->image);
5170
5171         klass->this_arg.byref = 1;
5172         klass->this_arg.data.klass = klass;
5173         klass->this_arg.type = MONO_TYPE_CLASS;
5174         klass->byval_arg.data.klass = klass;
5175         klass->byval_arg.type = MONO_TYPE_CLASS;
5176
5177         if (is_corlib && !strcmp (nspace, "System")) {
5178                 if (!strcmp (name, "ValueType")) {
5179                         /*
5180                          * do not set the valuetype bit for System.ValueType.
5181                          * klass->valuetype = 1;
5182                          */
5183                         klass->blittable = TRUE;
5184                 } else if (!strcmp (name, "Enum")) {
5185                         /*
5186                          * do not set the valuetype bit for System.Enum.
5187                          * klass->valuetype = 1;
5188                          */
5189                         klass->valuetype = 0;
5190                         klass->enumtype = 0;
5191                 } else if (!strcmp (name, "Object")) {
5192                         klass->byval_arg.type = MONO_TYPE_OBJECT;
5193                         klass->this_arg.type = MONO_TYPE_OBJECT;
5194                 } else if (!strcmp (name, "String")) {
5195                         klass->byval_arg.type = MONO_TYPE_STRING;
5196                         klass->this_arg.type = MONO_TYPE_STRING;
5197                 } else if (!strcmp (name, "TypedReference")) {
5198                         klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5199                         klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5200                 }
5201         }
5202
5203         if (klass->valuetype) {
5204                 int t = MONO_TYPE_VALUETYPE;
5205
5206                 if (is_corlib && !strcmp (nspace, "System")) {
5207                         switch (*name) {
5208                         case 'B':
5209                                 if (!strcmp (name, "Boolean")) {
5210                                         t = MONO_TYPE_BOOLEAN;
5211                                 } else if (!strcmp(name, "Byte")) {
5212                                         t = MONO_TYPE_U1;
5213                                         klass->blittable = TRUE;                                                
5214                                 }
5215                                 break;
5216                         case 'C':
5217                                 if (!strcmp (name, "Char")) {
5218                                         t = MONO_TYPE_CHAR;
5219                                 }
5220                                 break;
5221                         case 'D':
5222                                 if (!strcmp (name, "Double")) {
5223                                         t = MONO_TYPE_R8;
5224                                         klass->blittable = TRUE;                                                
5225                                 }
5226                                 break;
5227                         case 'I':
5228                                 if (!strcmp (name, "Int32")) {
5229                                         t = MONO_TYPE_I4;
5230                                         klass->blittable = TRUE;
5231                                 } else if (!strcmp(name, "Int16")) {
5232                                         t = MONO_TYPE_I2;
5233                                         klass->blittable = TRUE;
5234                                 } else if (!strcmp(name, "Int64")) {
5235                                         t = MONO_TYPE_I8;
5236                                         klass->blittable = TRUE;
5237                                 } else if (!strcmp(name, "IntPtr")) {
5238                                         t = MONO_TYPE_I;
5239                                         klass->blittable = TRUE;
5240                                 }
5241                                 break;
5242                         case 'S':
5243                                 if (!strcmp (name, "Single")) {
5244                                         t = MONO_TYPE_R4;
5245                                         klass->blittable = TRUE;                                                
5246                                 } else if (!strcmp(name, "SByte")) {
5247                                         t = MONO_TYPE_I1;
5248                                         klass->blittable = TRUE;
5249                                 }
5250                                 break;
5251                         case 'U':
5252                                 if (!strcmp (name, "UInt32")) {
5253                                         t = MONO_TYPE_U4;
5254                                         klass->blittable = TRUE;
5255                                 } else if (!strcmp(name, "UInt16")) {
5256                                         t = MONO_TYPE_U2;
5257                                         klass->blittable = TRUE;
5258                                 } else if (!strcmp(name, "UInt64")) {
5259                                         t = MONO_TYPE_U8;
5260                                         klass->blittable = TRUE;
5261                                 } else if (!strcmp(name, "UIntPtr")) {
5262                                         t = MONO_TYPE_U;
5263                                         klass->blittable = TRUE;
5264                                 }
5265                                 break;
5266                         case 'T':
5267                                 if (!strcmp (name, "TypedReference")) {
5268                                         t = MONO_TYPE_TYPEDBYREF;
5269                                         klass->blittable = TRUE;
5270                                 }
5271                                 break;
5272                         case 'V':
5273                                 if (!strcmp (name, "Void")) {
5274                                         t = MONO_TYPE_VOID;
5275                                 }
5276                                 break;
5277                         default:
5278                                 break;
5279                         }
5280                 }
5281                 klass->byval_arg.type = (MonoTypeEnum)t;
5282                 klass->this_arg.type = (MonoTypeEnum)t;
5283         }
5284
5285         if (MONO_CLASS_IS_INTERFACE (klass)) {
5286                 klass->interface_id = mono_get_unique_iid (klass);
5287
5288                 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5289                         //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5290                     /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5291                     * MS returns diferrent types based on which instance is called. For example:
5292                     *   object obj = new byte[10][];
5293                     *   Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5294                     *   Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5295                     *   a != b ==> true
5296                         */
5297                         if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5298                                 klass->is_array_special_interface = 1;
5299                 }
5300         }
5301 }
5302
5303 #ifndef DISABLE_COM
5304 /*
5305  * COM initialization is delayed until needed.
5306  * However when a [ComImport] attribute is present on a type it will trigger
5307  * the initialization. This is not a problem unless the BCL being executed 
5308  * lacks the types that COM depends on (e.g. Variant on Silverlight).
5309  */
5310 static void
5311 init_com_from_comimport (MonoClass *klass)
5312 {
5313         /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5314         if (mono_security_core_clr_enabled ()) {
5315                 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5316                 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5317                         /* but it can not be made available for application (i.e. user code) since all COM calls
5318                          * are considered native calls. In this case we fail with a TypeLoadException (just like
5319                          * Silverlight 2 does */
5320                         mono_class_set_type_load_failure (klass, "");
5321                         return;
5322                 }
5323         }
5324
5325         /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5326 }
5327 #endif /*DISABLE_COM*/
5328
5329 /*
5330  * LOCKING: this assumes the loader lock is held
5331  */
5332 void
5333 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5334 {
5335         gboolean system_namespace;
5336         gboolean is_corlib = mono_is_corlib_image (klass->image);
5337
5338         system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5339
5340         /* if root of the hierarchy */
5341         if (system_namespace && !strcmp (klass->name, "Object")) {
5342                 klass->parent = NULL;
5343                 klass->instance_size = sizeof (MonoObject);
5344                 return;
5345         }
5346         if (!strcmp (klass->name, "<Module>")) {
5347                 klass->parent = NULL;
5348                 klass->instance_size = 0;
5349                 return;
5350         }
5351
5352         if (!MONO_CLASS_IS_INTERFACE (klass)) {
5353                 /* Imported COM Objects always derive from __ComObject. */
5354 #ifndef DISABLE_COM
5355                 if (MONO_CLASS_IS_IMPORT (klass)) {
5356                         init_com_from_comimport (klass);
5357                         if (parent == mono_defaults.object_class)
5358                                 parent = mono_class_get_com_object_class ();
5359                 }
5360 #endif
5361                 if (!parent) {
5362                         /* set the parent to something useful and safe, but mark the type as broken */
5363                         parent = mono_defaults.object_class;
5364                         mono_class_set_type_load_failure (klass, "");
5365                         g_assert (parent);
5366                 }
5367
5368                 klass->parent = parent;
5369
5370                 if (mono_class_is_ginst (parent) && !parent->name) {
5371                         /*
5372                          * If the parent is a generic instance, we may get
5373                          * called before it is fully initialized, especially
5374                          * before it has its name.
5375                          */
5376                         return;
5377                 }
5378
5379 #ifndef DISABLE_REMOTING
5380                 klass->marshalbyref = parent->marshalbyref;
5381                 klass->contextbound  = parent->contextbound;
5382 #endif
5383
5384                 klass->delegate  = parent->delegate;
5385
5386                 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5387                         mono_class_set_is_com_object (klass);
5388                 
5389                 if (system_namespace) {
5390 #ifndef DISABLE_REMOTING
5391                         if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5392                                 klass->marshalbyref = 1;
5393
5394                         if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject")) 
5395                                 klass->contextbound  = 1;
5396 #endif
5397                         if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) 
5398                                 klass->delegate  = 1;
5399                 }
5400
5401                 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && 
5402                                                 (strcmp (klass->parent->name_space, "System") == 0)))
5403                         klass->valuetype = 1;
5404                 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5405                         klass->valuetype = klass->enumtype = 1;
5406                 }
5407                 /*klass->enumtype = klass->parent->enumtype; */
5408         } else {
5409                 /* initialize com types if COM interfaces are present */
5410 #ifndef DISABLE_COM
5411                 if (MONO_CLASS_IS_IMPORT (klass))
5412                         init_com_from_comimport (klass);
5413 #endif
5414                 klass->parent = NULL;
5415         }
5416
5417 }
5418
5419 /*
5420  * mono_class_setup_supertypes:
5421  * @class: a class
5422  *
5423  * Build the data structure needed to make fast type checks work.
5424  * This currently sets two fields in @class:
5425  *  - idepth: distance between @class and System.Object in the type
5426  *    hierarchy + 1
5427  *  - supertypes: array of classes: each element has a class in the hierarchy
5428  *    starting from @class up to System.Object
5429  * 
5430  * LOCKING: Acquires the loader lock.
5431  */
5432 void
5433 mono_class_setup_supertypes (MonoClass *klass)
5434 {
5435         int ms, idepth;
5436         MonoClass **supertypes;
5437
5438         mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5439         if (supertypes)
5440                 return;
5441
5442         if (klass->parent && !klass->parent->supertypes)
5443                 mono_class_setup_supertypes (klass->parent);
5444         if (klass->parent)
5445                 idepth = klass->parent->idepth + 1;
5446         else
5447                 idepth = 1;
5448
5449         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5450         supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5451
5452         if (klass->parent) {
5453                 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5454
5455                 int supertype_idx;
5456                 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5457                         CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5458         } else {
5459                 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5460         }
5461
5462         mono_memory_barrier ();
5463
5464         mono_loader_lock ();
5465         klass->idepth = idepth;
5466         /* Needed so idepth is visible before supertypes is set */
5467         mono_memory_barrier ();
5468         klass->supertypes = supertypes;
5469         mono_loader_unlock ();
5470 }
5471
5472 static gboolean
5473 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5474 {
5475         return mono_class_get_generic_class (gclass)->container_class == user_data;
5476 }
5477
5478 static gboolean
5479 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5480 {
5481         MonoClass *gtd = (MonoClass*)user_data;
5482         /* Only try to fix generic instances of @gtd */
5483         if (mono_class_get_generic_class (gclass)->container_class != gtd)
5484                 return FALSE;
5485
5486         /* Check if the generic instance has no parent. */
5487         if (gtd->parent && !gclass->parent)
5488                 mono_generic_class_setup_parent (gclass, gtd);
5489
5490         return TRUE;
5491 }
5492
5493 static void
5494 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5495 {
5496         mono_class_set_type_load_failure (klass, "%s", msg);
5497         mono_error_set_type_load_class (error, klass, "%s", msg);
5498 }
5499
5500 /**
5501  * mono_class_create_from_typedef:
5502  * \param image: image where the token is valid
5503  * \param type_token:  typedef token
5504  * \param error:  used to return any error found while creating the type
5505  *
5506  * Create the MonoClass* representing the specified type token.
5507  * \p type_token must be a TypeDef token.
5508  *
5509  * FIXME: don't return NULL on failure, just the the caller figure it out.
5510  */
5511 static MonoClass *
5512 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5513 {
5514         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5515         MonoClass *klass, *parent = NULL;
5516         guint32 cols [MONO_TYPEDEF_SIZE];
5517         guint32 cols_next [MONO_TYPEDEF_SIZE];
5518         guint tidx = mono_metadata_token_index (type_token);
5519         MonoGenericContext *context = NULL;
5520         const char *name, *nspace;
5521         guint icount = 0; 
5522         MonoClass **interfaces;
5523         guint32 field_last, method_last;
5524         guint32 nesting_tokeen;
5525
5526         error_init (error);
5527
5528         if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5529                 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5530                 return NULL;
5531         }
5532
5533         mono_loader_lock ();
5534
5535         if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5536                 mono_loader_unlock ();
5537                 return klass;
5538         }
5539
5540         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5541         
5542         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5543         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5544
5545         if (mono_metadata_has_generic_params (image, type_token)) {
5546                 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5547                 klass->class_kind = MONO_CLASS_GTD;
5548                 classes_size += sizeof (MonoClassGtd);
5549                 ++class_gtd_count;
5550         } else {
5551                 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5552                 klass->class_kind = MONO_CLASS_DEF;
5553                 classes_size += sizeof (MonoClassDef);
5554                 ++class_def_count;
5555         }
5556
5557         klass->name = name;
5558         klass->name_space = nspace;
5559
5560         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5561
5562         klass->image = image;
5563         klass->type_token = type_token;
5564         mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5565
5566         mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5567
5568         /*
5569          * Check whether we're a generic type definition.
5570          */
5571         if (mono_class_is_gtd (klass)) {
5572                 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5573                 generic_container->owner.klass = klass;
5574                 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5575                 context = &generic_container->context;
5576                 mono_class_set_generic_container (klass, generic_container);
5577                 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5578                 canonical_inst->type = MONO_TYPE_GENERICINST;
5579                 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5580                 enable_gclass_recording ();
5581         }
5582
5583         if (cols [MONO_TYPEDEF_EXTENDS]) {
5584                 MonoClass *tmp;
5585                 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5586
5587                 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5588                         /*WARNING: this must satisfy mono_metadata_type_hash*/
5589                         klass->this_arg.byref = 1;
5590                         klass->this_arg.data.klass = klass;
5591                         klass->this_arg.type = MONO_TYPE_CLASS;
5592                         klass->byval_arg.data.klass = klass;
5593                         klass->byval_arg.type = MONO_TYPE_CLASS;
5594                 }
5595                 parent = mono_class_get_checked (image, parent_token, error);
5596                 if (parent && context) /* Always inflate */
5597                         parent = mono_class_inflate_generic_class_checked (parent, context, error);
5598
5599                 if (parent == NULL) {
5600                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5601                         goto parent_failure;
5602                 }
5603
5604                 for (tmp = parent; tmp; tmp = tmp->parent) {
5605                         if (tmp == klass) {
5606                                 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5607                                 goto parent_failure;
5608                         }
5609                         if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5610                                 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5611                                 goto parent_failure;
5612                         }
5613                 }
5614         }
5615
5616         mono_class_setup_parent (klass, parent);
5617
5618         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5619         mono_class_setup_mono_type (klass);
5620
5621         if (mono_class_is_gtd (klass))
5622                 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5623
5624         /* 
5625          * This might access klass->byval_arg for recursion generated by generic constraints,
5626          * so it has to come after setup_mono_type ().
5627          */
5628         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5629                 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5630                 if (!mono_error_ok (error)) {
5631                         /*FIXME implement a mono_class_set_failure_from_mono_error */
5632                         mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
5633                         mono_loader_unlock ();
5634                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5635                         return NULL;
5636                 }
5637         }
5638
5639         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5640                 klass->unicode = 1;
5641
5642 #ifdef HOST_WIN32
5643         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5644                 klass->unicode = 1;
5645 #endif
5646
5647         klass->cast_class = klass->element_class = klass;
5648         if (mono_is_corlib_image (klass->image)) {
5649                 switch (klass->byval_arg.type) {
5650                         case MONO_TYPE_I1:
5651                                 if (mono_defaults.byte_class)
5652                                         klass->cast_class = mono_defaults.byte_class;
5653                                 break;
5654                         case MONO_TYPE_U1:
5655                                 if (mono_defaults.sbyte_class)
5656                                         mono_defaults.sbyte_class = klass;
5657                                 break;
5658                         case MONO_TYPE_I2:
5659                                 if (mono_defaults.uint16_class)
5660                                         mono_defaults.uint16_class = klass;
5661                                 break;
5662                         case MONO_TYPE_U2:
5663                                 if (mono_defaults.int16_class)
5664                                         klass->cast_class = mono_defaults.int16_class;
5665                                 break;
5666                         case MONO_TYPE_I4:
5667                                 if (mono_defaults.uint32_class)
5668                                         mono_defaults.uint32_class = klass;
5669                                 break;
5670                         case MONO_TYPE_U4:
5671                                 if (mono_defaults.int32_class)
5672                                         klass->cast_class = mono_defaults.int32_class;
5673                                 break;
5674                         case MONO_TYPE_I8:
5675                                 if (mono_defaults.uint64_class)
5676                                         mono_defaults.uint64_class = klass;
5677                                 break;
5678                         case MONO_TYPE_U8:
5679                                 if (mono_defaults.int64_class)
5680                                         klass->cast_class = mono_defaults.int64_class;
5681                                 break;
5682                 }
5683         }
5684
5685         if (!klass->enumtype) {
5686                 if (!mono_metadata_interfaces_from_typedef_full (
5687                             image, type_token, &interfaces, &icount, FALSE, context, error)){
5688
5689                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5690                         mono_loader_unlock ();
5691                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5692                         return NULL;
5693                 }
5694
5695                 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5696                 g_assert(icount <= 65535);
5697
5698                 klass->interfaces = interfaces;
5699                 klass->interface_count = icount;
5700                 klass->interfaces_inited = 1;
5701         }
5702
5703         /*g_print ("Load class %s\n", name);*/
5704
5705         /*
5706          * Compute the field and method lists
5707          */
5708         int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5709         mono_class_set_first_field_idx (klass, first_field_idx);
5710         int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5711         mono_class_set_first_method_idx (klass, first_method_idx);
5712
5713         if (tt->rows > tidx){           
5714                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5715                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5716                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5717         } else {
5718                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
5719                 method_last = image->tables [MONO_TABLE_METHOD].rows;
5720         }
5721
5722         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
5723             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5724                 mono_class_set_field_count (klass, field_last - first_field_idx);
5725         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5726                 mono_class_set_method_count (klass, method_last - first_method_idx);
5727
5728         /* reserve space to store vector pointer in arrays */
5729         if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5730                 klass->instance_size += 2 * sizeof (gpointer);
5731                 g_assert (mono_class_get_field_count (klass) == 0);
5732         }
5733
5734         if (klass->enumtype) {
5735                 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5736                 if (!enum_basetype) {
5737                         /*set it to a default value as the whole runtime can't handle this to be null*/
5738                         klass->cast_class = klass->element_class = mono_defaults.int32_class;
5739                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5740                         mono_loader_unlock ();
5741                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5742                         return NULL;
5743                 }
5744                 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5745         }
5746
5747         /*
5748          * If we're a generic type definition, load the constraints.
5749          * We must do this after the class has been constructed to make certain recursive scenarios
5750          * work.
5751          */
5752         if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5753                 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5754                 mono_loader_unlock ();
5755                 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5756                 return NULL;
5757         }
5758
5759         if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5760                 if (!strncmp (name, "Vector", 6))
5761                         klass->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
5762         } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5763                 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5764                         klass->simd_type = 1;
5765         }
5766
5767         mono_loader_unlock ();
5768
5769         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5770
5771         return klass;
5772
5773 parent_failure:
5774         if (mono_class_is_gtd (klass))
5775                 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5776
5777         mono_class_setup_mono_type (klass);
5778         mono_loader_unlock ();
5779         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5780         return NULL;
5781 }
5782
5783 /** Is klass a Nullable<T> ginst? */
5784 gboolean
5785 mono_class_is_nullable (MonoClass *klass)
5786 {
5787         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5788         return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5789 }
5790
5791
5792 /** if klass is T? return T */
5793 MonoClass*
5794 mono_class_get_nullable_param (MonoClass *klass)
5795 {
5796        g_assert (mono_class_is_nullable (klass));
5797        return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5798 }
5799
5800 static void
5801 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5802 {
5803         if (gtd->parent) {
5804                 MonoError error;
5805                 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5806
5807                 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5808                 if (!mono_error_ok (&error)) {
5809                         /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5810                         klass->parent = mono_defaults.object_class;
5811                         mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5812                         mono_error_cleanup (&error);
5813                 }
5814         }
5815         mono_loader_lock ();
5816         if (klass->parent)
5817                 mono_class_setup_parent (klass, klass->parent);
5818
5819         if (klass->enumtype) {
5820                 klass->cast_class = gtd->cast_class;
5821                 klass->element_class = gtd->element_class;
5822         }
5823         mono_loader_unlock ();
5824 }
5825
5826 gboolean
5827 mono_type_is_primitive (MonoType *type)
5828 {
5829         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5830                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5831 }
5832
5833 /*
5834  * Create the `MonoClass' for an instantiation of a generic type.
5835  * We only do this if we actually need it.
5836  */
5837 MonoClass*
5838 mono_generic_class_get_class (MonoGenericClass *gclass)
5839 {
5840         MonoClass *klass, *gklass;
5841
5842         if (gclass->cached_class)
5843                 return gclass->cached_class;
5844
5845         klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5846
5847         gklass = gclass->container_class;
5848
5849         if (gklass->nested_in) {
5850                 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5851                 klass->nested_in = gklass->nested_in;
5852         }
5853
5854         klass->name = gklass->name;
5855         klass->name_space = gklass->name_space;
5856         
5857         klass->image = gklass->image;
5858         klass->type_token = gklass->type_token;
5859
5860         klass->class_kind = MONO_CLASS_GINST;
5861         //FIXME add setter
5862         ((MonoClassGenericInst*)klass)->generic_class = gclass;
5863
5864         klass->byval_arg.type = MONO_TYPE_GENERICINST;
5865         klass->this_arg.type = klass->byval_arg.type;
5866         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5867         klass->this_arg.byref = TRUE;
5868         klass->enumtype = gklass->enumtype;
5869         klass->valuetype = gklass->valuetype;
5870
5871
5872         if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5873                 g_assert (gclass->context.class_inst);
5874                 g_assert (gclass->context.class_inst->type_argc > 0);
5875                 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5876                         klass->simd_type = 1;
5877         }
5878         klass->is_array_special_interface = gklass->is_array_special_interface;
5879
5880         klass->cast_class = klass->element_class = klass;
5881
5882         if (gclass->is_dynamic) {
5883                 /*
5884                  * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
5885                  * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5886                  * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5887                 */
5888                 if (!gklass->wastypebuilder)
5889                         klass->inited = 1;
5890
5891                 if (klass->enumtype) {
5892                         /*
5893                          * For enums, gklass->fields might not been set, but instance_size etc. is 
5894                          * already set in mono_reflection_create_internal_class (). For non-enums,
5895                          * these will be computed normally in mono_class_layout_fields ().
5896                          */
5897                         klass->instance_size = gklass->instance_size;
5898                         klass->sizes.class_size = gklass->sizes.class_size;
5899                         klass->size_inited = 1;
5900                 }
5901         }
5902
5903         mono_loader_lock ();
5904
5905         if (gclass->cached_class) {
5906                 mono_loader_unlock ();
5907                 return gclass->cached_class;
5908         }
5909
5910         if (record_gclass_instantiation > 0)
5911                 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5912
5913         if (mono_class_is_nullable (klass))
5914                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5915
5916         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5917
5918         mono_generic_class_setup_parent (klass, gklass);
5919
5920         if (gclass->is_dynamic)
5921                 mono_class_setup_supertypes (klass);
5922
5923         mono_memory_barrier ();
5924         gclass->cached_class = klass;
5925
5926         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5927
5928         ++class_ginst_count;
5929         inflated_classes_size += sizeof (MonoClassGenericInst);
5930         
5931         mono_loader_unlock ();
5932
5933         return klass;
5934 }
5935
5936 static MonoImage *
5937 get_image_for_container (MonoGenericContainer *container)
5938 {
5939         MonoImage *result;
5940         if (container->is_anonymous) {
5941                 result = container->owner.image;
5942         } else {
5943                 MonoClass *klass;
5944                 if (container->is_method) {
5945                         MonoMethod *method = container->owner.method;
5946                         g_assert_checked (method);
5947                         klass = method->klass;
5948                 } else {
5949                         klass = container->owner.klass;
5950                 }
5951                 g_assert_checked (klass);
5952                 result = klass->image;
5953         }
5954         g_assert (result);
5955         return result;
5956 }
5957
5958 MonoImage *
5959 get_image_for_generic_param (MonoGenericParam *param)
5960 {
5961         MonoGenericContainer *container = mono_generic_param_owner (param);
5962         g_assert_checked (container);
5963         return get_image_for_container (container);
5964 }
5965
5966 // Make a string in the designated image consisting of a single integer.
5967 #define INT_STRING_SIZE 16
5968 char *
5969 make_generic_name_string (MonoImage *image, int num)
5970 {
5971         char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5972         g_snprintf (name, INT_STRING_SIZE, "%d", num);
5973         return name;
5974 }
5975
5976 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5977 // pinfo is derived from param by the caller for us.
5978 static MonoClass*
5979 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5980 {
5981         MonoClass *klass, **ptr;
5982         int count, pos, i;
5983         MonoGenericContainer *container = mono_generic_param_owner (param);
5984         g_assert_checked (container);
5985
5986         MonoImage *image = get_image_for_container (container);
5987         gboolean is_mvar = container->is_method;
5988         gboolean is_anonymous = container->is_anonymous;
5989
5990         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5991         klass->class_kind = MONO_CLASS_GPARAM;
5992         classes_size += sizeof (MonoClassGenericParam);
5993         ++class_gparam_count;
5994
5995         if (pinfo) {
5996                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5997         } else {
5998                 int n = mono_generic_param_num (param);
5999                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6000         }
6001
6002         if (is_anonymous) {
6003                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space ,  "" );
6004         } else if (is_mvar) {
6005                 MonoMethod *omethod = container->owner.method;
6006                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6007         } else {
6008                 MonoClass *oklass = container->owner.klass;
6009                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6010         }
6011
6012         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6013
6014         // Count non-NULL items in pinfo->constraints
6015         count = 0;
6016         if (pinfo)
6017                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6018                         ;
6019
6020         pos = 0;
6021         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6022                 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6023                 pos++;
6024         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6025                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6026         } else {
6027                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6028         }
6029
6030         if (count - pos > 0) {
6031                 klass->interface_count = count - pos;
6032                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6033                 klass->interfaces_inited = TRUE;
6034                 for (i = pos; i < count; i++)
6035                         CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6036         }
6037
6038         CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6039
6040         klass->inited = TRUE;
6041         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class ,    klass );
6042         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6043
6044         klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6045         klass->this_arg.type = klass->byval_arg.type;
6046         CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param ,  param );
6047         CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6048         klass->this_arg.byref = TRUE;
6049
6050         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6051         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6052
6053         /*Init these fields to sane values*/
6054         klass->min_align = 1;
6055         /*
6056          * This makes sure the the value size of this class is equal to the size of the types the gparam is
6057          * constrained to, the JIT depends on this.
6058          */
6059         klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6060         mono_memory_barrier ();
6061         klass->size_inited = 1;
6062
6063         mono_class_setup_supertypes (klass);
6064
6065         if (count - pos > 0) {
6066                 mono_class_setup_vtable (klass->parent);
6067                 if (mono_class_has_failure (klass->parent))
6068                         mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6069                 else
6070                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6071         }
6072
6073         return klass;
6074 }
6075
6076 #define FAST_CACHE_SIZE 16
6077
6078 /*
6079  * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6080  * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6081  * we cache the MonoClasses.
6082  * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6083  * LOCKING: Takes the image lock depending on @take_lock.
6084  */
6085 static MonoClass *
6086 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6087 {
6088         int n = mono_generic_param_num (param);
6089         MonoImage *image = get_image_for_generic_param (param);
6090         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6091         MonoClass *klass = NULL;
6092         GHashTable *ht;
6093
6094         g_assert (image);
6095
6096         // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6097         // For high numbers or constraints we have to use pointer hashes.
6098         if (param->gshared_constraint) {
6099                 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6100                 if (ht) {
6101                         if (take_lock)
6102                                 mono_image_lock (image);
6103                         klass = (MonoClass *)g_hash_table_lookup (ht, param);
6104                         if (take_lock)
6105                                 mono_image_unlock (image);
6106                 }
6107                 return klass;
6108         }
6109
6110         if (n < FAST_CACHE_SIZE) {
6111                 if (is_mvar)
6112                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6113                 else
6114                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6115         } else {
6116                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6117                 if (ht) {
6118                         if (take_lock)
6119                                 mono_image_lock (image);
6120                         klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6121                         if (take_lock)
6122                                 mono_image_unlock (image);
6123                 }
6124                 return klass;
6125         }
6126 }
6127
6128 /*
6129  * LOCKING: Image lock (param->image) must be held
6130  */
6131 static void
6132 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6133 {
6134         int n = mono_generic_param_num (param);
6135         MonoImage *image = get_image_for_generic_param (param);
6136         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6137
6138         g_assert (image);
6139
6140         if (param->gshared_constraint) {
6141                 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6142                 if (!ht) {
6143                         ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6144                         mono_memory_barrier ();
6145                         if (is_mvar)
6146                                 image->mvar_cache_constrained = ht;
6147                         else
6148                                 image->var_cache_constrained = ht;
6149                 }
6150                 g_hash_table_insert (ht, param, klass);
6151         } else if (n < FAST_CACHE_SIZE) {
6152                 if (is_mvar) {
6153                         /* Requires locking to avoid droping an already published class */
6154                         if (!image->mvar_cache_fast)
6155                                 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6156                         image->mvar_cache_fast [n] = klass;
6157                 } else {
6158                         if (!image->var_cache_fast)
6159                                 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6160                         image->var_cache_fast [n] = klass;
6161                 }
6162         } else {
6163                 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6164                 if (!ht) {
6165                         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6166                         if (!ht) {
6167                                 ht = g_hash_table_new (NULL, NULL);
6168                                 mono_memory_barrier ();
6169                                 if (is_mvar)
6170                                         image->mvar_cache_slow = ht;
6171                                 else
6172                                         image->var_cache_slow = ht;
6173                         }
6174                 }
6175                 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6176         }
6177 }
6178
6179 /*
6180  * LOCKING: Acquires the image lock (@image).
6181  */
6182 MonoClass *
6183 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6184 {
6185         MonoImage *image = get_image_for_generic_param (param);
6186         MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6187         MonoClass *klass, *klass2;
6188
6189         // If a klass already exists for this object and is cached, return it.
6190         if (pinfo) // Non-anonymous
6191                 klass = pinfo->pklass;
6192         else     // Anonymous
6193                 klass = get_anon_gparam_class (param, TRUE);
6194
6195         if (klass)
6196                 return klass;
6197
6198         // Create a new klass
6199         klass = make_generic_param_class (param, pinfo);
6200
6201         // Now we need to cache the klass we created.
6202         // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6203         // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6204         // and allow our newly-created klass object to just leak.
6205         mono_memory_barrier ();
6206
6207         mono_image_lock (image);
6208
6209     // Here "klass2" refers to the klass potentially created by the other thread.
6210         if (pinfo) // Repeat check from above
6211                 klass2 = pinfo->pklass;
6212         else
6213                 klass2 = get_anon_gparam_class (param, FALSE);
6214
6215         if (klass2) {
6216                 klass = klass2;
6217         } else {
6218                 // Cache here
6219                 if (pinfo)
6220                         pinfo->pklass = klass;
6221                 else
6222                         set_anon_gparam_class (param, klass);
6223         }
6224         mono_image_unlock (image);
6225
6226         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6227         if (klass2)
6228                 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6229         else
6230                 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6231
6232         return klass;
6233 }
6234
6235 /**
6236  * mono_class_from_generic_parameter:
6237  * \param param Parameter to find/construct a class for.
6238  * \param arg2 Is ignored.
6239  * \param arg3 Is ignored.
6240  */
6241 MonoClass *
6242 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6243 {
6244         return mono_class_from_generic_parameter_internal (param);
6245 }
6246
6247 /**
6248  * mono_ptr_class_get:
6249  */
6250 MonoClass *
6251 mono_ptr_class_get (MonoType *type)
6252 {
6253         MonoClass *result;
6254         MonoClass *el_class;
6255         MonoImage *image;
6256         char *name;
6257
6258         el_class = mono_class_from_mono_type (type);
6259         image = el_class->image;
6260
6261         mono_image_lock (image);
6262         if (image->ptr_cache) {
6263                 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6264                         mono_image_unlock (image);
6265                         return result;
6266                 }
6267         }
6268         mono_image_unlock (image);
6269         
6270         result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6271
6272         classes_size += sizeof (MonoClassPointer);
6273         ++class_pointer_count;
6274
6275         result->parent = NULL; /* no parent for PTR types */
6276         result->name_space = el_class->name_space;
6277         name = g_strdup_printf ("%s*", el_class->name);
6278         result->name = mono_image_strdup (image, name);
6279         result->class_kind = MONO_CLASS_POINTER;
6280         g_free (name);
6281
6282         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6283
6284         result->image = el_class->image;
6285         result->inited = TRUE;
6286         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6287         result->cast_class = result->element_class = el_class;
6288         result->blittable = TRUE;
6289
6290         result->byval_arg.type = MONO_TYPE_PTR;
6291         result->this_arg.type = result->byval_arg.type;
6292         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6293         result->this_arg.byref = TRUE;
6294
6295         mono_class_setup_supertypes (result);
6296
6297         mono_image_lock (image);
6298         if (image->ptr_cache) {
6299                 MonoClass *result2;
6300                 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6301                         mono_image_unlock (image);
6302                         mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6303                         return result2;
6304                 }
6305         } else {
6306                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6307         }
6308         g_hash_table_insert (image->ptr_cache, el_class, result);
6309         mono_image_unlock (image);
6310
6311         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6312
6313         return result;
6314 }
6315
6316 static MonoClass *
6317 mono_fnptr_class_get (MonoMethodSignature *sig)
6318 {
6319         MonoClass *result, *cached;
6320         static GHashTable *ptr_hash = NULL;
6321
6322         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6323
6324         mono_loader_lock ();
6325         if (!ptr_hash)
6326                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6327         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6328         mono_loader_unlock ();
6329         if (cached)
6330                 return cached;
6331
6332         result = g_new0 (MonoClass, 1);
6333
6334         result->parent = NULL; /* no parent for PTR types */
6335         result->name_space = "System";
6336         result->name = "MonoFNPtrFakeClass";
6337         result->class_kind = MONO_CLASS_POINTER;
6338
6339         result->image = mono_defaults.corlib; /* need to fix... */
6340         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6341         result->cast_class = result->element_class = result;
6342         result->byval_arg.type = MONO_TYPE_FNPTR;
6343         result->this_arg.type = result->byval_arg.type;
6344         result->this_arg.data.method = result->byval_arg.data.method = sig;
6345         result->this_arg.byref = TRUE;
6346         result->blittable = TRUE;
6347         result->inited = TRUE;
6348
6349         mono_class_setup_supertypes (result);
6350
6351         mono_loader_lock ();
6352
6353         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6354         if (cached) {
6355                 g_free (result);
6356                 mono_loader_unlock ();
6357                 return cached;
6358         }
6359
6360         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6361
6362         classes_size += sizeof (MonoClassPointer);
6363         ++class_pointer_count;
6364
6365         g_hash_table_insert (ptr_hash, sig, result);
6366
6367         mono_loader_unlock ();
6368
6369         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6370
6371         return result;
6372 }
6373
6374 /**
6375  * mono_class_from_mono_type:
6376  * \param type describes the type to return
6377  * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6378  */
6379 MonoClass *
6380 mono_class_from_mono_type (MonoType *type)
6381 {
6382         switch (type->type) {
6383         case MONO_TYPE_OBJECT:
6384                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6385         case MONO_TYPE_VOID:
6386                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6387         case MONO_TYPE_BOOLEAN:
6388                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6389         case MONO_TYPE_CHAR:
6390                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6391         case MONO_TYPE_I1:
6392                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6393         case MONO_TYPE_U1:
6394                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6395         case MONO_TYPE_I2:
6396                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6397         case MONO_TYPE_U2:
6398                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6399         case MONO_TYPE_I4:
6400                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6401         case MONO_TYPE_U4:
6402                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6403         case MONO_TYPE_I:
6404                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6405         case MONO_TYPE_U:
6406                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6407         case MONO_TYPE_I8:
6408                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6409         case MONO_TYPE_U8:
6410                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6411         case MONO_TYPE_R4:
6412                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6413         case MONO_TYPE_R8:
6414                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6415         case MONO_TYPE_STRING:
6416                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6417         case MONO_TYPE_TYPEDBYREF:
6418                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6419         case MONO_TYPE_ARRAY:
6420                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6421         case MONO_TYPE_PTR:
6422                 return mono_ptr_class_get (type->data.type);
6423         case MONO_TYPE_FNPTR:
6424                 return mono_fnptr_class_get (type->data.method);
6425         case MONO_TYPE_SZARRAY:
6426                 return mono_array_class_get (type->data.klass, 1);
6427         case MONO_TYPE_CLASS:
6428         case MONO_TYPE_VALUETYPE:
6429                 return type->data.klass;
6430         case MONO_TYPE_GENERICINST:
6431                 return mono_generic_class_get_class (type->data.generic_class);
6432         case MONO_TYPE_MVAR:
6433         case MONO_TYPE_VAR:
6434                 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6435         default:
6436                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6437                 g_assert_not_reached ();
6438         }
6439
6440         // Yes, this returns NULL, even if it is documented as not doing so, but there
6441         // is no way for the code to make it this far, due to the assert above.
6442         return NULL;
6443 }
6444
6445 /**
6446  * mono_type_retrieve_from_typespec
6447  * \param image context where the image is created
6448  * \param type_spec  typespec token
6449  * \param context the generic context used to evaluate generic instantiations in
6450  */
6451 static MonoType *
6452 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6453 {
6454         MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6455
6456         *did_inflate = FALSE;
6457
6458         if (!t)
6459                 return NULL;
6460
6461         if (context && (context->class_inst || context->method_inst)) {
6462                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6463
6464                 if (!mono_error_ok (error)) {
6465                         return NULL;
6466                 }
6467
6468                 if (inflated) {
6469                         t = inflated;
6470                         *did_inflate = TRUE;
6471                 }
6472         }
6473         return t;
6474 }
6475
6476 /**
6477  * mono_class_create_from_typespec
6478  * \param image context where the image is created
6479  * \param type_spec typespec token
6480  * \param context the generic context used to evaluate generic instantiations in
6481  */
6482 static MonoClass *
6483 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6484 {
6485         MonoClass *ret;
6486         gboolean inflated = FALSE;
6487         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6488         return_val_if_nok (error, NULL);
6489         ret = mono_class_from_mono_type (t);
6490         if (inflated)
6491                 mono_metadata_free_type (t);
6492         return ret;
6493 }
6494
6495 /**
6496  * mono_bounded_array_class_get:
6497  * \param element_class element class 
6498  * \param rank the dimension of the array class
6499  * \param bounded whenever the array has non-zero bounds
6500  * \returns A class object describing the array with element type \p element_type and 
6501  * dimension \p rank.
6502  */
6503 MonoClass *
6504 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6505 {
6506         MonoImage *image;
6507         MonoClass *klass, *cached, *k;
6508         MonoClass *parent = NULL;
6509         GSList *list, *rootlist = NULL;
6510         int nsize;
6511         char *name;
6512
6513         g_assert (rank <= 255);
6514
6515         if (rank > 1)
6516                 /* bounded only matters for one-dimensional arrays */
6517                 bounded = FALSE;
6518
6519         image = eclass->image;
6520
6521         /* Check cache */
6522         cached = NULL;
6523         if (rank == 1 && !bounded) {
6524                 /*
6525                  * This case is very frequent not just during compilation because of calls
6526                  * from mono_class_from_mono_type (), mono_array_new (),
6527                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6528                  */
6529                 mono_os_mutex_lock (&image->szarray_cache_lock);
6530                 if (!image->szarray_cache)
6531                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6532                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6533                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6534         } else {
6535                 mono_loader_lock ();
6536                 if (!image->array_cache)
6537                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6538                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6539                 for (list = rootlist; list; list = list->next) {
6540                         k = (MonoClass *)list->data;
6541                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6542                                 cached = k;
6543                                 break;
6544                         }
6545                 }
6546                 mono_loader_unlock ();
6547         }
6548         if (cached)
6549                 return cached;
6550
6551         parent = mono_defaults.array_class;
6552         if (!parent->inited)
6553                 mono_class_init (parent);
6554
6555         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6556
6557         klass->image = image;
6558         klass->name_space = eclass->name_space;
6559         klass->class_kind = MONO_CLASS_ARRAY;
6560
6561         nsize = strlen (eclass->name);
6562         name = (char *)g_malloc (nsize + 2 + rank + 1);
6563         memcpy (name, eclass->name, nsize);
6564         name [nsize] = '[';
6565         if (rank > 1)
6566                 memset (name + nsize + 1, ',', rank - 1);
6567         if (bounded)
6568                 name [nsize + rank] = '*';
6569         name [nsize + rank + bounded] = ']';
6570         name [nsize + rank + bounded + 1] = 0;
6571         klass->name = mono_image_strdup (image, name);
6572         g_free (name);
6573
6574         klass->type_token = 0;
6575         klass->parent = parent;
6576         klass->instance_size = mono_class_instance_size (klass->parent);
6577
6578         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6579                 /*Arrays of those two types are invalid.*/
6580                 MonoError prepared_error;
6581                 error_init (&prepared_error);
6582                 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6583                 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6584                 mono_error_cleanup (&prepared_error);
6585         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6586                 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6587                 if (!ref_info_handle || eclass->wastypebuilder) {
6588                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6589                         g_assert (ref_info_handle && !eclass->wastypebuilder);
6590                 }
6591                 /* element_size -1 is ok as this is not an instantitable type*/
6592                 klass->sizes.element_size = -1;
6593         } else
6594                 klass->sizes.element_size = mono_class_array_element_size (eclass);
6595
6596         mono_class_setup_supertypes (klass);
6597
6598         if (mono_class_is_ginst (eclass))
6599                 mono_class_init (eclass);
6600         if (!eclass->size_inited)
6601                 mono_class_setup_fields (eclass);
6602         mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6603         /*FIXME we fail the array type, but we have to let other fields be set.*/
6604
6605         klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6606
6607         klass->rank = rank;
6608         
6609         if (eclass->enumtype)
6610                 klass->cast_class = eclass->element_class;
6611         else
6612                 klass->cast_class = eclass;
6613
6614         switch (klass->cast_class->byval_arg.type) {
6615         case MONO_TYPE_I1:
6616                 klass->cast_class = mono_defaults.byte_class;
6617                 break;
6618         case MONO_TYPE_U2:
6619                 klass->cast_class = mono_defaults.int16_class;
6620                 break;
6621         case MONO_TYPE_U4:
6622 #if SIZEOF_VOID_P == 4
6623         case MONO_TYPE_I:
6624         case MONO_TYPE_U:
6625 #endif
6626                 klass->cast_class = mono_defaults.int32_class;
6627                 break;
6628         case MONO_TYPE_U8:
6629 #if SIZEOF_VOID_P == 8
6630         case MONO_TYPE_I:
6631         case MONO_TYPE_U:
6632 #endif
6633                 klass->cast_class = mono_defaults.int64_class;
6634                 break;
6635         default:
6636                 break;
6637         }
6638
6639         klass->element_class = eclass;
6640
6641         if ((rank > 1) || bounded) {
6642                 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6643                 klass->byval_arg.type = MONO_TYPE_ARRAY;
6644                 klass->byval_arg.data.array = at;
6645                 at->eklass = eclass;
6646                 at->rank = rank;
6647                 /* FIXME: complete.... */
6648         } else {
6649                 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6650                 klass->byval_arg.data.klass = eclass;
6651         }
6652         klass->this_arg = klass->byval_arg;
6653         klass->this_arg.byref = 1;
6654
6655         if (rank > 32) {
6656                 MonoError prepared_error;
6657                 error_init (&prepared_error);
6658                 name = mono_type_get_full_name (klass);
6659                 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6660                 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6661                 mono_error_cleanup (&prepared_error);
6662                 g_free (name);
6663         }
6664
6665         mono_loader_lock ();
6666
6667         /* Check cache again */
6668         cached = NULL;
6669         if (rank == 1 && !bounded) {
6670                 mono_os_mutex_lock (&image->szarray_cache_lock);
6671                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6672                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6673         } else {
6674                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6675                 for (list = rootlist; list; list = list->next) {
6676                         k = (MonoClass *)list->data;
6677                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6678                                 cached = k;
6679                                 break;
6680                         }
6681                 }
6682         }
6683         if (cached) {
6684                 mono_loader_unlock ();
6685                 return cached;
6686         }
6687
6688         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6689
6690         classes_size += sizeof (MonoClassArray);
6691         ++class_array_count;
6692
6693         if (rank == 1 && !bounded) {
6694                 mono_os_mutex_lock (&image->szarray_cache_lock);
6695                 g_hash_table_insert (image->szarray_cache, eclass, klass);
6696                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6697         } else {
6698                 list = g_slist_append (rootlist, klass);
6699                 g_hash_table_insert (image->array_cache, eclass, list);
6700         }
6701
6702         mono_loader_unlock ();
6703
6704         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6705
6706         return klass;
6707 }
6708
6709 /**
6710  * mono_array_class_get:
6711  * \param element_class element class 
6712  * \param rank the dimension of the array class
6713  * \returns A class object describing the array with element type \p element_type and 
6714  * dimension \p rank.
6715  */
6716 MonoClass *
6717 mono_array_class_get (MonoClass *eclass, guint32 rank)
6718 {
6719         return mono_bounded_array_class_get (eclass, rank, FALSE);
6720 }
6721
6722 /**
6723  * mono_class_instance_size:
6724  * \param klass a class
6725  *
6726  * Use to get the size of a class in bytes.
6727  *
6728  * \returns The size of an object instance
6729  */
6730 gint32
6731 mono_class_instance_size (MonoClass *klass)
6732 {       
6733         if (!klass->size_inited)
6734                 mono_class_init (klass);
6735
6736         return klass->instance_size;
6737 }
6738
6739 /**
6740  * mono_class_min_align:
6741  * \param klass a class 
6742  *
6743  * Use to get the computed minimum alignment requirements for the specified class.
6744  *
6745  * Returns: minimum alignment requirements
6746  */
6747 gint32
6748 mono_class_min_align (MonoClass *klass)
6749 {       
6750         if (!klass->size_inited)
6751                 mono_class_init (klass);
6752
6753         return klass->min_align;
6754 }
6755
6756 /**
6757  * mono_class_value_size:
6758  * \param klass a class 
6759  *
6760  * This function is used for value types, and return the
6761  * space and the alignment to store that kind of value object.
6762  *
6763  * \returns the size of a value of kind \p klass
6764  */
6765 gint32
6766 mono_class_value_size (MonoClass *klass, guint32 *align)
6767 {
6768         gint32 size;
6769
6770         /* fixme: check disable, because we still have external revereces to
6771          * mscorlib and Dummy Objects 
6772          */
6773         /*g_assert (klass->valuetype);*/
6774
6775         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6776
6777         if (align)
6778                 *align = klass->min_align;
6779
6780         return size;
6781 }
6782
6783 /**
6784  * mono_class_data_size:
6785  * \param klass a class 
6786  * 
6787  * \returns The size of the static class data
6788  */
6789 gint32
6790 mono_class_data_size (MonoClass *klass)
6791 {       
6792         if (!klass->inited)
6793                 mono_class_init (klass);
6794         /* This can happen with dynamically created types */
6795         if (!klass->fields_inited)
6796                 mono_class_setup_fields (klass);
6797
6798         /* in arrays, sizes.class_size is unioned with element_size
6799          * and arrays have no static fields
6800          */
6801         if (klass->rank)
6802                 return 0;
6803         return klass->sizes.class_size;
6804 }
6805
6806 /*
6807  * Auxiliary routine to mono_class_get_field
6808  *
6809  * Takes a field index instead of a field token.
6810  */
6811 static MonoClassField *
6812 mono_class_get_field_idx (MonoClass *klass, int idx)
6813 {
6814         mono_class_setup_fields (klass);
6815         if (mono_class_has_failure (klass))
6816                 return NULL;
6817
6818         while (klass) {
6819                 int first_field_idx = mono_class_get_first_field_idx (klass);
6820                 int fcount = mono_class_get_field_count (klass);
6821                 if (klass->image->uncompressed_metadata) {
6822                         /* 
6823                          * first_field_idx points to the FieldPtr table, while idx points into the
6824                          * Field table, so we have to do a search.
6825                          */
6826                         /*FIXME this is broken for types with multiple fields with the same name.*/
6827                         const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6828                         int i;
6829
6830                         for (i = 0; i < fcount; ++i)
6831                                 if (mono_field_get_name (&klass->fields [i]) == name)
6832                                         return &klass->fields [i];
6833                         g_assert_not_reached ();
6834                 } else {                        
6835                         if (fcount) {
6836                                 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6837                                         return &klass->fields [idx - first_field_idx];
6838                                 }
6839                         }
6840                 }
6841                 klass = klass->parent;
6842         }
6843         return NULL;
6844 }
6845
6846 /**
6847  * mono_class_get_field:
6848  * \param class the class to lookup the field.
6849  * \param field_token the field token
6850  *
6851  * \returns A \c MonoClassField representing the type and offset of
6852  * the field, or a NULL value if the field does not belong to this
6853  * class.
6854  */
6855 MonoClassField *
6856 mono_class_get_field (MonoClass *klass, guint32 field_token)
6857 {
6858         int idx = mono_metadata_token_index (field_token);
6859
6860         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6861
6862         return mono_class_get_field_idx (klass, idx - 1);
6863 }
6864
6865 /**
6866  * mono_class_get_field_from_name:
6867  * \param klass the class to lookup the field.
6868  * \param name the field name
6869  *
6870  * Search the class \p klass and its parents for a field with the name \p name.
6871  * 
6872  * \returns The \c MonoClassField pointer of the named field or NULL
6873  */
6874 MonoClassField *
6875 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6876 {
6877         return mono_class_get_field_from_name_full (klass, name, NULL);
6878 }
6879
6880 /**
6881  * mono_class_get_field_from_name_full:
6882  * \param klass the class to lookup the field.
6883  * \param name the field name
6884  * \param type the type of the fields. This optional.
6885  *
6886  * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6887  *
6888  * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6889  * of its generic type definition.
6890  *
6891  * \returns The MonoClassField pointer of the named field or NULL
6892  */
6893 MonoClassField *
6894 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6895 {
6896         int i;
6897
6898         mono_class_setup_fields (klass);
6899         if (mono_class_has_failure (klass))
6900                 return NULL;
6901
6902         while (klass) {
6903                 int fcount = mono_class_get_field_count (klass);
6904                 for (i = 0; i < fcount; ++i) {
6905                         MonoClassField *field = &klass->fields [i];
6906
6907                         if (strcmp (name, mono_field_get_name (field)) != 0)
6908                                 continue;
6909
6910                         if (type) {
6911                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6912                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6913                                         continue;
6914                         }
6915                         return field;
6916                 }
6917                 klass = klass->parent;
6918         }
6919         return NULL;
6920 }
6921
6922 /**
6923  * mono_class_get_field_token:
6924  * \param field the field we need the token of
6925  *
6926  * Get the token of a field. Note that the tokesn is only valid for the image
6927  * the field was loaded from. Don't use this function for fields in dynamic types.
6928  * 
6929  * \returns The token representing the field in the image it was loaded from.
6930  */
6931 guint32
6932 mono_class_get_field_token (MonoClassField *field)
6933 {
6934         MonoClass *klass = field->parent;
6935         int i;
6936
6937         mono_class_setup_fields (klass);
6938
6939         while (klass) {
6940                 if (!klass->fields)
6941                         return 0;
6942                 int first_field_idx = mono_class_get_first_field_idx (klass);
6943                 int fcount = mono_class_get_field_count (klass);
6944                 for (i = 0; i < fcount; ++i) {
6945                         if (&klass->fields [i] == field) {
6946                                 int idx = first_field_idx + i + 1;
6947
6948                                 if (klass->image->uncompressed_metadata)
6949                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6950                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6951                         }
6952                 }
6953                 klass = klass->parent;
6954         }
6955
6956         g_assert_not_reached ();
6957         return 0;
6958 }
6959
6960 static int
6961 mono_field_get_index (MonoClassField *field)
6962 {
6963         int index = field - field->parent->fields;
6964         g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6965
6966         return index;
6967 }
6968
6969 /*
6970  * mono_class_get_field_default_value:
6971  *
6972  * Return the default value of the field as a pointer into the metadata blob.
6973  */
6974 const char*
6975 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6976 {
6977         guint32 cindex;
6978         guint32 constant_cols [MONO_CONSTANT_SIZE];
6979         int field_index;
6980         MonoClass *klass = field->parent;
6981         MonoFieldDefaultValue *def_values;
6982
6983         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6984
6985         def_values = mono_class_get_field_def_values (klass);
6986         if (!def_values) {
6987                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6988
6989                 mono_class_set_field_def_values (klass, def_values);
6990         }
6991
6992         field_index = mono_field_get_index (field);
6993                 
6994         if (!def_values [field_index].data) {
6995                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6996                 if (!cindex)
6997                         return NULL;
6998
6999                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7000
7001                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7002                 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7003                 mono_memory_barrier ();
7004                 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7005         }
7006
7007         *def_type = def_values [field_index].def_type;
7008         return def_values [field_index].data;
7009 }
7010
7011 static int
7012 mono_property_get_index (MonoProperty *prop)
7013 {
7014         MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7015         int index = prop - info->properties;
7016
7017         g_assert (index >= 0 && index < info->count);
7018
7019         return index;
7020 }
7021
7022 /*
7023  * mono_class_get_property_default_value:
7024  *
7025  * Return the default value of the field as a pointer into the metadata blob.
7026  */
7027 const char*
7028 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7029 {
7030         guint32 cindex;
7031         guint32 constant_cols [MONO_CONSTANT_SIZE];
7032         MonoClass *klass = property->parent;
7033
7034         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7035         /*
7036          * We don't cache here because it is not used by C# so it's quite rare, but
7037          * we still do the lookup in klass->ext because that is where the data
7038          * is stored for dynamic assemblies.
7039          */
7040
7041         if (image_is_dynamic (klass->image)) {
7042                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7043                 int prop_index = mono_property_get_index (property);
7044                 if (info->def_values && info->def_values [prop_index].data) {
7045                         *def_type = info->def_values [prop_index].def_type;
7046                         return info->def_values [prop_index].data;
7047                 }
7048                 return NULL;
7049         }
7050         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7051         if (!cindex)
7052                 return NULL;
7053
7054         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7055         *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7056         return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7057 }
7058
7059 /**
7060  * mono_class_get_event_token:
7061  */
7062 guint32
7063 mono_class_get_event_token (MonoEvent *event)
7064 {
7065         MonoClass *klass = event->parent;
7066         int i;
7067
7068         while (klass) {
7069                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7070                 if (info) {
7071                         for (i = 0; i < info->count; ++i) {
7072                                 if (&info->events [i] == event)
7073                                         return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7074                         }
7075                 }
7076                 klass = klass->parent;
7077         }
7078
7079         g_assert_not_reached ();
7080         return 0;
7081 }
7082
7083 /**
7084  * mono_class_get_property_from_name:
7085  * \param klass a class
7086  * \param name name of the property to lookup in the specified class
7087  *
7088  * Use this method to lookup a property in a class
7089  * \returns the \c MonoProperty with the given name, or NULL if the property
7090  * does not exist on the \p klass.
7091  */
7092 MonoProperty*
7093 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7094 {
7095         while (klass) {
7096                 MonoProperty* p;
7097                 gpointer iter = NULL;
7098                 while ((p = mono_class_get_properties (klass, &iter))) {
7099                         if (! strcmp (name, p->name))
7100                                 return p;
7101                 }
7102                 klass = klass->parent;
7103         }
7104         return NULL;
7105 }
7106
7107 /**
7108  * mono_class_get_property_token:
7109  * \param prop MonoProperty to query
7110  *
7111  * \returns The ECMA token for the specified property.
7112  */
7113 guint32
7114 mono_class_get_property_token (MonoProperty *prop)
7115 {
7116         MonoClass *klass = prop->parent;
7117         while (klass) {
7118                 MonoProperty* p;
7119                 int i = 0;
7120                 gpointer iter = NULL;
7121                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7122                 while ((p = mono_class_get_properties (klass, &iter))) {
7123                         if (&info->properties [i] == prop)
7124                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7125                         
7126                         i ++;
7127                 }
7128                 klass = klass->parent;
7129         }
7130
7131         g_assert_not_reached ();
7132         return 0;
7133 }
7134
7135 /**
7136  * mono_class_name_from_token:
7137  */
7138 char *
7139 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7140 {
7141         const char *name, *nspace;
7142         if (image_is_dynamic (image))
7143                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7144         
7145         switch (type_token & 0xff000000){
7146         case MONO_TOKEN_TYPE_DEF: {
7147                 guint32 cols [MONO_TYPEDEF_SIZE];
7148                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7149                 guint tidx = mono_metadata_token_index (type_token);
7150
7151                 if (tidx > tt->rows)
7152                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7153
7154                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7155                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7156                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7157                 if (strlen (nspace) == 0)
7158                         return g_strdup_printf ("%s", name);
7159                 else
7160                         return g_strdup_printf ("%s.%s", nspace, name);
7161         }
7162
7163         case MONO_TOKEN_TYPE_REF: {
7164                 MonoError error;
7165                 guint32 cols [MONO_TYPEREF_SIZE];
7166                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7167                 guint tidx = mono_metadata_token_index (type_token);
7168
7169                 if (tidx > t->rows)
7170                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7171
7172                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7173                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7174                         mono_error_cleanup (&error);
7175                         return msg;
7176                 }
7177
7178                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7179                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7180                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7181                 if (strlen (nspace) == 0)
7182                         return g_strdup_printf ("%s", name);
7183                 else
7184                         return g_strdup_printf ("%s.%s", nspace, name);
7185         }
7186                 
7187         case MONO_TOKEN_TYPE_SPEC:
7188                 return g_strdup_printf ("Typespec 0x%08x", type_token);
7189         default:
7190                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7191         }
7192 }
7193
7194 static char *
7195 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7196 {
7197         if (image_is_dynamic (image))
7198                 return g_strdup_printf ("DynamicAssembly %s", image->name);
7199         
7200         switch (type_token & 0xff000000){
7201         case MONO_TOKEN_TYPE_DEF:
7202                 if (image->assembly)
7203                         return mono_stringify_assembly_name (&image->assembly->aname);
7204                 else if (image->assembly_name)
7205                         return g_strdup (image->assembly_name);
7206                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7207         case MONO_TOKEN_TYPE_REF: {
7208                 MonoError error;
7209                 MonoAssemblyName aname;
7210                 guint32 cols [MONO_TYPEREF_SIZE];
7211                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7212                 guint32 idx = mono_metadata_token_index (type_token);
7213
7214                 if (idx > t->rows)
7215                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7216         
7217                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7218                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7219                         mono_error_cleanup (&error);
7220                         return msg;
7221                 }
7222                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7223
7224                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7225                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7226                 case MONO_RESOLUTION_SCOPE_MODULE:
7227                         /* FIXME: */
7228                         return g_strdup ("");
7229                 case MONO_RESOLUTION_SCOPE_MODULEREF:
7230                         /* FIXME: */
7231                         return g_strdup ("");
7232                 case MONO_RESOLUTION_SCOPE_TYPEREF:
7233                         /* FIXME: */
7234                         return g_strdup ("");
7235                 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7236                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7237                         return mono_stringify_assembly_name (&aname);
7238                 default:
7239                         g_assert_not_reached ();
7240                 }
7241                 break;
7242         }
7243         case MONO_TOKEN_TYPE_SPEC:
7244                 /* FIXME: */
7245                 return g_strdup ("");
7246         default:
7247                 g_assert_not_reached ();
7248         }
7249
7250         return NULL;
7251 }
7252
7253 /**
7254  * mono_class_get_full:
7255  * \param image the image where the class resides
7256  * \param type_token the token for the class
7257  * \param context the generic context used to evaluate generic instantiations in
7258  * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7259  * \returns The \c MonoClass that represents \p type_token in \p image
7260  */
7261 MonoClass *
7262 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7263 {
7264         MonoError error;
7265         MonoClass *klass;
7266         klass = mono_class_get_checked (image, type_token, &error);
7267
7268         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7269                 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7270
7271         g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7272         return klass;
7273 }
7274
7275
7276 MonoClass *
7277 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7278 {
7279         MonoClass *klass;
7280
7281         error_init (error);
7282         klass = mono_class_get_checked (image, type_token, error);
7283
7284         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7285                 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7286
7287         return klass;
7288 }
7289 /**
7290  * mono_class_get_checked:
7291  * \param image the image where the class resides
7292  * \param type_token the token for the class
7293  * \param error error object to return any error
7294  *
7295  * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7296  */
7297 MonoClass *
7298 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7299 {
7300         MonoClass *klass = NULL;
7301
7302         error_init (error);
7303
7304         if (image_is_dynamic (image)) {
7305                 int table = mono_metadata_token_table (type_token);
7306
7307                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7308                         mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7309                         return NULL;
7310                 }
7311                 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7312                 goto done;
7313         }
7314
7315         switch (type_token & 0xff000000){
7316         case MONO_TOKEN_TYPE_DEF:
7317                 klass = mono_class_create_from_typedef (image, type_token, error);
7318                 break;          
7319         case MONO_TOKEN_TYPE_REF:
7320                 klass = mono_class_from_typeref_checked (image, type_token, error);
7321                 break;
7322         case MONO_TOKEN_TYPE_SPEC:
7323                 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7324                 break;
7325         default:
7326                 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7327         }
7328
7329 done:
7330         /* Generic case, should be avoided for when a better error is possible. */
7331         if (!klass && mono_error_ok (error)) {
7332                 char *name = mono_class_name_from_token (image, type_token);
7333                 char *assembly = mono_assembly_name_from_token (image, type_token);
7334                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7335         }
7336
7337         return klass;
7338 }
7339
7340
7341 /**
7342  * mono_type_get_checked:
7343  * \param image the image where the type resides
7344  * \param type_token the token for the type
7345  * \param context the generic context used to evaluate generic instantiations in
7346  * \param error Error handling context
7347  *
7348  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7349  * 
7350  * \returns The MonoType that represents \p type_token in \p image
7351  */
7352 MonoType *
7353 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7354 {
7355         MonoType *type = NULL;
7356         gboolean inflated = FALSE;
7357
7358         error_init (error);
7359
7360         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7361         if (image_is_dynamic (image)) {
7362                 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7363                 return_val_if_nok (error, NULL);
7364                 return mono_class_get_type (klass);
7365         }
7366
7367         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7368                 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7369
7370                 if (!klass) {
7371                         return NULL;
7372                 }
7373
7374                 g_assert (klass);
7375                 return mono_class_get_type (klass);
7376         }
7377
7378         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7379
7380         if (!type) {
7381                 return NULL;
7382         }
7383
7384         if (inflated) {
7385                 MonoType *tmp = type;
7386                 type = mono_class_get_type (mono_class_from_mono_type (type));
7387                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7388                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7389                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7390                  *
7391                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7392                  * */
7393                 if (type->type != tmp->type)
7394                         type = tmp;
7395                 else
7396                         mono_metadata_free_type (tmp);
7397         }
7398         return type;
7399 }
7400
7401 /**
7402  * mono_class_get:
7403  * \param image image where the class token will be looked up.
7404  * \param type_token a type token from the image
7405  * \returns the \c MonoClass with the given \p type_token on the \p image
7406  */
7407 MonoClass *
7408 mono_class_get (MonoImage *image, guint32 type_token)
7409 {
7410         return mono_class_get_full (image, type_token, NULL);
7411 }
7412
7413 /**
7414  * mono_image_init_name_cache:
7415  *
7416  *  Initializes the class name cache stored in image->name_cache.
7417  *
7418  * LOCKING: Acquires the corresponding image lock.
7419  */
7420 void
7421 mono_image_init_name_cache (MonoImage *image)
7422 {
7423         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7424         guint32 cols [MONO_TYPEDEF_SIZE];
7425         const char *name;
7426         const char *nspace;
7427         guint32 i, visib, nspace_index;
7428         GHashTable *name_cache2, *nspace_table, *the_name_cache;
7429
7430         if (image->name_cache)
7431                 return;
7432
7433         the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7434
7435         if (image_is_dynamic (image)) {
7436                 mono_image_lock (image);
7437                 if (image->name_cache) {
7438                         /* Somebody initialized it before us */
7439                         g_hash_table_destroy (the_name_cache);
7440                 } else {
7441                         mono_atomic_store_release (&image->name_cache, the_name_cache);
7442                 }
7443                 mono_image_unlock (image);
7444                 return;
7445         }
7446
7447         /* Temporary hash table to avoid lookups in the nspace_table */
7448         name_cache2 = g_hash_table_new (NULL, NULL);
7449
7450         for (i = 1; i <= t->rows; ++i) {
7451                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7452                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7453                 /*
7454                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7455                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7456                  */
7457                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7458                         continue;
7459                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7460                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7461
7462                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7463                 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7464                 if (!nspace_table) {
7465                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7466                         g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7467                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7468                                                                  nspace_table);
7469                 }
7470                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7471         }
7472
7473         /* Load type names from EXPORTEDTYPES table */
7474         {
7475                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7476                 guint32 cols [MONO_EXP_TYPE_SIZE];
7477                 int i;
7478
7479                 for (i = 0; i < t->rows; ++i) {
7480                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7481
7482                         guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7483                         if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7484                                 /* Nested type */
7485                                 continue;
7486
7487                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7488                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7489
7490                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7491                         nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7492                         if (!nspace_table) {
7493                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7494                                 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7495                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7496                                                                          nspace_table);
7497                         }
7498                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7499                 }
7500         }
7501
7502         g_hash_table_destroy (name_cache2);
7503
7504         mono_image_lock (image);
7505         if (image->name_cache) {
7506                 /* Somebody initialized it before us */
7507                 g_hash_table_destroy (the_name_cache);
7508         } else {
7509                 mono_atomic_store_release (&image->name_cache, the_name_cache);
7510         }
7511         mono_image_unlock (image);
7512 }
7513
7514 /*FIXME Only dynamic assemblies should allow this operation.*/
7515 /**
7516  * mono_image_add_to_name_cache:
7517  */
7518 void
7519 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7520                                                           const char *name, guint32 index)
7521 {
7522         GHashTable *nspace_table;
7523         GHashTable *name_cache;
7524         guint32 old_index;
7525
7526         mono_image_init_name_cache (image);
7527         mono_image_lock (image);
7528
7529         name_cache = image->name_cache;
7530         if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7531                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7532                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7533         }
7534
7535         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7536                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7537
7538         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7539
7540         mono_image_unlock (image);
7541 }
7542
7543 typedef struct {
7544         gconstpointer key;
7545         gpointer value;
7546 } FindUserData;
7547
7548 static void
7549 find_nocase (gpointer key, gpointer value, gpointer user_data)
7550 {
7551         char *name = (char*)key;
7552         FindUserData *data = (FindUserData*)user_data;
7553
7554         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7555                 data->value = value;
7556 }
7557
7558 /**
7559  * mono_class_from_name_case:
7560  * \param image The MonoImage where the type is looked up in
7561  * \param name_space the type namespace
7562  * \param name the type short name.
7563  * \deprecated use the mono_class_from_name_case_checked variant instead.
7564  *
7565  * Obtains a \c MonoClass with a given namespace and a given name which
7566  * is located in the given \c MonoImage.   The namespace and name
7567  * lookups are case insensitive.
7568  */
7569 MonoClass *
7570 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7571 {
7572         MonoError error;
7573         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7574         mono_error_cleanup (&error);
7575
7576         return res;
7577 }
7578
7579 /**
7580  * mono_class_from_name_case_checked:
7581  * \param image The MonoImage where the type is looked up in
7582  * \param name_space the type namespace
7583  * \param name the type short name.
7584  * \param error if 
7585  *
7586  * Obtains a MonoClass with a given namespace and a given name which
7587  * is located in the given MonoImage.   The namespace and name
7588  * lookups are case insensitive.
7589  *
7590  * \returns The MonoClass if the given namespace and name were found, or NULL if it
7591  * was not found.   The \p error object will contain information about the problem
7592  * in that case.
7593  */
7594 MonoClass *
7595 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7596 {
7597         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7598         guint32 cols [MONO_TYPEDEF_SIZE];
7599         const char *n;
7600         const char *nspace;
7601         guint32 i, visib;
7602
7603         error_init (error);
7604
7605         if (image_is_dynamic (image)) {
7606                 guint32 token = 0;
7607                 FindUserData user_data;
7608
7609                 mono_image_init_name_cache (image);
7610                 mono_image_lock (image);
7611
7612                 user_data.key = name_space;
7613                 user_data.value = NULL;
7614                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7615
7616                 if (user_data.value) {
7617                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7618
7619                         user_data.key = name;
7620                         user_data.value = NULL;
7621
7622                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7623                         
7624                         if (user_data.value)
7625                                 token = GPOINTER_TO_UINT (user_data.value);
7626                 }
7627
7628                 mono_image_unlock (image);
7629                 
7630                 if (token)
7631                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7632                 else
7633                         return NULL;
7634
7635         }
7636
7637         /* add a cache if needed */
7638         for (i = 1; i <= t->rows; ++i) {
7639                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7640                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7641                 /*
7642                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7643                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7644                  */
7645                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7646                         continue;
7647                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7648                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7649                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7650                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7651         }
7652         return NULL;
7653 }
7654
7655 static MonoClass*
7656 return_nested_in (MonoClass *klass, char *nested)
7657 {
7658         MonoClass *found;
7659         char *s = strchr (nested, '/');
7660         gpointer iter = NULL;
7661
7662         if (s) {
7663                 *s = 0;
7664                 s++;
7665         }
7666
7667         while ((found = mono_class_get_nested_types (klass, &iter))) {
7668                 if (strcmp (found->name, nested) == 0) {
7669                         if (s)
7670                                 return return_nested_in (found, s);
7671                         return found;
7672                 }
7673         }
7674         return NULL;
7675 }
7676
7677 static MonoClass*
7678 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7679 {
7680         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7681         MonoImage *file_image;
7682         MonoClass *klass;
7683         int i;
7684
7685         error_init (error);
7686
7687         /* 
7688          * The EXPORTEDTYPES table only contains public types, so have to search the
7689          * modules as well.
7690          * Note: image->modules contains the contents of the MODULEREF table, while
7691          * the real module list is in the FILE table.
7692          */
7693         for (i = 0; i < file_table->rows; i++) {
7694                 guint32 cols [MONO_FILE_SIZE];
7695                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7696                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7697                         continue;
7698
7699                 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7700                 if (file_image) {
7701                         klass = mono_class_from_name_checked (file_image, name_space, name, error);
7702                         if (klass || !is_ok (error))
7703                                 return klass;
7704                 }
7705         }
7706
7707         return NULL;
7708 }
7709
7710 static MonoClass *
7711 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7712 {
7713         GHashTable *nspace_table;
7714         MonoImage *loaded_image;
7715         guint32 token = 0;
7716         int i;
7717         MonoClass *klass;
7718         char *nested;
7719         char buf [1024];
7720
7721         error_init (error);
7722
7723         // Checking visited images avoids stack overflows when cyclic references exist.
7724         if (g_hash_table_lookup (visited_images, image))
7725                 return NULL;
7726
7727         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7728
7729         if ((nested = strchr (name, '/'))) {
7730                 int pos = nested - name;
7731                 int len = strlen (name);
7732                 if (len > 1023)
7733                         return NULL;
7734                 memcpy (buf, name, len + 1);
7735                 buf [pos] = 0;
7736                 nested = buf + pos + 1;
7737                 name = buf;
7738         }
7739
7740         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7741         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7742                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7743                 if (res) {
7744                         if (!klass) {
7745                                 klass = search_modules (image, name_space, name, error);
7746                                 if (!is_ok (error))
7747                                         return NULL;
7748                         }
7749                         if (nested)
7750                                 return klass ? return_nested_in (klass, nested) : NULL;
7751                         else
7752                                 return klass;
7753                 }
7754         }
7755
7756         mono_image_init_name_cache (image);
7757         mono_image_lock (image);
7758
7759         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7760
7761         if (nspace_table)
7762                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7763
7764         mono_image_unlock (image);
7765
7766         if (!token && image_is_dynamic (image) && image->modules) {
7767                 /* Search modules as well */
7768                 for (i = 0; i < image->module_count; ++i) {
7769                         MonoImage *module = image->modules [i];
7770
7771                         klass = mono_class_from_name_checked (module, name_space, name, error);
7772                         if (klass || !is_ok (error))
7773                                 return klass;
7774                 }
7775         }
7776
7777         if (!token) {
7778                 klass = search_modules (image, name_space, name, error);
7779                 if (klass || !is_ok (error))
7780                         return klass;
7781                 return NULL;
7782         }
7783
7784         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7785                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7786                 guint32 cols [MONO_EXP_TYPE_SIZE];
7787                 guint32 idx, impl;
7788
7789                 idx = mono_metadata_token_index (token);
7790
7791                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7792
7793                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7794                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7795                         loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7796                         if (!loaded_image)
7797                                 return NULL;
7798                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7799                         if (nested)
7800                                 return klass ? return_nested_in (klass, nested) : NULL;
7801                         return klass;
7802                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7803                         guint32 assembly_idx;
7804
7805                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7806
7807                         mono_assembly_load_reference (image, assembly_idx - 1);
7808                         g_assert (image->references [assembly_idx - 1]);
7809                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7810                                 return NULL;                    
7811                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7812                         if (nested)
7813                                 return klass ? return_nested_in (klass, nested) : NULL;
7814                         return klass;
7815                 } else {
7816                         g_assert_not_reached ();
7817                 }
7818         }
7819
7820         token = MONO_TOKEN_TYPE_DEF | token;
7821
7822         klass = mono_class_get_checked (image, token, error);
7823         if (nested)
7824                 return return_nested_in (klass, nested);
7825         return klass;
7826 }
7827
7828 /**
7829  * mono_class_from_name_checked:
7830  * \param image The MonoImage where the type is looked up in
7831  * \param name_space the type namespace
7832  * \param name the type short name.
7833  *
7834  * Obtains a MonoClass with a given namespace and a given name which
7835  * is located in the given MonoImage.
7836  *
7837  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7838  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7839  */
7840 MonoClass *
7841 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7842 {
7843         MonoClass *klass;
7844         GHashTable *visited_images;
7845
7846         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7847
7848         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7849
7850         g_hash_table_destroy (visited_images);
7851
7852         return klass;
7853 }
7854
7855 /**
7856  * mono_class_from_name:
7857  * \param image The \c MonoImage where the type is looked up in
7858  * \param name_space the type namespace
7859  * \param name the type short name.
7860  *
7861  * Obtains a \c MonoClass with a given namespace and a given name which
7862  * is located in the given \c MonoImage.
7863  *
7864  * To reference nested classes, use the "/" character as a separator.
7865  * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7866  * inside \c Foo, like this: "class Foo { class Bar {} }".
7867  */
7868 MonoClass *
7869 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7870 {
7871         MonoError error;
7872         MonoClass *klass;
7873
7874         klass = mono_class_from_name_checked (image, name_space, name, &error);
7875         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7876
7877         return klass;
7878 }
7879
7880 /**
7881  * mono_class_load_from_name:
7882  * \param image The MonoImage where the type is looked up in
7883  * \param name_space the type namespace
7884  * \param name the type short name.
7885  *
7886  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7887  * This function should be used by the runtime for critical types to which there's no way to recover but crash
7888  * If they are missing. Thing of System.Object or System.String.
7889  */
7890 MonoClass *
7891 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7892 {
7893         MonoError error;
7894         MonoClass *klass;
7895
7896         klass = mono_class_from_name_checked (image, name_space, name, &error);
7897         if (!klass)
7898                 g_error ("Runtime critical type %s.%s not found", name_space, name);
7899         if (!mono_error_ok (&error))
7900                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7901         return klass;
7902 }
7903
7904 /**
7905  * mono_class_try_load_from_name:
7906  * \param image The MonoImage where the type is looked up in
7907  * \param name_space the type namespace
7908  * \param name the type short name.
7909  *
7910  * This function tries to load a type, returning the class was found or NULL otherwise.
7911  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7912  *
7913  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7914  * a type that we would otherwise assume to be available but was not due some error.
7915  *
7916  */
7917 MonoClass*
7918 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7919 {
7920         MonoError error;
7921         MonoClass *klass;
7922
7923         klass = mono_class_from_name_checked (image, name_space, name, &error);
7924         if (!mono_error_ok (&error))
7925                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7926         return klass;
7927 }
7928
7929
7930 /**
7931  * mono_class_is_subclass_of:
7932  * \param klass class to probe if it is a subclass of another one
7933  * \param klassc the class we suspect is the base class
7934  * \param check_interfaces whether we should perform interface checks
7935  *
7936  * This method determines whether \p klass is a subclass of \p klassc.
7937  *
7938  * If the \p check_interfaces flag is set, then if \p klassc is an interface
7939  * this method return TRUE if the \p klass implements the interface or
7940  * if \p klass is an interface, if one of its base classes is \p klass.
7941  *
7942  * If \p check_interfaces is false, then if \p klass is not an interface,
7943  * it returns TRUE if the \p klass is a subclass of \p klassc.
7944  *
7945  * if \p klass is an interface and \p klassc is \c System.Object, then this function
7946  * returns TRUE.
7947  *
7948  */
7949 gboolean
7950 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
7951                            gboolean check_interfaces)
7952 {
7953         /* FIXME test for interfaces with variant generic arguments */
7954         mono_class_init (klass);
7955         mono_class_init (klassc);
7956         
7957         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7958                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7959                         return TRUE;
7960         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7961                 int i;
7962
7963                 for (i = 0; i < klass->interface_count; i ++) {
7964                         MonoClass *ic =  klass->interfaces [i];
7965                         if (ic == klassc)
7966                                 return TRUE;
7967                 }
7968         } else {
7969                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7970                         return TRUE;
7971         }
7972
7973         /* 
7974          * MS.NET thinks interfaces are a subclass of Object, so we think it as
7975          * well.
7976          */
7977         if (klassc == mono_defaults.object_class)
7978                 return TRUE;
7979
7980         return FALSE;
7981 }
7982
7983 static gboolean
7984 mono_type_is_generic_argument (MonoType *type)
7985 {
7986         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7987 }
7988
7989 gboolean
7990 mono_class_has_variant_generic_params (MonoClass *klass)
7991 {
7992         int i;
7993         MonoGenericContainer *container;
7994
7995         if (!mono_class_is_ginst (klass))
7996                 return FALSE;
7997
7998         container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7999
8000         for (i = 0; i < container->type_argc; ++i)
8001                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8002                         return TRUE;
8003
8004         return FALSE;
8005 }
8006
8007 static gboolean
8008 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8009 {
8010         if (target == candidate)
8011                 return TRUE;
8012
8013         if (check_for_reference_conv &&
8014                 mono_type_is_generic_argument (&target->byval_arg) &&
8015                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8016                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8017                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8018
8019                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8020                         return FALSE;
8021         }
8022         if (!mono_class_is_assignable_from (target, candidate))
8023                 return FALSE;
8024         return TRUE;
8025 }
8026
8027 /**
8028  * @container the generic container from the GTD
8029  * @klass: the class to be assigned to
8030  * @oklass: the source class
8031  * 
8032  * Both @klass and @oklass must be instances of the same generic interface.
8033  *
8034  * Returns: TRUE if @klass can be assigned to a @klass variable
8035  */
8036 gboolean
8037 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8038 {
8039         int j;
8040         MonoType **klass_argv, **oklass_argv;
8041         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8042         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8043
8044         if (klass == oklass)
8045                 return TRUE;
8046
8047         /*Viable candidates are instances of the same generic interface*/
8048         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8049                 return FALSE;
8050
8051         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8052         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8053
8054         for (j = 0; j < container->type_argc; ++j) {
8055                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8056                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8057
8058                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8059                         return FALSE;
8060
8061                 /*
8062                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8063                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8064                  */
8065                 if (param1_class != param2_class) {
8066                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8067                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8068                                         return FALSE;
8069                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8070                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8071                                         return FALSE;
8072                         } else
8073                                 return FALSE;
8074                 }
8075         }
8076         return TRUE;
8077 }
8078
8079 static gboolean
8080 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8081 {
8082         MonoGenericParam *gparam, *ogparam;
8083         MonoGenericParamInfo *tinfo, *cinfo;
8084         MonoClass **candidate_class;
8085         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8086         int tmask, cmask;
8087
8088         if (target == candidate)
8089                 return TRUE;
8090         if (target->byval_arg.type != candidate->byval_arg.type)
8091                 return FALSE;
8092
8093         gparam = target->byval_arg.data.generic_param;
8094         ogparam = candidate->byval_arg.data.generic_param;
8095         tinfo = mono_generic_param_info (gparam);
8096         cinfo = mono_generic_param_info (ogparam);
8097
8098         class_constraint_satisfied = FALSE;
8099         valuetype_constraint_satisfied = FALSE;
8100
8101         /*candidate must have a super set of target's special constraints*/
8102         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8103         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8104
8105         if (cinfo->constraints) {
8106                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8107                         MonoClass *cc = *candidate_class;
8108
8109                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8110                                 class_constraint_satisfied = TRUE;
8111                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8112                                 valuetype_constraint_satisfied = TRUE;
8113                 }
8114         }
8115         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8116         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8117
8118         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8119                 return FALSE;
8120         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8121                 return FALSE;
8122         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8123                 valuetype_constraint_satisfied)) {
8124                 return FALSE;
8125         }
8126
8127
8128         /*candidate type constraints must be a superset of target's*/
8129         if (tinfo->constraints) {
8130                 MonoClass **target_class;
8131                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8132                         MonoClass *tc = *target_class;
8133
8134                         /*
8135                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8136                          * check it's constraints since it satisfy the constraint by itself.
8137                          */
8138                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8139                                 continue;
8140
8141                         if (!cinfo->constraints)
8142                                 return FALSE;
8143
8144                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8145                                 MonoClass *cc = *candidate_class;
8146
8147                                 if (mono_class_is_assignable_from (tc, cc))
8148                                         break;
8149
8150                                 /*
8151                                  * This happens when we have the following:
8152                                  *
8153                                  * Bar<K> where K : IFace
8154                                  * Foo<T, U> where T : U where U : IFace
8155                                  *      ...
8156                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8157                                  *
8158                                  */
8159                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8160                                         if (mono_gparam_is_assignable_from (target, cc))
8161                                                 break;
8162                                 }
8163                         }
8164                         if (!*candidate_class)
8165                                 return FALSE;
8166                 }
8167         }
8168
8169         /*candidate itself must have a constraint that satisfy target*/
8170         if (cinfo->constraints) {
8171                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8172                         MonoClass *cc = *candidate_class;
8173                         if (mono_class_is_assignable_from (target, cc))
8174                                 return TRUE;
8175                 }
8176         }
8177         return FALSE;
8178 }
8179
8180 /**
8181  * mono_class_is_assignable_from:
8182  * \param klass the class to be assigned to
8183  * \param oklass the source class
8184  *
8185  * \returns TRUE if an instance of class \p oklass can be assigned to an
8186  * instance of class \p klass
8187  */
8188 gboolean
8189 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8190 {
8191         MonoError error;
8192         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8193         if (!klass->inited)
8194                 mono_class_init (klass);
8195
8196         if (!oklass->inited)
8197                 mono_class_init (oklass);
8198
8199         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8200                 return FALSE;
8201
8202         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8203                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8204                         return FALSE;
8205                 return mono_gparam_is_assignable_from (klass, oklass);
8206         }
8207
8208         if (MONO_CLASS_IS_INTERFACE (klass)) {
8209                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8210                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8211                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8212                         int i;
8213
8214                         if (constraints) {
8215                                 for (i = 0; constraints [i]; ++i) {
8216                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8217                                                 return TRUE;
8218                                 }
8219                         }
8220
8221                         return FALSE;
8222                 }
8223
8224                 /* interface_offsets might not be set for dynamic classes */
8225                 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8226                         /* 
8227                          * oklass might be a generic type parameter but they have 
8228                          * interface_offsets set.
8229                          */
8230                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8231                         if (!is_ok (&error)) {
8232                                 mono_error_cleanup (&error);
8233                                 return FALSE;
8234                         }
8235                         return result;
8236                 }
8237                 if (!oklass->interface_bitmap)
8238                         /* Happens with generic instances of not-yet created dynamic types */
8239                         return FALSE;
8240                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8241                         return TRUE;
8242
8243                 if (klass->is_array_special_interface && oklass->rank == 1) {
8244                         //XXX we could offset this by having the cast target computed at JIT time
8245                         //XXX we could go even further and emit a wrapper that would do the extra type check
8246                         MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8247                         MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8248
8249                         // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
8250                         // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8251                         if (iface_klass->valuetype)
8252                                 iface_klass = iface_klass->cast_class;
8253
8254                         //array covariant casts only operates on scalar to scalar
8255                         //This is so int[] can't be casted to IComparable<int>[]
8256                         if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8257                                 return TRUE;
8258                 }
8259
8260                 if (mono_class_has_variant_generic_params (klass)) {
8261                         int i;
8262                         mono_class_setup_interfaces (oklass, &error);
8263                         if (!mono_error_ok (&error)) {
8264                                 mono_error_cleanup (&error);
8265                                 return FALSE;
8266                         }
8267
8268                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8269                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8270                                 MonoClass *iface = oklass->interfaces_packed [i];
8271
8272                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8273                                         return TRUE;
8274                         }
8275                 }
8276                 return FALSE;
8277         } else if (klass->delegate) {
8278                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8279                         return TRUE;
8280         }else if (klass->rank) {
8281                 MonoClass *eclass, *eoclass;
8282
8283                 if (oklass->rank != klass->rank)
8284                         return FALSE;
8285
8286                 /* vectors vs. one dimensional arrays */
8287                 if (oklass->byval_arg.type != klass->byval_arg.type)
8288                         return FALSE;
8289
8290                 eclass = klass->cast_class;
8291                 eoclass = oklass->cast_class;
8292
8293                 /* 
8294                  * a is b does not imply a[] is b[] when a is a valuetype, and
8295                  * b is a reference type.
8296                  */
8297
8298                 if (eoclass->valuetype) {
8299                         if ((eclass == mono_defaults.enum_class) || 
8300                                 (eclass == mono_defaults.enum_class->parent) ||
8301                                 (eclass == mono_defaults.object_class))
8302                                 return FALSE;
8303                 }
8304
8305                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8306         } else if (mono_class_is_nullable (klass)) {
8307                 if (mono_class_is_nullable (oklass))
8308                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8309                 else
8310                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8311         } else if (klass == mono_defaults.object_class)
8312                 return TRUE;
8313
8314         return mono_class_has_parent (oklass, klass);
8315 }       
8316
8317 /*Check if @oklass is variant compatible with @klass.*/
8318 static gboolean
8319 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8320 {
8321         int j;
8322         MonoType **klass_argv, **oklass_argv;
8323         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8324         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8325
8326         /*Viable candidates are instances of the same generic interface*/
8327         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8328                 return FALSE;
8329
8330         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8331         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8332
8333         for (j = 0; j < container->type_argc; ++j) {
8334                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8335                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8336
8337                 if (param1_class->valuetype != param2_class->valuetype)
8338                         return FALSE;
8339
8340                 /*
8341                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8342                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8343                  */
8344                 if (param1_class != param2_class) {
8345                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8346                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8347                                         return FALSE;
8348                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8349                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8350                                         return FALSE;
8351                         } else
8352                                 return FALSE;
8353                 }
8354         }
8355         return TRUE;
8356 }
8357 /*Check if @candidate implements the interface @target*/
8358 static gboolean
8359 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8360 {
8361         MonoError error;
8362         int i;
8363         gboolean is_variant = mono_class_has_variant_generic_params (target);
8364
8365         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8366                 if (mono_class_is_variant_compatible_slow (target, candidate))
8367                         return TRUE;
8368         }
8369
8370         do {
8371                 if (candidate == target)
8372                         return TRUE;
8373
8374                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8375                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8376                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8377                         int j;
8378                         if (tb && tb->interfaces) {
8379                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8380                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8381                                         MonoClass *iface_class;
8382
8383                                         /* we can't realize the type here since it can do pretty much anything. */
8384                                         if (!iface->type)
8385                                                 continue;
8386                                         iface_class = mono_class_from_mono_type (iface->type);
8387                                         if (iface_class == target)
8388                                                 return TRUE;
8389                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8390                                                 return TRUE;
8391                                         if (mono_class_implement_interface_slow (target, iface_class))
8392                                                 return TRUE;
8393                                 }
8394                         }
8395                 } else {
8396                         /*setup_interfaces don't mono_class_init anything*/
8397                         /*FIXME this doesn't handle primitive type arrays.
8398                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8399                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8400                         */
8401                         mono_class_setup_interfaces (candidate, &error);
8402                         if (!mono_error_ok (&error)) {
8403                                 mono_error_cleanup (&error);
8404                                 return FALSE;
8405                         }
8406
8407                         for (i = 0; i < candidate->interface_count; ++i) {
8408                                 if (candidate->interfaces [i] == target)
8409                                         return TRUE;
8410                                 
8411                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8412                                         return TRUE;
8413
8414                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8415                                         return TRUE;
8416                         }
8417                 }
8418                 candidate = candidate->parent;
8419         } while (candidate);
8420
8421         return FALSE;
8422 }
8423
8424 /*
8425  * Check if @oklass can be assigned to @klass.
8426  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8427  */
8428 gboolean
8429 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8430 {
8431         if (candidate == target)
8432                 return TRUE;
8433         if (target == mono_defaults.object_class)
8434                 return TRUE;
8435
8436         if (mono_class_has_parent (candidate, target))
8437                 return TRUE;
8438
8439         /*If target is not an interface there is no need to check them.*/
8440         if (MONO_CLASS_IS_INTERFACE (target))
8441                 return mono_class_implement_interface_slow (target, candidate);
8442
8443         if (target->delegate && mono_class_has_variant_generic_params (target))
8444                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8445
8446         if (target->rank) {
8447                 MonoClass *eclass, *eoclass;
8448
8449                 if (target->rank != candidate->rank)
8450                         return FALSE;
8451
8452                 /* vectors vs. one dimensional arrays */
8453                 if (target->byval_arg.type != candidate->byval_arg.type)
8454                         return FALSE;
8455
8456                 eclass = target->cast_class;
8457                 eoclass = candidate->cast_class;
8458
8459                 /*
8460                  * a is b does not imply a[] is b[] when a is a valuetype, and
8461                  * b is a reference type.
8462                  */
8463
8464                 if (eoclass->valuetype) {
8465                         if ((eclass == mono_defaults.enum_class) ||
8466                                 (eclass == mono_defaults.enum_class->parent) ||
8467                                 (eclass == mono_defaults.object_class))
8468                                 return FALSE;
8469                 }
8470
8471                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8472         }
8473         /*FIXME properly handle nullables */
8474         /*FIXME properly handle (M)VAR */
8475         return FALSE;
8476 }
8477
8478 /**
8479  * mono_class_get_cctor:
8480  * \param klass A MonoClass pointer
8481  *
8482  * \returns The static constructor of \p klass if it exists, NULL otherwise.
8483  */
8484 MonoMethod*
8485 mono_class_get_cctor (MonoClass *klass)
8486 {
8487         MonoCachedClassInfo cached_info;
8488
8489         if (image_is_dynamic (klass->image)) {
8490                 /* 
8491                  * has_cctor is not set for these classes because mono_class_init () is
8492                  * not run for them.
8493                  */
8494                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8495         }
8496
8497         mono_class_init (klass);
8498
8499         if (!klass->has_cctor)
8500                 return NULL;
8501
8502         if (mono_class_is_ginst (klass) && !klass->methods)
8503                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8504
8505         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8506                 MonoError error;
8507                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8508                 if (!mono_error_ok (&error))
8509                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8510                 return result;
8511         }
8512
8513         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8514 }
8515
8516 /**
8517  * mono_class_get_finalizer:
8518  * \param klass: The MonoClass pointer
8519  *
8520  * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8521  */
8522 MonoMethod*
8523 mono_class_get_finalizer (MonoClass *klass)
8524 {
8525         MonoCachedClassInfo cached_info;
8526
8527         if (!klass->inited)
8528                 mono_class_init (klass);
8529         if (!mono_class_has_finalizer (klass))
8530                 return NULL;
8531
8532         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8533                 MonoError error;
8534                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8535                 if (!mono_error_ok (&error))
8536                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8537                 return result;
8538         }else {
8539                 mono_class_setup_vtable (klass);
8540                 return klass->vtable [finalize_slot];
8541         }
8542 }
8543
8544 /**
8545  * mono_class_needs_cctor_run:
8546  * \param klass the MonoClass pointer
8547  * \param caller a MonoMethod describing the caller
8548  *
8549  * Determines whenever the class has a static constructor and whenever it
8550  * needs to be called when executing CALLER.
8551  */
8552 gboolean
8553 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8554 {
8555         MonoMethod *method;
8556
8557         method = mono_class_get_cctor (klass);
8558         if (method)
8559                 return (method == caller) ? FALSE : TRUE;
8560         else
8561                 return FALSE;
8562 }
8563
8564 /**
8565  * mono_class_array_element_size:
8566  * \param klass
8567  *
8568  * \returns The number of bytes an element of type \p klass uses when stored into an array.
8569  */
8570 gint32
8571 mono_class_array_element_size (MonoClass *klass)
8572 {
8573         MonoType *type = &klass->byval_arg;
8574         
8575 handle_enum:
8576         switch (type->type) {
8577         case MONO_TYPE_I1:
8578         case MONO_TYPE_U1:
8579         case MONO_TYPE_BOOLEAN:
8580                 return 1;
8581         case MONO_TYPE_I2:
8582         case MONO_TYPE_U2:
8583         case MONO_TYPE_CHAR:
8584                 return 2;
8585         case MONO_TYPE_I4:
8586         case MONO_TYPE_U4:
8587         case MONO_TYPE_R4:
8588                 return 4;
8589         case MONO_TYPE_I:
8590         case MONO_TYPE_U:
8591         case MONO_TYPE_PTR:
8592         case MONO_TYPE_CLASS:
8593         case MONO_TYPE_STRING:
8594         case MONO_TYPE_OBJECT:
8595         case MONO_TYPE_SZARRAY:
8596         case MONO_TYPE_ARRAY: 
8597                 return sizeof (gpointer);
8598         case MONO_TYPE_I8:
8599         case MONO_TYPE_U8:
8600         case MONO_TYPE_R8:
8601                 return 8;
8602         case MONO_TYPE_VALUETYPE:
8603                 if (type->data.klass->enumtype) {
8604                         type = mono_class_enum_basetype (type->data.klass);
8605                         klass = klass->element_class;
8606                         goto handle_enum;
8607                 }
8608                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8609         case MONO_TYPE_GENERICINST:
8610                 type = &type->data.generic_class->container_class->byval_arg;
8611                 goto handle_enum;
8612         case MONO_TYPE_VAR:
8613         case MONO_TYPE_MVAR: {
8614                 int align;
8615
8616                 return mono_type_size (type, &align);
8617         }
8618         case MONO_TYPE_VOID:
8619                 return 0;
8620                 
8621         default:
8622                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8623         }
8624         return -1;
8625 }
8626
8627 /**
8628  * mono_array_element_size:
8629  * \param ac pointer to a \c MonoArrayClass
8630  *
8631  * \returns The size of single array element.
8632  */
8633 gint32
8634 mono_array_element_size (MonoClass *ac)
8635 {
8636         g_assert (ac->rank);
8637         return ac->sizes.element_size;
8638 }
8639
8640 /**
8641  * mono_ldtoken:
8642  */
8643 gpointer
8644 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8645               MonoGenericContext *context)
8646 {
8647         MonoError error;
8648         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8649         g_assert (mono_error_ok (&error));
8650         return res;
8651 }
8652
8653 gpointer
8654 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8655               MonoGenericContext *context, MonoError *error)
8656 {
8657         error_init (error);
8658
8659         if (image_is_dynamic (image)) {
8660                 MonoClass *tmp_handle_class;
8661                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8662
8663                 mono_error_assert_ok (error);
8664                 g_assert (tmp_handle_class);
8665                 if (handle_class)
8666                         *handle_class = tmp_handle_class;
8667
8668                 if (tmp_handle_class == mono_defaults.typehandle_class)
8669                         return &((MonoClass*)obj)->byval_arg;
8670                 else
8671                         return obj;
8672         }
8673
8674         switch (token & 0xff000000) {
8675         case MONO_TOKEN_TYPE_DEF:
8676         case MONO_TOKEN_TYPE_REF:
8677         case MONO_TOKEN_TYPE_SPEC: {
8678                 MonoType *type;
8679                 if (handle_class)
8680                         *handle_class = mono_defaults.typehandle_class;
8681                 type = mono_type_get_checked (image, token, context, error);
8682                 if (!type)
8683                         return NULL;
8684
8685                 mono_class_init (mono_class_from_mono_type (type));
8686                 /* We return a MonoType* as handle */
8687                 return type;
8688         }
8689         case MONO_TOKEN_FIELD_DEF: {
8690                 MonoClass *klass;
8691                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8692                 if (!type) {
8693                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8694                         return NULL;
8695                 }
8696                 if (handle_class)
8697                         *handle_class = mono_defaults.fieldhandle_class;
8698                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8699                 if (!klass)
8700                         return NULL;
8701
8702                 mono_class_init (klass);
8703                 return mono_class_get_field (klass, token);
8704         }
8705         case MONO_TOKEN_METHOD_DEF:
8706         case MONO_TOKEN_METHOD_SPEC: {
8707                 MonoMethod *meth;
8708                 meth = mono_get_method_checked (image, token, NULL, context, error);
8709                 if (handle_class)
8710                         *handle_class = mono_defaults.methodhandle_class;
8711                 if (!meth)
8712                         return NULL;
8713
8714                 return meth;
8715         }
8716         case MONO_TOKEN_MEMBER_REF: {
8717                 guint32 cols [MONO_MEMBERREF_SIZE];
8718                 const char *sig;
8719                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8720                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8721                 mono_metadata_decode_blob_size (sig, &sig);
8722                 if (*sig == 0x6) { /* it's a field */
8723                         MonoClass *klass;
8724                         MonoClassField *field;
8725                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8726                         if (handle_class)
8727                                 *handle_class = mono_defaults.fieldhandle_class;
8728                         return field;
8729                 } else {
8730                         MonoMethod *meth;
8731                         meth = mono_get_method_checked (image, token, NULL, context, error);
8732                         if (handle_class)
8733                                 *handle_class = mono_defaults.methodhandle_class;
8734                         return meth;
8735                 }
8736         }
8737         default:
8738                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8739         }
8740         return NULL;
8741 }
8742
8743 gpointer
8744 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8745 {
8746         MonoClass *handle_class;
8747         error_init (error);
8748         return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8749 }
8750
8751 gpointer
8752 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8753 {
8754         return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8755 }
8756
8757 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8758
8759 void
8760 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8761 {
8762         get_cached_class_info = func;
8763 }
8764
8765 static gboolean
8766 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8767 {
8768         if (!get_cached_class_info)
8769                 return FALSE;
8770         else
8771                 return get_cached_class_info (klass, res);
8772 }
8773
8774 void
8775 mono_install_get_class_from_name (MonoGetClassFromName func)
8776 {
8777         get_class_from_name = func;
8778 }
8779
8780 /**
8781  * mono_class_get_image:
8782  *
8783  * Use this method to get the \c MonoImage* where this class came from.
8784  *
8785  * \returns The image where this class is defined.
8786  */
8787 MonoImage*
8788 mono_class_get_image (MonoClass *klass)
8789 {
8790         return klass->image;
8791 }
8792
8793 /**
8794  * mono_class_get_element_class:
8795  * \param klass the \c MonoClass to act on
8796  *
8797  * Use this function to get the element class of an array.
8798  *
8799  * \returns The element class of an array.
8800  */
8801 MonoClass*
8802 mono_class_get_element_class (MonoClass *klass)
8803 {
8804         return klass->element_class;
8805 }
8806
8807 /**
8808  * mono_class_is_valuetype:
8809  * \param klass the \c MonoClass to act on
8810  *
8811  * Use this method to determine if the provided \c MonoClass* represents a value type,
8812  * or a reference type.
8813  *
8814  * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8815  */
8816 gboolean
8817 mono_class_is_valuetype (MonoClass *klass)
8818 {
8819         return klass->valuetype;
8820 }
8821
8822 /**
8823  * mono_class_is_enum:
8824  * \param klass the \c MonoClass to act on
8825  *
8826  * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8827  *
8828  * \returns TRUE if the \c MonoClass represents an enumeration.
8829  */
8830 gboolean
8831 mono_class_is_enum (MonoClass *klass)
8832 {
8833         return klass->enumtype;
8834 }
8835
8836 /**
8837  * mono_class_enum_basetype:
8838  * \param klass the \c MonoClass to act on
8839  *
8840  * Use this function to get the underlying type for an enumeration value.
8841  * 
8842  * \returns The underlying type representation for an enumeration.
8843  */
8844 MonoType*
8845 mono_class_enum_basetype (MonoClass *klass)
8846 {
8847         if (klass->element_class == klass)
8848                 /* SRE or broken types */
8849                 return NULL;
8850         else
8851                 return &klass->element_class->byval_arg;
8852 }
8853
8854 /**
8855  * mono_class_get_parent
8856  * \param klass the \c MonoClass to act on
8857  *
8858  * \returns The parent class for this class.
8859  */
8860 MonoClass*
8861 mono_class_get_parent (MonoClass *klass)
8862 {
8863         return klass->parent;
8864 }
8865
8866 /**
8867  * mono_class_get_nesting_type:
8868  * \param klass the \c MonoClass to act on
8869  *
8870  * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8871  *
8872  * If the return is NULL, this indicates that this class is not nested.
8873  *
8874  * \returns The container type where this type is nested or NULL if this type is not a nested type.
8875  */
8876 MonoClass*
8877 mono_class_get_nesting_type (MonoClass *klass)
8878 {
8879         return klass->nested_in;
8880 }
8881
8882 /**
8883  * mono_class_get_rank:
8884  * \param klass the MonoClass to act on
8885  *
8886  * \returns The rank for the array (the number of dimensions).
8887  */
8888 int
8889 mono_class_get_rank (MonoClass *klass)
8890 {
8891         return klass->rank;
8892 }
8893
8894 /**
8895  * mono_class_get_name
8896  * \param klass the \c MonoClass to act on
8897  *
8898  * \returns The name of the class.
8899  */
8900 const char*
8901 mono_class_get_name (MonoClass *klass)
8902 {
8903         return klass->name;
8904 }
8905
8906 /**
8907  * mono_class_get_namespace:
8908  * \param klass the \c MonoClass to act on
8909  *
8910  * \returns The namespace of the class.
8911  */
8912 const char*
8913 mono_class_get_namespace (MonoClass *klass)
8914 {
8915         return klass->name_space;
8916 }
8917
8918 /**
8919  * mono_class_get_type:
8920  * \param klass the \c MonoClass to act on
8921  *
8922  * This method returns the internal \c MonoType representation for the class.
8923  *
8924  * \returns The \c MonoType from the class.
8925  */
8926 MonoType*
8927 mono_class_get_type (MonoClass *klass)
8928 {
8929         return &klass->byval_arg;
8930 }
8931
8932 /**
8933  * mono_class_get_type_token:
8934  * \param klass the \c MonoClass to act on
8935  *
8936  * This method returns type token for the class.
8937  *
8938  * \returns The type token for the class.
8939  */
8940 guint32
8941 mono_class_get_type_token (MonoClass *klass)
8942 {
8943   return klass->type_token;
8944 }
8945
8946 /**
8947  * mono_class_get_byref_type:
8948  * \param klass the \c MonoClass to act on
8949  *
8950  * 
8951  */
8952 MonoType*
8953 mono_class_get_byref_type (MonoClass *klass)
8954 {
8955         return &klass->this_arg;
8956 }
8957
8958 /**
8959  * mono_class_num_fields:
8960  * \param klass the \c MonoClass to act on
8961  *
8962  * \returns The number of static and instance fields in the class.
8963  */
8964 int
8965 mono_class_num_fields (MonoClass *klass)
8966 {
8967         return mono_class_get_field_count (klass);
8968 }
8969
8970 /**
8971  * mono_class_num_methods:
8972  * \param klass the \c MonoClass to act on
8973  *
8974  * \returns The number of methods in the class.
8975  */
8976 int
8977 mono_class_num_methods (MonoClass *klass)
8978 {
8979         return mono_class_get_method_count (klass);
8980 }
8981
8982 /**
8983  * mono_class_num_properties
8984  * \param klass the \c MonoClass to act on
8985  *
8986  * \returns The number of properties in the class.
8987  */
8988 int
8989 mono_class_num_properties (MonoClass *klass)
8990 {
8991         mono_class_setup_properties (klass);
8992
8993         return mono_class_get_property_info (klass)->count;
8994 }
8995
8996 /**
8997  * mono_class_num_events:
8998  * \param klass the \c MonoClass to act on
8999  *
9000  * \returns The number of events in the class.
9001  */
9002 int
9003 mono_class_num_events (MonoClass *klass)
9004 {
9005         mono_class_setup_events (klass);
9006
9007         return mono_class_get_event_info (klass)->count;
9008 }
9009
9010 /**
9011  * mono_class_get_fields:
9012  * \param klass the \c MonoClass to act on
9013  *
9014  * This routine is an iterator routine for retrieving the fields in a class.
9015  *
9016  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9017  * iterate over all of the elements.  When no more values are
9018  * available, the return value is NULL.
9019  *
9020  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9021  */
9022 MonoClassField*
9023 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9024 {
9025         MonoClassField* field;
9026         if (!iter)
9027                 return NULL;
9028         if (!*iter) {
9029                 mono_class_setup_fields (klass);
9030                 if (mono_class_has_failure (klass))
9031                         return NULL;
9032                 /* start from the first */
9033                 if (mono_class_get_field_count (klass)) {
9034                         *iter = &klass->fields [0];
9035                         return &klass->fields [0];
9036                 } else {
9037                         /* no fields */
9038                         return NULL;
9039                 }
9040         }
9041         field = (MonoClassField *)*iter;
9042         field++;
9043         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9044                 *iter = field;
9045                 return field;
9046         }
9047         return NULL;
9048 }
9049
9050 /**
9051  * mono_class_get_methods:
9052  * \param klass the \c MonoClass to act on
9053  *
9054  * This routine is an iterator routine for retrieving the fields in a class.
9055  *
9056  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9057  * iterate over all of the elements.  When no more values are
9058  * available, the return value is NULL.
9059  *
9060  * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9061  */
9062 MonoMethod*
9063 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9064 {
9065         MonoMethod** method;
9066         if (!iter)
9067                 return NULL;
9068         if (!*iter) {
9069                 mono_class_setup_methods (klass);
9070
9071                 /*
9072                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9073                  * FIXME we should better report this error to the caller
9074                  */
9075                 if (!klass->methods)
9076                         return NULL;
9077                 /* start from the first */
9078                 if (mono_class_get_method_count (klass)) {
9079                         *iter = &klass->methods [0];
9080                         return klass->methods [0];
9081                 } else {
9082                         /* no method */
9083                         return NULL;
9084                 }
9085         }
9086         method = (MonoMethod **)*iter;
9087         method++;
9088         if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9089                 *iter = method;
9090                 return *method;
9091         }
9092         return NULL;
9093 }
9094
9095 /*
9096  * mono_class_get_virtual_methods:
9097  *
9098  *   Iterate over the virtual methods of KLASS.
9099  *
9100  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9101  */
9102 static MonoMethod*
9103 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9104 {
9105         MonoMethod** method;
9106         if (!iter)
9107                 return NULL;
9108         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9109                 if (!*iter) {
9110                         mono_class_setup_methods (klass);
9111                         /*
9112                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9113                          * FIXME we should better report this error to the caller
9114                          */
9115                         if (!klass->methods)
9116                                 return NULL;
9117                         /* start from the first */
9118                         method = &klass->methods [0];
9119                 } else {
9120                         method = (MonoMethod **)*iter;
9121                         method++;
9122                 }
9123                 int mcount = mono_class_get_method_count (klass);
9124                 while (method < &klass->methods [mcount]) {
9125                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9126                                 break;
9127                         method ++;
9128                 }
9129                 if (method < &klass->methods [mcount]) {
9130                         *iter = method;
9131                         return *method;
9132                 } else {
9133                         return NULL;
9134                 }
9135         } else {
9136                 /* Search directly in metadata to avoid calling setup_methods () */
9137                 MonoMethod *res = NULL;
9138                 int i, start_index;
9139
9140                 if (!*iter) {
9141                         start_index = 0;
9142                 } else {
9143                         start_index = GPOINTER_TO_UINT (*iter);
9144                 }
9145
9146                 int first_idx = mono_class_get_first_method_idx (klass);
9147                 int mcount = mono_class_get_method_count (klass);
9148                 for (i = start_index; i < mcount; ++i) {
9149                         guint32 flags;
9150
9151                         /* first_idx points into the methodptr table */
9152                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9153
9154                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9155                                 break;
9156                 }
9157
9158                 if (i < mcount) {
9159                         MonoError error;
9160                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9161                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9162
9163                         /* Add 1 here so the if (*iter) check fails */
9164                         *iter = GUINT_TO_POINTER (i + 1);
9165                         return res;
9166                 } else {
9167                         return NULL;
9168                 }
9169         }
9170 }
9171
9172 /**
9173  * mono_class_get_properties:
9174  * \param klass the \c MonoClass to act on
9175  *
9176  * This routine is an iterator routine for retrieving the properties in a class.
9177  *
9178  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9179  * iterate over all of the elements.  When no more values are
9180  * available, the return value is NULL.
9181  *
9182  * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9183  */
9184 MonoProperty*
9185 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9186 {
9187         MonoProperty* property;
9188         if (!iter)
9189                 return NULL;
9190         if (!*iter) {
9191                 mono_class_setup_properties (klass);
9192                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9193                 /* start from the first */
9194                 if (info->count) {
9195                         *iter = &info->properties [0];
9196                         return (MonoProperty *)*iter;
9197                 } else {
9198                         /* no fields */
9199                         return NULL;
9200                 }
9201         }
9202         property = (MonoProperty *)*iter;
9203         property++;
9204         MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9205         if (property < &info->properties [info->count]) {
9206                 *iter = property;
9207                 return (MonoProperty *)*iter;
9208         }
9209         return NULL;
9210 }
9211
9212 /**
9213  * mono_class_get_events:
9214  * \param klass the \c MonoClass to act on
9215  *
9216  * This routine is an iterator routine for retrieving the properties in a class.
9217  *
9218  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9219  * iterate over all of the elements.  When no more values are
9220  * available, the return value is NULL.
9221  *
9222  * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9223  */
9224 MonoEvent*
9225 mono_class_get_events (MonoClass* klass, gpointer *iter)
9226 {
9227         MonoEvent* event;
9228         if (!iter)
9229                 return NULL;
9230         if (!*iter) {
9231                 mono_class_setup_events (klass);
9232                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9233                 /* start from the first */
9234                 if (info->count) {
9235                         *iter = &info->events [0];
9236                         return (MonoEvent *)*iter;
9237                 } else {
9238                         /* no fields */
9239                         return NULL;
9240                 }
9241         }
9242         event = (MonoEvent *)*iter;
9243         event++;
9244         MonoClassEventInfo *info = mono_class_get_event_info (klass);
9245         if (event < &info->events [info->count]) {
9246                 *iter = event;
9247                 return (MonoEvent *)*iter;
9248         }
9249         return NULL;
9250 }
9251
9252 /**
9253  * mono_class_get_interfaces
9254  * \param klass the \c MonoClass to act on
9255  *
9256  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9257  *
9258  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9259  * iterate over all of the elements.  When no more values are
9260  * available, the return value is NULL.
9261  *
9262  * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9263  */
9264 MonoClass*
9265 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9266 {
9267         MonoError error;
9268         MonoClass** iface;
9269         if (!iter)
9270                 return NULL;
9271         if (!*iter) {
9272                 if (!klass->inited)
9273                         mono_class_init (klass);
9274                 if (!klass->interfaces_inited) {
9275                         mono_class_setup_interfaces (klass, &error);
9276                         if (!mono_error_ok (&error)) {
9277                                 mono_error_cleanup (&error);
9278                                 return NULL;
9279                         }
9280                 }
9281                 /* start from the first */
9282                 if (klass->interface_count) {
9283                         *iter = &klass->interfaces [0];
9284                         return klass->interfaces [0];
9285                 } else {
9286                         /* no interface */
9287                         return NULL;
9288                 }
9289         }
9290         iface = (MonoClass **)*iter;
9291         iface++;
9292         if (iface < &klass->interfaces [klass->interface_count]) {
9293                 *iter = iface;
9294                 return *iface;
9295         }
9296         return NULL;
9297 }
9298
9299 static void
9300 setup_nested_types (MonoClass *klass)
9301 {
9302         MonoError error;
9303         GList *classes, *nested_classes, *l;
9304         int i;
9305
9306         if (klass->nested_classes_inited)
9307                 return;
9308
9309         if (!klass->type_token) {
9310                 mono_loader_lock ();
9311                 klass->nested_classes_inited = TRUE;
9312                 mono_loader_unlock ();
9313                 return;
9314         }
9315
9316         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9317         classes = NULL;
9318         while (i) {
9319                 MonoClass* nclass;
9320                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9321                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9322                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9323                 if (!mono_error_ok (&error)) {
9324                         /*FIXME don't swallow the error message*/
9325                         mono_error_cleanup (&error);
9326
9327                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9328                         continue;
9329                 }
9330
9331                 classes = g_list_prepend (classes, nclass);
9332
9333                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9334         }
9335
9336         nested_classes = NULL;
9337         for (l = classes; l; l = l->next)
9338                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9339         g_list_free (classes);
9340
9341         mono_loader_lock ();
9342         if (!klass->nested_classes_inited) {
9343                 mono_class_set_nested_classes_property (klass, nested_classes);
9344                 mono_memory_barrier ();
9345                 klass->nested_classes_inited = TRUE;
9346         }
9347         mono_loader_unlock ();
9348 }
9349
9350 /**
9351  * mono_class_get_nested_types
9352  * \param klass the \c MonoClass to act on
9353  *
9354  * This routine is an iterator routine for retrieving the nested types of a class.
9355  * This works only if \p klass is non-generic, or a generic type definition.
9356  *
9357  * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9358  * iterate over all of the elements.  When no more values are
9359  * available, the return value is NULL.
9360  *
9361  * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9362  */
9363 MonoClass*
9364 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9365 {
9366         GList *item;
9367
9368         if (!iter)
9369                 return NULL;
9370         if (!klass->nested_classes_inited)
9371                 setup_nested_types (klass);
9372
9373         if (!*iter) {
9374                 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9375                 /* start from the first */
9376                 if (nested_classes) {
9377                         *iter = nested_classes;
9378                         return (MonoClass *)nested_classes->data;
9379                 } else {
9380                         /* no nested types */
9381                         return NULL;
9382                 }
9383         }
9384         item = (GList *)*iter;
9385         item = item->next;
9386         if (item) {
9387                 *iter = item;
9388                 return (MonoClass *)item->data;
9389         }
9390         return NULL;
9391 }
9392
9393
9394 /**
9395  * mono_class_is_delegate
9396  * \param klass the \c MonoClass to act on
9397  *
9398  * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9399  */
9400 mono_bool
9401 mono_class_is_delegate (MonoClass *klass)
9402 {
9403         return klass->delegate;
9404 }
9405
9406 /**
9407  * mono_class_implements_interface
9408  * \param klass The MonoClass to act on
9409  * \param interface The interface to check if \p klass implements.
9410  *
9411  * \returns TRUE if \p klass implements \p interface.
9412  */
9413 mono_bool
9414 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9415 {
9416         return mono_class_is_assignable_from (iface, klass);
9417 }
9418
9419 /**
9420  * mono_field_get_name:
9421  * \param field the \c MonoClassField to act on
9422  *
9423  * \returns The name of the field.
9424  */
9425 const char*
9426 mono_field_get_name (MonoClassField *field)
9427 {
9428         return field->name;
9429 }
9430
9431 /**
9432  * mono_field_get_type:
9433  * \param field the \c MonoClassField to act on
9434  * \returns \c MonoType of the field.
9435  */
9436 MonoType*
9437 mono_field_get_type (MonoClassField *field)
9438 {
9439         MonoError error;
9440         MonoType *type = mono_field_get_type_checked (field, &error);
9441         if (!mono_error_ok (&error)) {
9442                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9443                 mono_error_cleanup (&error);
9444         }
9445         return type;
9446 }
9447
9448
9449 /**
9450  * mono_field_get_type_checked:
9451  * \param field the \c MonoClassField to act on
9452  * \param error used to return any error found while retrieving \p field type
9453  *
9454  * \returns \c MonoType of the field.
9455  */
9456 MonoType*
9457 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9458 {
9459         error_init (error);
9460         if (!field->type)
9461                 mono_field_resolve_type (field, error);
9462         return field->type;
9463 }
9464
9465 /**
9466  * mono_field_get_parent:
9467  * \param field the \c MonoClassField to act on
9468  *
9469  * \returns \c MonoClass where the field was defined.
9470  */
9471 MonoClass*
9472 mono_field_get_parent (MonoClassField *field)
9473 {
9474         return field->parent;
9475 }
9476
9477 /**
9478  * mono_field_get_flags;
9479  * \param field the \c MonoClassField to act on
9480  *
9481  * The metadata flags for a field are encoded using the
9482  * \c FIELD_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9483  *
9484  * \returns The flags for the field.
9485  */
9486 guint32
9487 mono_field_get_flags (MonoClassField *field)
9488 {
9489         if (!field->type)
9490                 return mono_field_resolve_flags (field);
9491         return field->type->attrs;
9492 }
9493
9494 /**
9495  * mono_field_get_offset:
9496  * \param field the \c MonoClassField to act on
9497  *
9498  * \returns The field offset.
9499  */
9500 guint32
9501 mono_field_get_offset (MonoClassField *field)
9502 {
9503         return field->offset;
9504 }
9505
9506 static const char *
9507 mono_field_get_rva (MonoClassField *field)
9508 {
9509         guint32 rva;
9510         int field_index;
9511         MonoClass *klass = field->parent;
9512         MonoFieldDefaultValue *def_values;
9513
9514         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9515
9516         def_values = mono_class_get_field_def_values (klass);
9517         if (!def_values) {
9518                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9519
9520                 mono_class_set_field_def_values (klass, def_values);
9521         }
9522
9523         field_index = mono_field_get_index (field);
9524                 
9525         if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9526                 int first_field_idx = mono_class_get_first_field_idx (klass);
9527                 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9528                 if (!rva)
9529                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9530                 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9531         }
9532
9533         return def_values [field_index].data;
9534 }
9535
9536 /**
9537  * mono_field_get_data:
9538  * \param field the \c MonoClassField to act on
9539  *
9540  * \returns A pointer to the metadata constant value or to the field
9541  * data if it has an RVA flag.
9542  */
9543 const char *
9544 mono_field_get_data (MonoClassField *field)
9545 {
9546         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9547                 MonoTypeEnum def_type;
9548
9549                 return mono_class_get_field_default_value (field, &def_type);
9550         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9551                 return mono_field_get_rva (field);
9552         } else {
9553                 return NULL;
9554         }
9555 }
9556
9557 /**
9558  * mono_property_get_name: 
9559  * \param prop the \c MonoProperty to act on
9560  * \returns The name of the property
9561  */
9562 const char*
9563 mono_property_get_name (MonoProperty *prop)
9564 {
9565         return prop->name;
9566 }
9567
9568 /**
9569  * mono_property_get_set_method
9570  * \param prop the \c MonoProperty to act on.
9571  * \returns The setter method of the property, a \c MonoMethod.
9572  */
9573 MonoMethod*
9574 mono_property_get_set_method (MonoProperty *prop)
9575 {
9576         return prop->set;
9577 }
9578
9579 /**
9580  * mono_property_get_get_method
9581  * \param prop the MonoProperty to act on.
9582  * \returns The getter method of the property (A \c MonoMethod)
9583  */
9584 MonoMethod*
9585 mono_property_get_get_method (MonoProperty *prop)
9586 {
9587         return prop->get;
9588 }
9589
9590 /**
9591  * mono_property_get_parent:
9592  * \param prop the \c MonoProperty to act on.
9593  * \returns The \c MonoClass where the property was defined.
9594  */
9595 MonoClass*
9596 mono_property_get_parent (MonoProperty *prop)
9597 {
9598         return prop->parent;
9599 }
9600
9601 /**
9602  * mono_property_get_flags:
9603  * \param prop the \c MonoProperty to act on.
9604  *
9605  * The metadata flags for a property are encoded using the
9606  * \c PROPERTY_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
9607  *
9608  * \returns The flags for the property.
9609  */
9610 guint32
9611 mono_property_get_flags (MonoProperty *prop)
9612 {
9613         return prop->attrs;
9614 }
9615
9616 /**
9617  * mono_event_get_name:
9618  * \param event the MonoEvent to act on
9619  * \returns The name of the event.
9620  */
9621 const char*
9622 mono_event_get_name (MonoEvent *event)
9623 {
9624         return event->name;
9625 }
9626
9627 /**
9628  * mono_event_get_add_method:
9629  * \param event The \c MonoEvent to act on.
9630  * \returns The \c add method for the event, a \c MonoMethod.
9631  */
9632 MonoMethod*
9633 mono_event_get_add_method (MonoEvent *event)
9634 {
9635         return event->add;
9636 }
9637
9638 /**
9639  * mono_event_get_remove_method:
9640  * \param event The \c MonoEvent to act on.
9641  * \returns The \c remove method for the event, a \c MonoMethod.
9642  */
9643 MonoMethod*
9644 mono_event_get_remove_method (MonoEvent *event)
9645 {
9646         return event->remove;
9647 }
9648
9649 /**
9650  * mono_event_get_raise_method:
9651  * \param event The \c MonoEvent to act on.
9652  * \returns The \c raise method for the event, a \c MonoMethod.
9653  */
9654 MonoMethod*
9655 mono_event_get_raise_method (MonoEvent *event)
9656 {
9657         return event->raise;
9658 }
9659
9660 /**
9661  * mono_event_get_parent:
9662  * \param event the MonoEvent to act on.
9663  * \returns The \c MonoClass where the event is defined.
9664  */
9665 MonoClass*
9666 mono_event_get_parent (MonoEvent *event)
9667 {
9668         return event->parent;
9669 }
9670
9671 /**
9672  * mono_event_get_flags
9673  * \param event the \c MonoEvent to act on.
9674  *
9675  * The metadata flags for an event are encoded using the
9676  * \c EVENT_* constants.  See the \c tabledefs.h file for details.
9677  *
9678  * \returns The flags for the event.
9679  */
9680 guint32
9681 mono_event_get_flags (MonoEvent *event)
9682 {
9683         return event->attrs;
9684 }
9685
9686 /**
9687  * mono_class_get_method_from_name:
9688  * \param klass where to look for the method
9689  * \param name name of the method
9690  * \param param_count number of parameters. -1 for any number.
9691  *
9692  * Obtains a \c MonoMethod with a given name and number of parameters.
9693  * It only works if there are no multiple signatures for any given method name.
9694  */
9695 MonoMethod *
9696 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9697 {
9698         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9699 }
9700
9701 static MonoMethod*
9702 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9703 {
9704         MonoMethod *res = NULL;
9705         int i;
9706
9707         /* Search directly in the metadata to avoid calling setup_methods () */
9708         int first_idx = mono_class_get_first_method_idx (klass);
9709         int mcount = mono_class_get_method_count (klass);
9710         for (i = 0; i < mcount; ++i) {
9711                 MonoError error;
9712                 guint32 cols [MONO_METHOD_SIZE];
9713                 MonoMethod *method;
9714                 MonoMethodSignature *sig;
9715
9716                 /* first_idx points into the methodptr table */
9717                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9718
9719                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9720                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9721                         if (!method) {
9722                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9723                                 continue;
9724                         }
9725                         if (param_count == -1) {
9726                                 res = method;
9727                                 break;
9728                         }
9729                         sig = mono_method_signature_checked (method, &error);
9730                         if (!sig) {
9731                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9732                                 continue;
9733                         }
9734                         if (sig->param_count == param_count) {
9735                                 res = method;
9736                                 break;
9737                         }
9738                 }
9739         }
9740
9741         return res;
9742 }
9743
9744 /**
9745  * mono_class_get_method_from_name_flags:
9746  * \param klass where to look for the method
9747  * \param name_space name of the method
9748  * \param param_count number of parameters. -1 for any number.
9749  * \param flags flags which must be set in the method
9750  *
9751  * Obtains a \c MonoMethod with a given name and number of parameters.
9752  * It only works if there are no multiple signatures for any given method name.
9753  */
9754 MonoMethod *
9755 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9756 {
9757         MonoMethod *res = NULL;
9758         int i;
9759
9760         mono_class_init (klass);
9761
9762         if (mono_class_is_ginst (klass) && !klass->methods) {
9763                 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9764                 if (res) {
9765                         MonoError error;
9766                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9767                         if (!mono_error_ok (&error))
9768                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9769                 }
9770                 return res;
9771         }
9772
9773         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9774                 mono_class_setup_methods (klass);
9775                 /*
9776                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9777                 See mono/tests/array_load_exception.il
9778                 FIXME we should better report this error to the caller
9779                  */
9780                 if (!klass->methods)
9781                         return NULL;
9782                 int mcount = mono_class_get_method_count (klass);
9783                 for (i = 0; i < mcount; ++i) {
9784                         MonoMethod *method = klass->methods [i];
9785
9786                         if (method->name[0] == name [0] && 
9787                                 !strcmp (name, method->name) &&
9788                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9789                                 ((method->flags & flags) == flags)) {
9790                                 res = method;
9791                                 break;
9792                         }
9793                 }
9794         }
9795         else {
9796             res = find_method_in_metadata (klass, name, param_count, flags);
9797         }
9798
9799         return res;
9800 }
9801
9802 /**
9803  * mono_class_set_failure:
9804  * \param klass class in which the failure was detected
9805  * \param ex_type the kind of exception/error to be thrown (later)
9806  * \param ex_data exception data (specific to each type of exception/error)
9807  *
9808  * Keep a detected failure informations in the class for later processing.
9809  * Note that only the first failure is kept.
9810  *
9811  * LOCKING: Acquires the loader lock.
9812  */
9813 static gboolean
9814 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9815 {
9816         g_assert (boxed_error != NULL);
9817
9818         if (mono_class_has_failure (klass))
9819                 return FALSE;
9820
9821         mono_loader_lock ();
9822         klass->has_failure = 1;
9823         mono_class_set_exception_data (klass, boxed_error);
9824         mono_loader_unlock ();
9825
9826         return TRUE;
9827 }
9828
9829 gboolean
9830 mono_class_has_failure (const MonoClass *klass)
9831 {
9832         g_assert (klass != NULL);
9833         return klass->has_failure != 0;
9834 }
9835
9836
9837 /**
9838  * mono_class_set_type_load_failure:
9839  * \param klass class in which the failure was detected
9840  * \param fmt \c printf -style error message string.
9841  *
9842  * Collect detected failure informaion in the class for later processing.
9843  * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9844  * Note that only the first failure is kept.
9845  *
9846  * LOCKING: Acquires the loader lock.
9847  *
9848  * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9849  */
9850 gboolean
9851 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9852 {
9853         MonoError prepare_error;
9854         va_list args;
9855
9856         if (mono_class_has_failure (klass))
9857                 return FALSE;
9858         
9859         error_init (&prepare_error);
9860         
9861         va_start (args, fmt);
9862         mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9863         va_end (args);
9864
9865         MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9866         mono_error_cleanup (&prepare_error);
9867         return mono_class_set_failure (klass, box);
9868 }
9869
9870 /**
9871  * mono_classes_init:
9872  *
9873  * Initialize the resources used by this module.
9874  */
9875 void
9876 mono_classes_init (void)
9877 {
9878         mono_os_mutex_init (&classes_mutex);
9879
9880         mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9881         mono_native_tls_alloc (&init_pending_tls_id, NULL);
9882
9883         mono_counters_register ("MonoClassDef count",
9884                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9885         mono_counters_register ("MonoClassGtd count",
9886                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9887         mono_counters_register ("MonoClassGenericInst count",
9888                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9889         mono_counters_register ("MonoClassGenericParam count",
9890                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9891         mono_counters_register ("MonoClassArray count",
9892                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9893         mono_counters_register ("MonoClassPointer count",
9894                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9895         mono_counters_register ("Inflated methods size",
9896                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9897         mono_counters_register ("Inflated classes size",
9898                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9899         mono_counters_register ("MonoClass size",
9900                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9901 }
9902
9903 /**
9904  * mono_classes_cleanup:
9905  *
9906  * Free the resources used by this module.
9907  */
9908 void
9909 mono_classes_cleanup (void)
9910 {
9911         mono_native_tls_free (setup_fields_tls_id);
9912         mono_native_tls_free (init_pending_tls_id);
9913
9914         if (global_interface_bitset)
9915                 mono_bitset_free (global_interface_bitset);
9916         global_interface_bitset = NULL;
9917         mono_os_mutex_destroy (&classes_mutex);
9918 }
9919
9920 /**
9921  * mono_class_get_exception_for_failure:
9922  * \param klass class in which the failure was detected
9923  *
9924  * \returns a constructed MonoException than the caller can then throw
9925  * using mono_raise_exception - or NULL if no failure is present (or
9926  * doesn't result in an exception).
9927  */
9928 MonoException*
9929 mono_class_get_exception_for_failure (MonoClass *klass)
9930 {
9931         if (!mono_class_has_failure (klass))
9932                 return NULL;
9933         MonoError unboxed_error;
9934         error_init (&unboxed_error);
9935         mono_error_set_for_class_failure (&unboxed_error, klass);
9936         return mono_error_convert_to_exception (&unboxed_error);
9937 }
9938
9939 static gboolean
9940 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9941  {
9942         outer_klass = mono_class_get_generic_type_definition (outer_klass);
9943         inner_klass = mono_class_get_generic_type_definition (inner_klass);
9944         do {
9945                 if (outer_klass == inner_klass)
9946                         return TRUE;
9947                 inner_klass = inner_klass->nested_in;
9948         } while (inner_klass);
9949         return FALSE;
9950 }
9951
9952 MonoClass *
9953 mono_class_get_generic_type_definition (MonoClass *klass)
9954 {
9955         MonoGenericClass *gklass =  mono_class_try_get_generic_class (klass);
9956         return gklass ? gklass->container_class : klass;
9957 }
9958
9959 /*
9960  * Check if @klass is a subtype of @parent ignoring generic instantiations.
9961  * 
9962  * Generic instantiations are ignored for all super types of @klass.
9963  * 
9964  * Visibility checks ignoring generic instantiations.  
9965  */
9966 gboolean
9967 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9968 {
9969         int i;
9970         klass = mono_class_get_generic_type_definition (klass);
9971         parent = mono_class_get_generic_type_definition (parent);
9972         mono_class_setup_supertypes (klass);
9973
9974         for (i = 0; i < klass->idepth; ++i) {
9975                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9976                         return TRUE;
9977         }
9978         return FALSE;
9979 }
9980 /*
9981  * Subtype can only access parent members with family protection if the site object
9982  * is subclass of Subtype. For example:
9983  * class A { protected int x; }
9984  * class B : A {
9985  *      void valid_access () {
9986  *              B b;
9987  *              b.x = 0;
9988  *  }
9989  *  void invalid_access () {
9990  *              A a;
9991  *              a.x = 0;
9992  *  }
9993  * }
9994  * */
9995 static gboolean
9996 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9997 {
9998         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9999                 return FALSE;
10000
10001         if (context_klass == NULL)
10002                 return TRUE;
10003         /*if access_klass is not member_klass context_klass must be type compat*/
10004         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10005                 return FALSE;
10006         return TRUE;
10007 }
10008
10009 static gboolean
10010 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10011 {
10012         GSList *tmp;
10013         if (accessing == accessed)
10014                 return TRUE;
10015         if (!accessed || !accessing)
10016                 return FALSE;
10017
10018         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10019          * anywhere so untrusted friends are not safe to access platform's code internals */
10020         if (mono_security_core_clr_enabled ()) {
10021                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10022                         return FALSE;
10023         }
10024
10025         mono_assembly_load_friends (accessed);
10026         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10027                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10028                 /* Be conservative with checks */
10029                 if (!friend_->name)
10030                         continue;
10031                 if (strcmp (accessing->aname.name, friend_->name))
10032                         continue;
10033                 if (friend_->public_key_token [0]) {
10034                         if (!accessing->aname.public_key_token [0])
10035                                 continue;
10036                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10037                                 continue;
10038                 }
10039                 return TRUE;
10040         }
10041         return FALSE;
10042 }
10043
10044 /*
10045  * If klass is a generic type or if it is derived from a generic type, return the
10046  * MonoClass of the generic definition
10047  * Returns NULL if not found
10048  */
10049 static MonoClass*
10050 get_generic_definition_class (MonoClass *klass)
10051 {
10052         while (klass) {
10053                 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10054                 if (gklass && gklass->container_class)
10055                         return gklass->container_class;
10056                 klass = klass->parent;
10057         }
10058         return NULL;
10059 }
10060
10061 static gboolean
10062 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10063 {
10064         int i;
10065         for (i = 0; i < ginst->type_argc; ++i) {
10066                 MonoType *type = ginst->type_argv[i];
10067                 switch (type->type) {
10068                 case MONO_TYPE_SZARRAY:
10069                         if (!can_access_type (access_klass, type->data.klass))
10070                                 return FALSE;
10071                         break;
10072                 case MONO_TYPE_ARRAY:
10073                         if (!can_access_type (access_klass, type->data.array->eklass))
10074                                 return FALSE;
10075                         break;
10076                 case MONO_TYPE_PTR:
10077                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10078                                 return FALSE;
10079                         break;
10080                 case MONO_TYPE_CLASS:
10081                 case MONO_TYPE_VALUETYPE:
10082                 case MONO_TYPE_GENERICINST:
10083                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10084                                 return FALSE;
10085                 default:
10086                         break;
10087                 }
10088         }
10089         return TRUE;
10090 }
10091
10092 static gboolean
10093 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10094 {
10095         int access_level;
10096
10097         if (access_klass == member_klass)
10098                 return TRUE;
10099
10100         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10101                 return TRUE;
10102
10103         if (access_klass->element_class && !access_klass->enumtype)
10104                 access_klass = access_klass->element_class;
10105
10106         if (member_klass->element_class && !member_klass->enumtype)
10107                 member_klass = member_klass->element_class;
10108
10109         access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10110
10111         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10112                 return TRUE;
10113
10114         if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10115                 return FALSE;
10116
10117         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10118                 return TRUE;
10119
10120         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10121                 return FALSE;
10122
10123         /*Non nested type with nested visibility. We just fail it.*/
10124         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10125                 return FALSE;
10126
10127         switch (access_level) {
10128         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10129                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10130
10131         case TYPE_ATTRIBUTE_PUBLIC:
10132                 return TRUE;
10133
10134         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10135                 return TRUE;
10136
10137         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10138                 return is_nesting_type (member_klass, access_klass);
10139
10140         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10141                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10142
10143         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10144                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10145
10146         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10147                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10148                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10149
10150         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10151                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10152                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10153         }
10154         return FALSE;
10155 }
10156
10157 /* FIXME: check visibility of type, too */
10158 static gboolean
10159 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10160 {
10161         MonoClass *member_generic_def;
10162         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10163                 return TRUE;
10164
10165         MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10166         if (((access_gklass && access_gklass->container_class) ||
10167                                         mono_class_is_gtd (access_klass)) && 
10168                         (member_generic_def = get_generic_definition_class (member_klass))) {
10169                 MonoClass *access_container;
10170
10171                 if (mono_class_is_gtd (access_klass))
10172                         access_container = access_klass;
10173                 else
10174                         access_container = access_gklass->container_class;
10175
10176                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10177                         return TRUE;
10178         }
10179
10180         /* Partition I 8.5.3.2 */
10181         /* the access level values are the same for fields and methods */
10182         switch (access_level) {
10183         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10184                 /* same compilation unit */
10185                 return access_klass->image == member_klass->image;
10186         case FIELD_ATTRIBUTE_PRIVATE:
10187                 return access_klass == member_klass;
10188         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10189                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10190                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10191                         return TRUE;
10192                 return FALSE;
10193         case FIELD_ATTRIBUTE_ASSEMBLY:
10194                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10195         case FIELD_ATTRIBUTE_FAMILY:
10196                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10197                         return TRUE;
10198                 return FALSE;
10199         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10200                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10201                         return TRUE;
10202                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10203         case FIELD_ATTRIBUTE_PUBLIC:
10204                 return TRUE;
10205         }
10206         return FALSE;
10207 }
10208
10209 /**
10210  * mono_method_can_access_field:
10211  * \param method Method that will attempt to access the field
10212  * \param field the field to access
10213  *
10214  * Used to determine if a method is allowed to access the specified field.
10215  *
10216  * \returns TRUE if the given \p method is allowed to access the \p field while following
10217  * the accessibility rules of the CLI.
10218  */
10219 gboolean
10220 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10221 {
10222         /* FIXME: check all overlapping fields */
10223         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10224         if (!can) {
10225                 MonoClass *nested = method->klass->nested_in;
10226                 while (nested) {
10227                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10228                         if (can)
10229                                 return TRUE;
10230                         nested = nested->nested_in;
10231                 }
10232         }
10233         return can;
10234 }
10235
10236 /**
10237  * mono_method_can_access_method:
10238  * \param method Method that will attempt to access the other method
10239  * \param called the method that we want to probe for accessibility.
10240  *
10241  * Used to determine if the \p method is allowed to access the specified \p called method.
10242  *
10243  * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10244  * the accessibility rules of the CLI.
10245  */
10246 gboolean
10247 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10248 {
10249         method = mono_method_get_method_definition (method);
10250         called = mono_method_get_method_definition (called);
10251         return mono_method_can_access_method_full (method, called, NULL);
10252 }
10253
10254 /*
10255  * mono_method_can_access_method_full:
10256  * @method: The caller method 
10257  * @called: The called method 
10258  * @context_klass: The static type on stack of the owner @called object used
10259  * 
10260  * This function must be used with instance calls, as they have more strict family accessibility.
10261  * It can be used with static methods, but context_klass should be NULL.
10262  * 
10263  * Returns: TRUE if caller have proper visibility and acessibility to @called
10264  */
10265 gboolean
10266 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10267 {
10268         /* Wrappers are except from access checks */
10269         if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10270                 return TRUE;
10271
10272         MonoClass *access_class = method->klass;
10273         MonoClass *member_class = called->klass;
10274         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10275         if (!can) {
10276                 MonoClass *nested = access_class->nested_in;
10277                 while (nested) {
10278                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10279                         if (can)
10280                                 break;
10281                         nested = nested->nested_in;
10282                 }
10283         }
10284
10285         if (!can)
10286                 return FALSE;
10287
10288         can = can_access_type (access_class, member_class);
10289         if (!can) {
10290                 MonoClass *nested = access_class->nested_in;
10291                 while (nested) {
10292                         can = can_access_type (nested, member_class);
10293                         if (can)
10294                                 break;
10295                         nested = nested->nested_in;
10296                 }
10297         }
10298
10299         if (!can)
10300                 return FALSE;
10301
10302         if (called->is_inflated) {
10303                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10304                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10305                         return FALSE;
10306         }
10307                 
10308         return TRUE;
10309 }
10310
10311
10312 /*
10313  * mono_method_can_access_field_full:
10314  * @method: The caller method 
10315  * @field: The accessed field
10316  * @context_klass: The static type on stack of the owner @field object used
10317  * 
10318  * This function must be used with instance fields, as they have more strict family accessibility.
10319  * It can be used with static fields, but context_klass should be NULL.
10320  * 
10321  * Returns: TRUE if caller have proper visibility and acessibility to @field
10322  */
10323 gboolean
10324 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10325 {
10326         MonoClass *access_class = method->klass;
10327         MonoClass *member_class = field->parent;
10328         /* FIXME: check all overlapping fields */
10329         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10330         if (!can) {
10331                 MonoClass *nested = access_class->nested_in;
10332                 while (nested) {
10333                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10334                         if (can)
10335                                 break;
10336                         nested = nested->nested_in;
10337                 }
10338         }
10339
10340         if (!can)
10341                 return FALSE;
10342
10343         can = can_access_type (access_class, member_class);
10344         if (!can) {
10345                 MonoClass *nested = access_class->nested_in;
10346                 while (nested) {
10347                         can = can_access_type (nested, member_class);
10348                         if (can)
10349                                 break;
10350                         nested = nested->nested_in;
10351                 }
10352         }
10353
10354         if (!can)
10355                 return FALSE;
10356         return TRUE;
10357 }
10358
10359 /*
10360  * mono_class_can_access_class:
10361  * @source_class: The source class 
10362  * @target_class: The accessed class
10363  * 
10364  * This function returns is @target_class is visible to @source_class
10365  * 
10366  * Returns: TRUE if source have proper visibility and acessibility to target
10367  */
10368 gboolean
10369 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10370 {
10371         return can_access_type (source_class, target_class);
10372 }
10373
10374 /**
10375  * mono_type_is_valid_enum_basetype:
10376  * \param type The MonoType to check
10377  * \returns TRUE if the type can be used as the basetype of an enum
10378  */
10379 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10380         switch (type->type) {
10381         case MONO_TYPE_I1:
10382         case MONO_TYPE_U1:
10383         case MONO_TYPE_BOOLEAN:
10384         case MONO_TYPE_I2:
10385         case MONO_TYPE_U2:
10386         case MONO_TYPE_CHAR:
10387         case MONO_TYPE_I4:
10388         case MONO_TYPE_U4:
10389         case MONO_TYPE_I8:
10390         case MONO_TYPE_U8:
10391         case MONO_TYPE_I:
10392         case MONO_TYPE_U:
10393                 return TRUE;
10394         default:
10395                 return FALSE;
10396         }
10397 }
10398
10399 /**
10400  * mono_class_is_valid_enum:
10401  * \param klass An enum class to be validated
10402  *
10403  * This method verify the required properties an enum should have.
10404  *
10405  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10406  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10407  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10408  *
10409  * \returns TRUE if the informed enum class is valid 
10410  */
10411 gboolean
10412 mono_class_is_valid_enum (MonoClass *klass)
10413 {
10414         MonoClassField * field;
10415         gpointer iter = NULL;
10416         gboolean found_base_field = FALSE;
10417
10418         g_assert (klass->enumtype);
10419         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10420         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10421                 return FALSE;
10422         }
10423
10424         if (!mono_class_is_auto_layout (klass))
10425                 return FALSE;
10426
10427         while ((field = mono_class_get_fields (klass, &iter))) {
10428                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10429                         if (found_base_field)
10430                                 return FALSE;
10431                         found_base_field = TRUE;
10432                         if (!mono_type_is_valid_enum_basetype (field->type))
10433                                 return FALSE;
10434                 }
10435         }
10436
10437         if (!found_base_field)
10438                 return FALSE;
10439
10440         if (mono_class_get_method_count (klass) > 0)
10441                 return FALSE;
10442
10443         return TRUE;
10444 }
10445
10446 gboolean
10447 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10448 {
10449         return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10450 }
10451
10452 /*
10453  * mono_class_setup_interface_id:
10454  *
10455  * Initializes MonoClass::interface_id if required.
10456  *
10457  * LOCKING: Acquires the loader lock.
10458  */
10459 void
10460 mono_class_setup_interface_id (MonoClass *klass)
10461 {
10462         mono_loader_lock ();
10463         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10464                 klass->interface_id = mono_get_unique_iid (klass);
10465         mono_loader_unlock ();
10466 }
10467
10468 /*
10469  * mono_class_setup_interfaces:
10470  *
10471  *   Initialize klass->interfaces/interfaces_count.
10472  * LOCKING: Acquires the loader lock.
10473  * This function can fail the type.
10474  */
10475 void
10476 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10477 {
10478         int i, interface_count;
10479         MonoClass **interfaces;
10480
10481         error_init (error);
10482
10483         if (klass->interfaces_inited)
10484                 return;
10485
10486         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10487                 MonoType *args [1];
10488
10489                 /* generic IList, ICollection, IEnumerable */
10490                 interface_count = 2;
10491                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10492
10493                 args [0] = &klass->element_class->byval_arg;
10494                 interfaces [0] = mono_class_bind_generic_parameters (
10495                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10496                 interfaces [1] = mono_class_bind_generic_parameters (
10497                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10498         } else if (mono_class_is_ginst (klass)) {
10499                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10500
10501                 mono_class_setup_interfaces (gklass, error);
10502                 if (!mono_error_ok (error)) {
10503                         mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10504                         return;
10505                 }
10506
10507                 interface_count = gklass->interface_count;
10508                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10509                 for (i = 0; i < interface_count; i++) {
10510                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10511                         if (!mono_error_ok (error)) {
10512                                 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10513                                 return;
10514                         }
10515                 }
10516         } else {
10517                 interface_count = 0;
10518                 interfaces = NULL;
10519         }
10520
10521         mono_loader_lock ();
10522         if (!klass->interfaces_inited) {
10523                 klass->interface_count = interface_count;
10524                 klass->interfaces = interfaces;
10525
10526                 mono_memory_barrier ();
10527
10528                 klass->interfaces_inited = TRUE;
10529         }
10530         mono_loader_unlock ();
10531 }
10532
10533 static void
10534 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10535 {
10536         MonoClass *klass = field->parent;
10537         MonoImage *image = klass->image;
10538         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10539         MonoType *ftype;
10540         int field_idx = field - klass->fields;
10541
10542         error_init (error);
10543
10544         if (gtd) {
10545                 MonoClassField *gfield = &gtd->fields [field_idx];
10546                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10547                 if (!mono_error_ok (error)) {
10548                         char *full_name = mono_type_get_full_name (gtd);
10549                         mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10550                         g_free (full_name);
10551                 }
10552
10553                 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10554                 if (!mono_error_ok (error)) {
10555                         char *full_name = mono_type_get_full_name (klass);
10556                         mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10557                         g_free (full_name);
10558                 }
10559         } else {
10560                 const char *sig;
10561                 guint32 cols [MONO_FIELD_SIZE];
10562                 MonoGenericContainer *container = NULL;
10563                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10564
10565                 /*FIXME, in theory we do not lazy load SRE fields*/
10566                 g_assert (!image_is_dynamic (image));
10567
10568                 if (mono_class_is_gtd (klass)) {
10569                         container = mono_class_get_generic_container (klass);
10570                 } else if (gtd) {
10571                         container = mono_class_get_generic_container (gtd);
10572                         g_assert (container);
10573                 }
10574
10575                 /* first_field_idx and idx points into the fieldptr table */
10576                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10577
10578                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10579                         char *full_name = mono_type_get_full_name (klass);
10580                         mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10581                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10582                         g_free (full_name);
10583                         return;
10584                 }
10585
10586                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10587
10588                 mono_metadata_decode_value (sig, &sig);
10589                 /* FIELD signature == 0x06 */
10590                 g_assert (*sig == 0x06);
10591
10592                 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10593                 if (!ftype) {
10594                         char *full_name = mono_type_get_full_name (klass);
10595                         mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10596                         g_free (full_name);
10597                 }
10598         }
10599         mono_memory_barrier ();
10600         field->type = ftype;
10601 }
10602
10603 static guint32
10604 mono_field_resolve_flags (MonoClassField *field)
10605 {
10606         MonoClass *klass = field->parent;
10607         MonoImage *image = klass->image;
10608         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10609         int field_idx = field - klass->fields;
10610
10611         if (gtd) {
10612                 MonoClassField *gfield = &gtd->fields [field_idx];
10613                 return mono_field_get_flags (gfield);
10614         } else {
10615                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10616
10617                 /*FIXME, in theory we do not lazy load SRE fields*/
10618                 g_assert (!image_is_dynamic (image));
10619
10620                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10621         }
10622 }
10623
10624 /**
10625  * mono_class_get_fields_lazy:
10626  * \param klass the MonoClass to act on
10627  *
10628  * This routine is an iterator routine for retrieving the fields in a class.
10629  * Only minimal information about fields are loaded. Accessors must be used
10630  * for all MonoClassField returned.
10631  *
10632  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10633  * iterate over all of the elements.  When no more values are
10634  * available, the return value is NULL.
10635  *
10636  * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10637  */
10638 MonoClassField*
10639 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10640 {
10641         MonoClassField* field;
10642         if (!iter)
10643                 return NULL;
10644         if (!*iter) {
10645                 mono_class_setup_basic_field_info (klass);
10646                 if (!klass->fields)
10647                         return NULL;
10648                 /* start from the first */
10649                 if (mono_class_get_field_count (klass)) {
10650                         *iter = &klass->fields [0];
10651                         return (MonoClassField *)*iter;
10652                 } else {
10653                         /* no fields */
10654                         return NULL;
10655                 }
10656         }
10657         field = (MonoClassField *)*iter;
10658         field++;
10659         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10660                 *iter = field;
10661                 return (MonoClassField *)*iter;
10662         }
10663         return NULL;
10664 }
10665
10666 char*
10667 mono_class_full_name (MonoClass *klass)
10668 {
10669         return mono_type_full_name (&klass->byval_arg);
10670 }
10671
10672 /* Declare all shared lazy type lookup functions */
10673 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10674
10675 /**
10676  * mono_method_get_base_method:
10677  * \param method a method
10678  * \param definition if true, get the definition
10679  * \param error set on failure
10680  *
10681  * Given a virtual method associated with a subclass, return the corresponding
10682  * method from an ancestor.  If \p definition is FALSE, returns the method in the
10683  * superclass of the given method.  If \p definition is TRUE, return the method
10684  * in the ancestor class where it was first declared.  The type arguments will
10685  * be inflated in the ancestor classes.  If the method is not associated with a
10686  * class, or isn't virtual, returns the method itself.  On failure returns NULL
10687  * and sets \p error.
10688  */
10689 MonoMethod*
10690 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10691 {
10692         MonoClass *klass, *parent;
10693         MonoGenericContext *generic_inst = NULL;
10694         MonoMethod *result = NULL;
10695         int slot;
10696
10697         if (method->klass == NULL)
10698                 return method;
10699
10700         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10701             MONO_CLASS_IS_INTERFACE (method->klass) ||
10702             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10703                 return method;
10704
10705         slot = mono_method_get_vtable_slot (method);
10706         if (slot == -1)
10707                 return method;
10708
10709         klass = method->klass;
10710         if (mono_class_is_ginst (klass)) {
10711                 generic_inst = mono_class_get_context (klass);
10712                 klass = mono_class_get_generic_class (klass)->container_class;
10713         }
10714
10715 retry:
10716         if (definition) {
10717                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10718                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10719                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10720                            or klass is the generic container class and generic_inst is the instantiation.
10721
10722                            when we go to the parent, if the parent is an open constructed type, we need to
10723                            replace the type parameters by the definitions from the generic_inst, and then take it
10724                            apart again into the klass and the generic_inst.
10725
10726                            For cases like this:
10727                            class C<T> : B<T, int> {
10728                                public override void Foo () { ... }
10729                            }
10730                            class B<U,V> : A<HashMap<U,V>> {
10731                                public override void Foo () { ... }
10732                            }
10733                            class A<X> {
10734                                public virtual void Foo () { ... }
10735                            }
10736
10737                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
10738                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
10739                            NULL;
10740                         */
10741                         MonoGenericContext *parent_inst = NULL;
10742                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10743                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10744                                 return_val_if_nok  (error, NULL);
10745                         }
10746                         if (mono_class_is_ginst (parent)) {
10747                                 parent_inst = mono_class_get_context (parent);
10748                                 parent = mono_class_get_generic_class (parent)->container_class;
10749                         }
10750
10751                         mono_class_setup_vtable (parent);
10752                         if (parent->vtable_size <= slot)
10753                                 break;
10754                         klass = parent;
10755                         generic_inst = parent_inst;
10756                 }
10757         } else {
10758                 klass = klass->parent;
10759                 if (!klass)
10760                         return method;
10761                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10762                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10763                         return_val_if_nok (error, NULL);
10764
10765                         generic_inst = NULL;
10766                 }
10767                 if (mono_class_is_ginst (klass)) {
10768                         generic_inst = mono_class_get_context (klass);
10769                         klass = mono_class_get_generic_class (klass)->container_class;
10770                 }
10771
10772         }
10773
10774         if (generic_inst) {
10775                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10776                 return_val_if_nok (error, NULL);
10777         }
10778
10779         if (klass == method->klass)
10780                 return method;
10781
10782         /*This is possible if definition == FALSE.
10783          * Do it here to be really sure we don't read invalid memory.
10784          */
10785         if (slot >= klass->vtable_size)
10786                 return method;
10787
10788         mono_class_setup_vtable (klass);
10789
10790         result = klass->vtable [slot];
10791         if (result == NULL) {
10792                 /* It is an abstract method */
10793                 gboolean found = FALSE;
10794                 gpointer iter = NULL;
10795                 while ((result = mono_class_get_methods (klass, &iter))) {
10796                         if (result->slot == slot) {
10797                                 found = TRUE;
10798                                 break;
10799                         }
10800                 }
10801                 /* found might be FALSE if we looked in an abstract class
10802                  * that doesn't override an abstract method of its
10803                  * parent: 
10804                  *   abstract class Base {
10805                  *     public abstract void Foo ();
10806                  *   }
10807                  *   abstract class Derived : Base { }
10808                  *   class Child : Derived {
10809                  *     public override void Foo () { }
10810                  *  }
10811                  *
10812                  *  if m was Child.Foo and we ask for the base method,
10813                  *  then we get here with klass == Derived and found == FALSE
10814                  */
10815                 /* but it shouldn't be the case that if we're looking
10816                  * for the definition and didn't find a result; the
10817                  * loop above should've taken us as far as we could
10818                  * go! */
10819                 g_assert (!(definition && !found));
10820                 if (!found)
10821                         goto retry;
10822         }
10823
10824         g_assert (result != NULL);
10825         return result;
10826 }