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