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