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