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