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