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