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