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