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