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