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