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