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