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