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