Merge pull request #642 from Ventero/CleanCopyLocal
[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 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 }
5336 #endif /*DISABLE_COM*/
5337
5338 /*
5339  * LOCKING: this assumes the loader lock is held
5340  */
5341 void
5342 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5343 {
5344         gboolean system_namespace;
5345         gboolean is_corlib = mono_is_corlib_image (class->image);
5346
5347         system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5348
5349         /* if root of the hierarchy */
5350         if (system_namespace && !strcmp (class->name, "Object")) {
5351                 class->parent = NULL;
5352                 class->instance_size = sizeof (MonoObject);
5353                 return;
5354         }
5355         if (!strcmp (class->name, "<Module>")) {
5356                 class->parent = NULL;
5357                 class->instance_size = 0;
5358                 return;
5359         }
5360
5361         if (!MONO_CLASS_IS_INTERFACE (class)) {
5362                 /* Imported COM Objects always derive from __ComObject. */
5363 #ifndef DISABLE_COM
5364                 if (MONO_CLASS_IS_IMPORT (class)) {
5365                         init_com_from_comimport (class);
5366                         if (parent == mono_defaults.object_class)
5367                                 parent = mono_class_get_com_object_class ();
5368                 }
5369 #endif
5370                 if (!parent) {
5371                         /* set the parent to something useful and safe, but mark the type as broken */
5372                         parent = mono_defaults.object_class;
5373                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5374                 }
5375
5376                 class->parent = parent;
5377
5378                 if (parent->generic_class && !parent->name) {
5379                         /*
5380                          * If the parent is a generic instance, we may get
5381                          * called before it is fully initialized, especially
5382                          * before it has its name.
5383                          */
5384                         return;
5385                 }
5386
5387 #ifndef DISABLE_REMOTING
5388                 class->marshalbyref = parent->marshalbyref;
5389                 class->contextbound  = parent->contextbound;
5390 #endif
5391
5392                 class->delegate  = parent->delegate;
5393
5394                 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5395                         mono_class_set_is_com_object (class);
5396                 
5397                 if (system_namespace) {
5398 #ifndef DISABLE_REMOTING
5399                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5400                                 class->marshalbyref = 1;
5401
5402                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
5403                                 class->contextbound  = 1;
5404 #endif
5405                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
5406                                 class->delegate  = 1;
5407                 }
5408
5409                 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) && 
5410                                                 (strcmp (class->parent->name_space, "System") == 0)))
5411                         class->valuetype = 1;
5412                 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5413                         class->valuetype = class->enumtype = 1;
5414                 }
5415                 /*class->enumtype = class->parent->enumtype; */
5416         } else {
5417                 /* initialize com types if COM interfaces are present */
5418 #ifndef DISABLE_COM
5419                 if (MONO_CLASS_IS_IMPORT (class))
5420                         init_com_from_comimport (class);
5421 #endif
5422                 class->parent = NULL;
5423         }
5424
5425 }
5426
5427 /*
5428  * mono_class_setup_supertypes:
5429  * @class: a class
5430  *
5431  * Build the data structure needed to make fast type checks work.
5432  * This currently sets two fields in @class:
5433  *  - idepth: distance between @class and System.Object in the type
5434  *    hierarchy + 1
5435  *  - supertypes: array of classes: each element has a class in the hierarchy
5436  *    starting from @class up to System.Object
5437  * 
5438  * LOCKING: this assumes the loader lock is held
5439  */
5440 void
5441 mono_class_setup_supertypes (MonoClass *class)
5442 {
5443         int ms;
5444         MonoClass **supertypes;
5445
5446         if (class->supertypes)
5447                 return;
5448
5449         if (class->parent && !class->parent->supertypes)
5450                 mono_class_setup_supertypes (class->parent);
5451         if (class->parent)
5452                 class->idepth = class->parent->idepth + 1;
5453         else
5454                 class->idepth = 1;
5455
5456         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5457         supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5458
5459         if (class->parent) {
5460                 supertypes [class->idepth - 1] = class;
5461                 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5462         } else {
5463                 supertypes [0] = class;
5464         }
5465
5466         mono_atomic_store_release (&class->supertypes, supertypes);
5467 }
5468
5469 static gboolean
5470 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5471 {
5472         MonoClass *gtd = (MonoClass*)user_data;
5473         /* Only try to fix generic instances of @gtd */
5474         if (gclass->generic_class->container_class != gtd)
5475                 return FALSE;
5476
5477         /* Check if the generic instance has no parent. */
5478         if (gtd->parent && !gclass->parent)
5479                 mono_generic_class_setup_parent (gclass, gtd);
5480
5481         return TRUE;
5482 }
5483
5484 static void
5485 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5486 {
5487         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5488         mono_error_set_type_load_class (error, class, msg);
5489 }
5490
5491 static void
5492 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5493 {
5494         MonoLoaderError *lerror = mono_loader_get_last_error ();
5495
5496         if (lerror) {
5497                 set_failure_from_loader_error (class, lerror);
5498                 mono_error_set_from_loader_error (error);
5499                 if (msg)
5500                         g_free (msg);
5501         } else {
5502                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5503                 mono_error_set_type_load_class (error, class, msg);
5504         }
5505 }
5506
5507 /**
5508  * mono_class_create_from_typedef:
5509  * @image: image where the token is valid
5510  * @type_token:  typedef token
5511  * @error:  used to return any error found while creating the type
5512  *
5513  * Create the MonoClass* representing the specified type token.
5514  * @type_token must be a TypeDef token.
5515  *
5516  * FIXME: don't return NULL on failure, just the the caller figure it out.
5517  */
5518 static MonoClass *
5519 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5520 {
5521         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5522         MonoClass *class, *parent = NULL;
5523         guint32 cols [MONO_TYPEDEF_SIZE];
5524         guint32 cols_next [MONO_TYPEDEF_SIZE];
5525         guint tidx = mono_metadata_token_index (type_token);
5526         MonoGenericContext *context = NULL;
5527         const char *name, *nspace;
5528         guint icount = 0; 
5529         MonoClass **interfaces;
5530         guint32 field_last, method_last;
5531         guint32 nesting_tokeen;
5532
5533         mono_error_init (error);
5534
5535         if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5536                 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5537                 g_assert (!mono_loader_get_last_error ());
5538                 return NULL;
5539         }
5540
5541         mono_loader_lock ();
5542
5543         if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5544                 mono_loader_unlock ();
5545                 g_assert (!mono_loader_get_last_error ());
5546                 return class;
5547         }
5548
5549         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5550         
5551         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5552         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5553
5554         class = mono_image_alloc0 (image, sizeof (MonoClass));
5555
5556         class->name = name;
5557         class->name_space = nspace;
5558
5559         mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5560
5561         class->image = image;
5562         class->type_token = type_token;
5563         class->flags = cols [MONO_TYPEDEF_FLAGS];
5564
5565         mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5566
5567         classes_size += sizeof (MonoClass);
5568
5569         /*
5570          * Check whether we're a generic type definition.
5571          */
5572         class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5573         if (class->generic_container) {
5574                 class->is_generic = 1;
5575                 class->generic_container->owner.klass = class;
5576                 context = &class->generic_container->context;
5577         }
5578
5579         if (class->generic_container)
5580                 enable_gclass_recording ();
5581
5582         if (cols [MONO_TYPEDEF_EXTENDS]) {
5583                 MonoClass *tmp;
5584                 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5585
5586                 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5587                         /*WARNING: this must satisfy mono_metadata_type_hash*/
5588                         class->this_arg.byref = 1;
5589                         class->this_arg.data.klass = class;
5590                         class->this_arg.type = MONO_TYPE_CLASS;
5591                         class->byval_arg.data.klass = class;
5592                         class->byval_arg.type = MONO_TYPE_CLASS;
5593                 }
5594                 parent = mono_class_get_full (image, parent_token, context);
5595
5596                 if (parent == NULL) {
5597                         mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5598                         goto parent_failure;
5599                 }
5600
5601                 for (tmp = parent; tmp; tmp = tmp->parent) {
5602                         if (tmp == class) {
5603                                 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5604                                 goto parent_failure;
5605                         }
5606                         if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5607                                 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5608                                 goto parent_failure;
5609                         }
5610                 }
5611         }
5612
5613         mono_class_setup_parent (class, parent);
5614
5615         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5616         mono_class_setup_mono_type (class);
5617
5618         if (class->generic_container)
5619                 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5620
5621         /* 
5622          * This might access class->byval_arg for recursion generated by generic constraints,
5623          * so it has to come after setup_mono_type ().
5624          */
5625         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5626                 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5627                 if (!mono_error_ok (error)) {
5628                         /*FIXME implement a mono_class_set_failure_from_mono_error */
5629                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5630                         mono_loader_unlock ();
5631                         mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5632                         g_assert (!mono_loader_get_last_error ());
5633                         return NULL;
5634                 }
5635         }
5636
5637         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5638                 class->unicode = 1;
5639
5640 #ifdef HOST_WIN32
5641         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5642                 class->unicode = 1;
5643 #endif
5644
5645         class->cast_class = class->element_class = class;
5646
5647         if (!class->enumtype) {
5648                 if (!mono_metadata_interfaces_from_typedef_full (
5649                             image, type_token, &interfaces, &icount, FALSE, context)){
5650                         mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5651                         mono_loader_unlock ();
5652                         mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5653                         return NULL;
5654                 }
5655
5656                 class->interfaces = interfaces;
5657                 class->interface_count = icount;
5658                 class->interfaces_inited = 1;
5659         }
5660
5661         /*g_print ("Load class %s\n", name);*/
5662
5663         /*
5664          * Compute the field and method lists
5665          */
5666         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5667         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5668
5669         if (tt->rows > tidx){           
5670                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5671                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5672                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5673         } else {
5674                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
5675                 method_last = image->tables [MONO_TABLE_METHOD].rows;
5676         }
5677
5678         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
5679             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5680                 class->field.count = field_last - class->field.first;
5681         else
5682                 class->field.count = 0;
5683
5684         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5685                 class->method.count = method_last - class->method.first;
5686         else
5687                 class->method.count = 0;
5688
5689         /* reserve space to store vector pointer in arrays */
5690         if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5691                 class->instance_size += 2 * sizeof (gpointer);
5692                 g_assert (class->field.count == 0);
5693         }
5694
5695         if (class->enumtype) {
5696                 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5697                 if (!enum_basetype) {
5698                         /*set it to a default value as the whole runtime can't handle this to be null*/
5699                         class->cast_class = class->element_class = mono_defaults.int32_class;
5700                         mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5701                         mono_loader_unlock ();
5702                         mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5703                         g_assert (!mono_loader_get_last_error ());
5704                         return NULL;
5705                 }
5706                 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5707         }
5708
5709         /*
5710          * If we're a generic type definition, load the constraints.
5711          * We must do this after the class has been constructed to make certain recursive scenarios
5712          * work.
5713          */
5714         if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5715                 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5716                 mono_loader_unlock ();
5717                 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5718                 g_assert (!mono_loader_get_last_error ());
5719                 return NULL;
5720         }
5721
5722         if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5723                 if (!strncmp (name, "Vector", 6))
5724                         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");
5725         }
5726
5727         mono_loader_unlock ();
5728
5729         mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5730         g_assert (!mono_loader_get_last_error ());
5731
5732         return class;
5733
5734 parent_failure:
5735         mono_class_setup_mono_type (class);
5736         mono_loader_unlock ();
5737         mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5738         g_assert (!mono_loader_get_last_error ());
5739         return NULL;
5740 }
5741
5742 /** is klass Nullable<T>? */
5743 gboolean
5744 mono_class_is_nullable (MonoClass *klass)
5745 {
5746        return klass->generic_class != NULL &&
5747                klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5748 }
5749
5750
5751 /** if klass is T? return T */
5752 MonoClass*
5753 mono_class_get_nullable_param (MonoClass *klass)
5754 {
5755        g_assert (mono_class_is_nullable (klass));
5756        return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5757 }
5758
5759 static void
5760 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5761 {
5762         if (gtd->parent) {
5763                 MonoError error;
5764                 MonoGenericClass *gclass = klass->generic_class;
5765
5766                 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5767                 if (!mono_error_ok (&error)) {
5768                         /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5769                         klass->parent = mono_defaults.object_class;
5770                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5771                         mono_error_cleanup (&error);
5772                 }
5773         }
5774         if (klass->parent)
5775                 mono_class_setup_parent (klass, klass->parent);
5776
5777         if (klass->enumtype) {
5778                 klass->cast_class = gtd->cast_class;
5779                 klass->element_class = gtd->element_class;
5780         }
5781 }
5782
5783
5784 /*
5785  * Create the `MonoClass' for an instantiation of a generic type.
5786  * We only do this if we actually need it.
5787  */
5788 MonoClass*
5789 mono_generic_class_get_class (MonoGenericClass *gclass)
5790 {
5791         MonoClass *klass, *gklass;
5792
5793         if (gclass->cached_class)
5794                 return gclass->cached_class;
5795
5796         mono_loader_lock ();
5797         if (gclass->cached_class) {
5798                 mono_loader_unlock ();
5799                 return gclass->cached_class;
5800         }
5801
5802         klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5803
5804         gklass = gclass->container_class;
5805
5806         if (record_gclass_instantiation > 0)
5807                 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5808
5809         if (gklass->nested_in) {
5810                 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5811                 klass->nested_in = gklass->nested_in;
5812         }
5813
5814         klass->name = gklass->name;
5815         klass->name_space = gklass->name_space;
5816         
5817         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5818         
5819         klass->image = gklass->image;
5820         klass->flags = gklass->flags;
5821         klass->type_token = gklass->type_token;
5822         klass->field.count = gklass->field.count;
5823
5824         klass->is_inflated = 1;
5825         klass->generic_class = gclass;
5826
5827         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5828         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5829         klass->this_arg.byref = TRUE;
5830         klass->enumtype = gklass->enumtype;
5831         klass->valuetype = gklass->valuetype;
5832
5833         klass->cast_class = klass->element_class = klass;
5834
5835         if (mono_class_is_nullable (klass))
5836                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5837
5838         /*
5839          * We're not interested in the nested classes of a generic instance.
5840          * We use the generic type definition to look for nested classes.
5841          */
5842
5843         mono_generic_class_setup_parent (klass, gklass);
5844
5845         if (gclass->is_dynamic) {
5846                 klass->inited = 1;
5847
5848                 mono_class_setup_supertypes (klass);
5849
5850                 if (klass->enumtype) {
5851                         /*
5852                          * For enums, gklass->fields might not been set, but instance_size etc. is 
5853                          * already set in mono_reflection_create_internal_class (). For non-enums,
5854                          * these will be computed normally in mono_class_layout_fields ().
5855                          */
5856                         klass->instance_size = gklass->instance_size;
5857                         klass->sizes.class_size = gklass->sizes.class_size;
5858                         mono_memory_barrier ();
5859                         klass->size_inited = 1;
5860                 }
5861         }
5862
5863         mono_memory_barrier ();
5864         gclass->cached_class = klass;
5865
5866         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5867
5868         inflated_classes ++;
5869         inflated_classes_size += sizeof (MonoClass);
5870         
5871         mono_loader_unlock ();
5872
5873         return klass;
5874 }
5875
5876 static MonoClass*
5877 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5878 {
5879         MonoClass *klass, **ptr;
5880         int count, pos, i;
5881         MonoGenericContainer *container = mono_generic_param_owner (param);
5882
5883         if (!image)
5884                 /* FIXME: */
5885                 image = mono_defaults.corlib;
5886
5887         klass = mono_image_alloc0 (image, sizeof (MonoClass));
5888         classes_size += sizeof (MonoClass);
5889
5890         if (pinfo) {
5891                 klass->name = pinfo->name;
5892         } else {
5893                 int n = mono_generic_param_num (param);
5894                 klass->name = mono_image_alloc0 (image, 16);
5895                 sprintf ((char*)klass->name, "%d", n);
5896         }
5897
5898         if (container) {
5899                 if (is_mvar) {
5900                         MonoMethod *omethod = container->owner.method;
5901                         klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5902                 } else {
5903                         MonoClass *oklass = container->owner.klass;
5904                         klass->name_space = oklass ? oklass->name_space : "";
5905                 }
5906         } else {
5907                 klass->name_space = "";
5908         }
5909
5910         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5911
5912         count = 0;
5913         if (pinfo)
5914                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5915                         ;
5916
5917         pos = 0;
5918         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5919                 klass->parent = pinfo->constraints [0];
5920                 pos++;
5921         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5922                 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5923         else
5924                 klass->parent = mono_defaults.object_class;
5925
5926
5927         if (count - pos > 0) {
5928                 klass->interface_count = count - pos;
5929                 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5930                 klass->interfaces_inited = TRUE;
5931                 for (i = pos; i < count; i++)
5932                         klass->interfaces [i - pos] = pinfo->constraints [i];
5933         }
5934
5935         klass->image = image;
5936
5937         klass->inited = TRUE;
5938         klass->cast_class = klass->element_class = klass;
5939         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5940
5941         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5942         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5943         klass->this_arg.byref = TRUE;
5944
5945         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5946         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5947
5948         /*Init these fields to sane values*/
5949         klass->min_align = 1;
5950         klass->instance_size = sizeof (gpointer);
5951         mono_memory_barrier ();
5952         klass->size_inited = 1;
5953
5954         mono_class_setup_supertypes (klass);
5955
5956         if (count - pos > 0) {
5957                 mono_class_setup_vtable (klass->parent);
5958                 if (klass->parent->exception_type)
5959                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
5960                 else
5961                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
5962         }
5963
5964         return klass;
5965 }
5966
5967 #define FAST_CACHE_SIZE 16
5968
5969 static MonoClass *
5970 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
5971 {
5972         int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5973         MonoImage *image = param->image;
5974         GHashTable *ht;
5975
5976         g_assert (image);
5977
5978         if (n < FAST_CACHE_SIZE) {
5979                 if (is_mvar)
5980                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
5981                 else
5982                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
5983         } else {
5984                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5985                 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
5986         }
5987 }
5988
5989 /*
5990  * LOCKING: Acquires the loader lock.
5991  */
5992 static void
5993 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
5994 {
5995         int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5996         MonoImage *image = param->image;
5997         GHashTable *ht;
5998
5999         g_assert (image);
6000
6001         if (n < FAST_CACHE_SIZE) {
6002                 if (is_mvar) {
6003                         /* No locking needed */
6004                         if (!image->mvar_cache_fast)
6005                                 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6006                         image->mvar_cache_fast [n] = klass;
6007                 } else {
6008                         if (!image->var_cache_fast)
6009                                 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6010                         image->var_cache_fast [n] = klass;
6011                 }
6012                 return;
6013         }
6014         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6015         if (!ht) {
6016                 mono_loader_lock ();
6017                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6018                 if (!ht) {
6019                         ht = g_hash_table_new (NULL, NULL);
6020                         mono_memory_barrier ();
6021                         if (is_mvar)
6022                                 image->mvar_cache_slow = ht;
6023                         else
6024                                 image->var_cache_slow = ht;
6025                 }
6026                 mono_loader_unlock ();
6027         }
6028
6029         g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6030 }
6031
6032 /*
6033  * LOCKING: Acquires the loader lock.
6034  */
6035 MonoClass *
6036 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6037 {
6038         MonoGenericContainer *container = mono_generic_param_owner (param);
6039         MonoGenericParamInfo *pinfo;
6040         MonoClass *klass;
6041
6042         mono_loader_lock ();
6043
6044         if (container) {
6045                 pinfo = mono_generic_param_info (param);
6046                 if (pinfo->pklass) {
6047                         mono_loader_unlock ();
6048                         return pinfo->pklass;
6049                 }
6050         } else {
6051                 pinfo = NULL;
6052                 image = NULL;
6053
6054                 klass = get_anon_gparam_class (param, is_mvar);
6055                 if (klass) {
6056                         mono_loader_unlock ();
6057                         return klass;
6058                 }
6059         }
6060
6061         if (!image && container) {
6062                 if (is_mvar) {
6063                         MonoMethod *method = container->owner.method;
6064                         image = (method && method->klass) ? method->klass->image : NULL;
6065                 } else {
6066                         MonoClass *klass = container->owner.klass;
6067                         // FIXME: 'klass' should not be null
6068                         //        But, monodis creates GenericContainers without associating a owner to it
6069                         image = klass ? klass->image : NULL;
6070                 }
6071         }
6072
6073         klass = make_generic_param_class (param, image, is_mvar, pinfo);
6074
6075         mono_memory_barrier ();
6076
6077         if (container)
6078                 pinfo->pklass = klass;
6079         else
6080                 set_anon_gparam_class (param, is_mvar, klass);
6081
6082         mono_loader_unlock ();
6083
6084         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6085         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6086
6087         return klass;
6088 }
6089
6090 MonoClass *
6091 mono_ptr_class_get (MonoType *type)
6092 {
6093         MonoClass *result;
6094         MonoClass *el_class;
6095         MonoImage *image;
6096         char *name;
6097
6098         el_class = mono_class_from_mono_type (type);
6099         image = el_class->image;
6100
6101         mono_loader_lock ();
6102
6103         if (!image->ptr_cache)
6104                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6105
6106         if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6107                 mono_loader_unlock ();
6108                 return result;
6109         }
6110         result = mono_image_alloc0 (image, sizeof (MonoClass));
6111
6112         classes_size += sizeof (MonoClass);
6113
6114         result->parent = NULL; /* no parent for PTR types */
6115         result->name_space = el_class->name_space;
6116         name = g_strdup_printf ("%s*", el_class->name);
6117         result->name = mono_image_strdup (image, name);
6118         g_free (name);
6119
6120         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6121
6122         result->image = el_class->image;
6123         result->inited = TRUE;
6124         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6125         /* Can pointers get boxed? */
6126         result->instance_size = sizeof (gpointer);
6127         result->cast_class = result->element_class = el_class;
6128         result->blittable = TRUE;
6129
6130         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6131         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6132         result->this_arg.byref = TRUE;
6133
6134         mono_class_setup_supertypes (result);
6135
6136         g_hash_table_insert (image->ptr_cache, el_class, result);
6137
6138         mono_loader_unlock ();
6139
6140         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6141
6142         return result;
6143 }
6144
6145 static MonoClass *
6146 mono_fnptr_class_get (MonoMethodSignature *sig)
6147 {
6148         MonoClass *result;
6149         static GHashTable *ptr_hash = NULL;
6150
6151         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6152
6153         mono_loader_lock ();
6154
6155         if (!ptr_hash)
6156                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6157         
6158         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6159                 mono_loader_unlock ();
6160                 return result;
6161         }
6162         result = g_new0 (MonoClass, 1);
6163
6164         result->parent = NULL; /* no parent for PTR types */
6165         result->name_space = "System";
6166         result->name = "MonoFNPtrFakeClass";
6167
6168         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6169
6170         result->image = mono_defaults.corlib; /* need to fix... */
6171         result->inited = TRUE;
6172         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6173         /* Can pointers get boxed? */
6174         result->instance_size = sizeof (gpointer);
6175         result->cast_class = result->element_class = result;
6176         result->blittable = TRUE;
6177
6178         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6179         result->this_arg.data.method = result->byval_arg.data.method = sig;
6180         result->this_arg.byref = TRUE;
6181         result->blittable = TRUE;
6182
6183         mono_class_setup_supertypes (result);
6184
6185         g_hash_table_insert (ptr_hash, sig, result);
6186
6187         mono_loader_unlock ();
6188
6189         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6190
6191         return result;
6192 }
6193
6194 MonoClass *
6195 mono_class_from_mono_type (MonoType *type)
6196 {
6197         switch (type->type) {
6198         case MONO_TYPE_OBJECT:
6199                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6200         case MONO_TYPE_VOID:
6201                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6202         case MONO_TYPE_BOOLEAN:
6203                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6204         case MONO_TYPE_CHAR:
6205                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6206         case MONO_TYPE_I1:
6207                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6208         case MONO_TYPE_U1:
6209                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6210         case MONO_TYPE_I2:
6211                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6212         case MONO_TYPE_U2:
6213                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6214         case MONO_TYPE_I4:
6215                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6216         case MONO_TYPE_U4:
6217                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6218         case MONO_TYPE_I:
6219                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6220         case MONO_TYPE_U:
6221                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6222         case MONO_TYPE_I8:
6223                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6224         case MONO_TYPE_U8:
6225                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6226         case MONO_TYPE_R4:
6227                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6228         case MONO_TYPE_R8:
6229                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6230         case MONO_TYPE_STRING:
6231                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6232         case MONO_TYPE_TYPEDBYREF:
6233                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6234         case MONO_TYPE_ARRAY:
6235                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6236         case MONO_TYPE_PTR:
6237                 return mono_ptr_class_get (type->data.type);
6238         case MONO_TYPE_FNPTR:
6239                 return mono_fnptr_class_get (type->data.method);
6240         case MONO_TYPE_SZARRAY:
6241                 return mono_array_class_get (type->data.klass, 1);
6242         case MONO_TYPE_CLASS:
6243         case MONO_TYPE_VALUETYPE:
6244                 return type->data.klass;
6245         case MONO_TYPE_GENERICINST:
6246                 return mono_generic_class_get_class (type->data.generic_class);
6247         case MONO_TYPE_VAR:
6248                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6249         case MONO_TYPE_MVAR:
6250                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6251         default:
6252                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6253                 g_assert_not_reached ();
6254         }
6255         
6256         return NULL;
6257 }
6258
6259 /**
6260  * mono_type_retrieve_from_typespec
6261  * @image: context where the image is created
6262  * @type_spec:  typespec token
6263  * @context: the generic context used to evaluate generic instantiations in
6264  */
6265 static MonoType *
6266 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6267 {
6268         MonoType *t = mono_type_create_from_typespec (image, type_spec);
6269
6270         mono_error_init (error);
6271         *did_inflate = FALSE;
6272
6273         if (!t) {
6274                 char *name = mono_class_name_from_token (image, type_spec);
6275                 char *assembly = mono_assembly_name_from_token (image, type_spec);
6276                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6277                 return NULL;
6278         }
6279
6280         if (context && (context->class_inst || context->method_inst)) {
6281                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6282
6283                 if (!mono_error_ok (error))
6284                         return NULL;
6285
6286                 if (inflated) {
6287                         t = inflated;
6288                         *did_inflate = TRUE;
6289                 }
6290         }
6291         return t;
6292 }
6293
6294 /**
6295  * mono_class_create_from_typespec
6296  * @image: context where the image is created
6297  * @type_spec:  typespec token
6298  * @context: the generic context used to evaluate generic instantiations in
6299  */
6300 static MonoClass *
6301 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6302 {
6303         MonoClass *ret;
6304         gboolean inflated = FALSE;
6305         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6306         if (!mono_error_ok (error))
6307                 return NULL;
6308         ret = mono_class_from_mono_type (t);
6309         if (inflated)
6310                 mono_metadata_free_type (t);
6311         return ret;
6312 }
6313
6314 /**
6315  * mono_bounded_array_class_get:
6316  * @element_class: element class 
6317  * @rank: the dimension of the array class
6318  * @bounded: whenever the array has non-zero bounds
6319  *
6320  * Returns: a class object describing the array with element type @element_type and 
6321  * dimension @rank. 
6322  */
6323 MonoClass *
6324 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6325 {
6326         MonoImage *image;
6327         MonoClass *class;
6328         MonoClass *parent = NULL;
6329         GSList *list, *rootlist = NULL;
6330         int nsize;
6331         char *name;
6332         gboolean corlib_type = FALSE;
6333
6334         g_assert (rank <= 255);
6335
6336         if (rank > 1)
6337                 /* bounded only matters for one-dimensional arrays */
6338                 bounded = FALSE;
6339
6340         image = eclass->image;
6341
6342         if (rank == 1 && !bounded) {
6343                 /* 
6344                  * This case is very frequent not just during compilation because of calls 
6345                  * from mono_class_from_mono_type (), mono_array_new (), 
6346                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6347                  */
6348                 EnterCriticalSection (&image->szarray_cache_lock);
6349                 if (!image->szarray_cache)
6350                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6351                 class = g_hash_table_lookup (image->szarray_cache, eclass);
6352                 LeaveCriticalSection (&image->szarray_cache_lock);
6353                 if (class)
6354                         return class;
6355
6356                 mono_loader_lock ();
6357         } else {
6358                 mono_loader_lock ();
6359
6360                 if (!image->array_cache)
6361                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6362
6363                 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6364                         for (; list; list = list->next) {
6365                                 class = list->data;
6366                                 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6367                                         mono_loader_unlock ();
6368                                         return class;
6369                                 }
6370                         }
6371                 }
6372         }
6373
6374         /* for the building corlib use System.Array from it */
6375         if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6376                 parent = mono_class_from_name (image, "System", "Array");
6377                 corlib_type = TRUE;
6378         } else {
6379                 parent = mono_defaults.array_class;
6380                 if (!parent->inited)
6381                         mono_class_init (parent);
6382         }
6383
6384         class = mono_image_alloc0 (image, sizeof (MonoClass));
6385
6386         class->image = image;
6387         class->name_space = eclass->name_space;
6388         nsize = strlen (eclass->name);
6389         name = g_malloc (nsize + 2 + rank + 1);
6390         memcpy (name, eclass->name, nsize);
6391         name [nsize] = '[';
6392         if (rank > 1)
6393                 memset (name + nsize + 1, ',', rank - 1);
6394         if (bounded)
6395                 name [nsize + rank] = '*';
6396         name [nsize + rank + bounded] = ']';
6397         name [nsize + rank + bounded + 1] = 0;
6398         class->name = mono_image_strdup (image, name);
6399         g_free (name);
6400
6401         mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6402
6403         classes_size += sizeof (MonoClass);
6404
6405         class->type_token = 0;
6406         /* all arrays are marked serializable and sealed, bug #42779 */
6407         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6408         class->parent = parent;
6409         class->instance_size = mono_class_instance_size (class->parent);
6410
6411         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6412                 /*Arrays of those two types are invalid.*/
6413                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6414         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6415                 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6416                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6417                         g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6418                 }
6419                 /* element_size -1 is ok as this is not an instantitable type*/
6420                 class->sizes.element_size = -1;
6421         } else
6422                 class->sizes.element_size = mono_class_array_element_size (eclass);
6423
6424         mono_class_setup_supertypes (class);
6425
6426         if (eclass->generic_class)
6427                 mono_class_init (eclass);
6428         if (!eclass->size_inited)
6429                 mono_class_setup_fields (eclass);
6430         if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6431                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6432
6433         class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6434
6435         class->rank = rank;
6436         
6437         if (eclass->enumtype)
6438                 class->cast_class = eclass->element_class;
6439         else
6440                 class->cast_class = eclass;
6441
6442         switch (class->cast_class->byval_arg.type) {
6443         case MONO_TYPE_I1:
6444                 class->cast_class = mono_defaults.byte_class;
6445                 break;
6446         case MONO_TYPE_U2:
6447                 class->cast_class = mono_defaults.int16_class;
6448                 break;
6449         case MONO_TYPE_U4:
6450 #if SIZEOF_VOID_P == 4
6451         case MONO_TYPE_I:
6452         case MONO_TYPE_U:
6453 #endif
6454                 class->cast_class = mono_defaults.int32_class;
6455                 break;
6456         case MONO_TYPE_U8:
6457 #if SIZEOF_VOID_P == 8
6458         case MONO_TYPE_I:
6459         case MONO_TYPE_U:
6460 #endif
6461                 class->cast_class = mono_defaults.int64_class;
6462                 break;
6463         }
6464
6465         class->element_class = eclass;
6466
6467         if ((rank > 1) || bounded) {
6468                 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6469                 class->byval_arg.type = MONO_TYPE_ARRAY;
6470                 class->byval_arg.data.array = at;
6471                 at->eklass = eclass;
6472                 at->rank = rank;
6473                 /* FIXME: complete.... */
6474         } else {
6475                 class->byval_arg.type = MONO_TYPE_SZARRAY;
6476                 class->byval_arg.data.klass = eclass;
6477         }
6478         class->this_arg = class->byval_arg;
6479         class->this_arg.byref = 1;
6480         if (corlib_type) {
6481                 class->inited = 1;
6482         }
6483
6484         class->generic_container = eclass->generic_container;
6485
6486         if (rank == 1 && !bounded) {
6487                 MonoClass *prev_class;
6488
6489                 EnterCriticalSection (&image->szarray_cache_lock);
6490                 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6491                 if (prev_class)
6492                         /* Someone got in before us */
6493                         class = prev_class;
6494                 else
6495                         g_hash_table_insert (image->szarray_cache, eclass, class);
6496                 LeaveCriticalSection (&image->szarray_cache_lock);
6497         } else {
6498                 list = g_slist_append (rootlist, class);
6499                 g_hash_table_insert (image->array_cache, eclass, list);
6500         }
6501
6502         mono_loader_unlock ();
6503
6504         mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6505
6506         return class;
6507 }
6508
6509 /**
6510  * mono_array_class_get:
6511  * @element_class: element class 
6512  * @rank: the dimension of the array class
6513  *
6514  * Returns: a class object describing the array with element type @element_type and 
6515  * dimension @rank. 
6516  */
6517 MonoClass *
6518 mono_array_class_get (MonoClass *eclass, guint32 rank)
6519 {
6520         return mono_bounded_array_class_get (eclass, rank, FALSE);
6521 }
6522
6523 /**
6524  * mono_class_instance_size:
6525  * @klass: a class 
6526  * 
6527  * Returns: the size of an object instance
6528  */
6529 gint32
6530 mono_class_instance_size (MonoClass *klass)
6531 {       
6532         if (!klass->size_inited)
6533                 mono_class_init (klass);
6534
6535         return klass->instance_size;
6536 }
6537
6538 /**
6539  * mono_class_min_align:
6540  * @klass: a class 
6541  * 
6542  * Returns: minimm alignment requirements 
6543  */
6544 gint32
6545 mono_class_min_align (MonoClass *klass)
6546 {       
6547         if (!klass->size_inited)
6548                 mono_class_init (klass);
6549
6550         return klass->min_align;
6551 }
6552
6553 /**
6554  * mono_class_value_size:
6555  * @klass: a class 
6556  *
6557  * This function is used for value types, and return the
6558  * space and the alignment to store that kind of value object.
6559  *
6560  * Returns: the size of a value of kind @klass
6561  */
6562 gint32
6563 mono_class_value_size      (MonoClass *klass, guint32 *align)
6564 {
6565         gint32 size;
6566
6567         /* fixme: check disable, because we still have external revereces to
6568          * mscorlib and Dummy Objects 
6569          */
6570         /*g_assert (klass->valuetype);*/
6571
6572         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6573
6574         if (align)
6575                 *align = klass->min_align;
6576
6577         return size;
6578 }
6579
6580 /**
6581  * mono_class_data_size:
6582  * @klass: a class 
6583  * 
6584  * Returns: the size of the static class data
6585  */
6586 gint32
6587 mono_class_data_size (MonoClass *klass)
6588 {       
6589         if (!klass->inited)
6590                 mono_class_init (klass);
6591
6592         /* in arrays, sizes.class_size is unioned with element_size
6593          * and arrays have no static fields
6594          */
6595         if (klass->rank)
6596                 return 0;
6597         return klass->sizes.class_size;
6598 }
6599
6600 /*
6601  * Auxiliary routine to mono_class_get_field
6602  *
6603  * Takes a field index instead of a field token.
6604  */
6605 static MonoClassField *
6606 mono_class_get_field_idx (MonoClass *class, int idx)
6607 {
6608         mono_class_setup_fields_locking (class);
6609         if (class->exception_type)
6610                 return NULL;
6611
6612         while (class) {
6613                 if (class->image->uncompressed_metadata) {
6614                         /* 
6615                          * class->field.first points to the FieldPtr table, while idx points into the
6616                          * Field table, so we have to do a search.
6617                          */
6618                         /*FIXME this is broken for types with multiple fields with the same name.*/
6619                         const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6620                         int i;
6621
6622                         for (i = 0; i < class->field.count; ++i)
6623                                 if (mono_field_get_name (&class->fields [i]) == name)
6624                                         return &class->fields [i];
6625                         g_assert_not_reached ();
6626                 } else {                        
6627                         if (class->field.count) {
6628                                 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6629                                         return &class->fields [idx - class->field.first];
6630                                 }
6631                         }
6632                 }
6633                 class = class->parent;
6634         }
6635         return NULL;
6636 }
6637
6638 /**
6639  * mono_class_get_field:
6640  * @class: the class to lookup the field.
6641  * @field_token: the field token
6642  *
6643  * Returns: A MonoClassField representing the type and offset of
6644  * the field, or a NULL value if the field does not belong to this
6645  * class.
6646  */
6647 MonoClassField *
6648 mono_class_get_field (MonoClass *class, guint32 field_token)
6649 {
6650         int idx = mono_metadata_token_index (field_token);
6651
6652         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6653
6654         return mono_class_get_field_idx (class, idx - 1);
6655 }
6656
6657 /**
6658  * mono_class_get_field_from_name:
6659  * @klass: the class to lookup the field.
6660  * @name: the field name
6661  *
6662  * Search the class @klass and it's parents for a field with the name @name.
6663  * 
6664  * Returns: the MonoClassField pointer of the named field or NULL
6665  */
6666 MonoClassField *
6667 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6668 {
6669         return mono_class_get_field_from_name_full (klass, name, NULL);
6670 }
6671
6672 /**
6673  * mono_class_get_field_from_name_full:
6674  * @klass: the class to lookup the field.
6675  * @name: the field name
6676  * @type: the type of the fields. This optional.
6677  *
6678  * Search the class @klass and it's parents for a field with the name @name and type @type.
6679  *
6680  * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6681  * of its generic type definition.
6682  *
6683  * Returns: the MonoClassField pointer of the named field or NULL
6684  */
6685 MonoClassField *
6686 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6687 {
6688         int i;
6689
6690         mono_class_setup_fields_locking (klass);
6691         if (klass->exception_type)
6692                 return NULL;
6693
6694         while (klass) {
6695                 for (i = 0; i < klass->field.count; ++i) {
6696                         MonoClassField *field = &klass->fields [i];
6697
6698                         if (strcmp (name, mono_field_get_name (field)) != 0)
6699                                 continue;
6700
6701                         if (type) {
6702                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6703                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6704                                         continue;
6705                         }
6706                         return field;
6707                 }
6708                 klass = klass->parent;
6709         }
6710         return NULL;
6711 }
6712
6713 /**
6714  * mono_class_get_field_token:
6715  * @field: the field we need the token of
6716  *
6717  * Get the token of a field. Note that the tokesn is only valid for the image
6718  * the field was loaded from. Don't use this function for fields in dynamic types.
6719  * 
6720  * Returns: the token representing the field in the image it was loaded from.
6721  */
6722 guint32
6723 mono_class_get_field_token (MonoClassField *field)
6724 {
6725         MonoClass *klass = field->parent;
6726         int i;
6727
6728         mono_class_setup_fields_locking (klass);
6729
6730         while (klass) {
6731                 if (!klass->fields)
6732                         return 0;
6733                 for (i = 0; i < klass->field.count; ++i) {
6734                         if (&klass->fields [i] == field) {
6735                                 int idx = klass->field.first + i + 1;
6736
6737                                 if (klass->image->uncompressed_metadata)
6738                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6739                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6740                         }
6741                 }
6742                 klass = klass->parent;
6743         }
6744
6745         g_assert_not_reached ();
6746         return 0;
6747 }
6748
6749 static int
6750 mono_field_get_index (MonoClassField *field)
6751 {
6752         int index = field - field->parent->fields;
6753
6754         g_assert (index >= 0 && index < field->parent->field.count);
6755
6756         return index;
6757 }
6758
6759 /*
6760  * mono_class_get_field_default_value:
6761  *
6762  * Return the default value of the field as a pointer into the metadata blob.
6763  */
6764 const char*
6765 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6766 {
6767         guint32 cindex;
6768         guint32 constant_cols [MONO_CONSTANT_SIZE];
6769         int field_index;
6770         MonoClass *klass = field->parent;
6771
6772         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6773
6774         if (!klass->ext || !klass->ext->field_def_values) {
6775                 mono_loader_lock ();
6776                 mono_class_alloc_ext (klass);
6777                 if (!klass->ext->field_def_values)
6778                         klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6779                 mono_loader_unlock ();
6780         }
6781
6782         field_index = mono_field_get_index (field);
6783                 
6784         if (!klass->ext->field_def_values [field_index].data) {
6785                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6786                 if (!cindex)
6787                         return NULL;
6788
6789                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6790
6791                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6792                 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6793                 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6794         }
6795
6796         *def_type = klass->ext->field_def_values [field_index].def_type;
6797         return klass->ext->field_def_values [field_index].data;
6798 }
6799
6800 static int
6801 mono_property_get_index (MonoProperty *prop)
6802 {
6803         int index = prop - prop->parent->ext->properties;
6804
6805         g_assert (index >= 0 && index < prop->parent->ext->property.count);
6806
6807         return index;
6808 }
6809
6810 /*
6811  * mono_class_get_property_default_value:
6812  *
6813  * Return the default value of the field as a pointer into the metadata blob.
6814  */
6815 const char*
6816 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6817 {
6818         guint32 cindex;
6819         guint32 constant_cols [MONO_CONSTANT_SIZE];
6820         MonoClass *klass = property->parent;
6821
6822         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6823         /*
6824          * We don't cache here because it is not used by C# so it's quite rare, but
6825          * we still do the lookup in klass->ext because that is where the data
6826          * is stored for dynamic assemblies.
6827          */
6828
6829         if (klass->image->dynamic) {
6830                 int prop_index = mono_property_get_index (property);
6831                 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6832                         *def_type = klass->ext->prop_def_values [prop_index].def_type;
6833                         return klass->ext->prop_def_values [prop_index].data;
6834                 }
6835                 return NULL;
6836         }
6837         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6838         if (!cindex)
6839                 return NULL;
6840
6841         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6842         *def_type = constant_cols [MONO_CONSTANT_TYPE];
6843         return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6844 }
6845
6846 guint32
6847 mono_class_get_event_token (MonoEvent *event)
6848 {
6849         MonoClass *klass = event->parent;
6850         int i;
6851
6852         while (klass) {
6853                 if (klass->ext) {
6854                         for (i = 0; i < klass->ext->event.count; ++i) {
6855                                 if (&klass->ext->events [i] == event)
6856                                         return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6857                         }
6858                 }
6859                 klass = klass->parent;
6860         }
6861
6862         g_assert_not_reached ();
6863         return 0;
6864 }
6865
6866 MonoProperty*
6867 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6868 {
6869         while (klass) {
6870                 MonoProperty* p;
6871                 gpointer iter = NULL;
6872                 while ((p = mono_class_get_properties (klass, &iter))) {
6873                         if (! strcmp (name, p->name))
6874                                 return p;
6875                 }
6876                 klass = klass->parent;
6877         }
6878         return NULL;
6879 }
6880
6881 guint32
6882 mono_class_get_property_token (MonoProperty *prop)
6883 {
6884         MonoClass *klass = prop->parent;
6885         while (klass) {
6886                 MonoProperty* p;
6887                 int i = 0;
6888                 gpointer iter = NULL;
6889                 while ((p = mono_class_get_properties (klass, &iter))) {
6890                         if (&klass->ext->properties [i] == prop)
6891                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6892                         
6893                         i ++;
6894                 }
6895                 klass = klass->parent;
6896         }
6897
6898         g_assert_not_reached ();
6899         return 0;
6900 }
6901
6902 char *
6903 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6904 {
6905         const char *name, *nspace;
6906         if (image->dynamic)
6907                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6908         
6909         switch (type_token & 0xff000000){
6910         case MONO_TOKEN_TYPE_DEF: {
6911                 guint32 cols [MONO_TYPEDEF_SIZE];
6912                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6913                 guint tidx = mono_metadata_token_index (type_token);
6914
6915                 if (tidx > tt->rows)
6916                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6917
6918                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6919                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6920                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6921                 if (strlen (nspace) == 0)
6922                         return g_strdup_printf ("%s", name);
6923                 else
6924                         return g_strdup_printf ("%s.%s", nspace, name);
6925         }
6926
6927         case MONO_TOKEN_TYPE_REF: {
6928                 MonoError error;
6929                 guint32 cols [MONO_TYPEREF_SIZE];
6930                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
6931                 guint tidx = mono_metadata_token_index (type_token);
6932
6933                 if (tidx > t->rows)
6934                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6935
6936                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6937                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6938                         mono_error_cleanup (&error);
6939                         return msg;
6940                 }
6941
6942                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6943                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6944                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6945                 if (strlen (nspace) == 0)
6946                         return g_strdup_printf ("%s", name);
6947                 else
6948                         return g_strdup_printf ("%s.%s", nspace, name);
6949         }
6950                 
6951         case MONO_TOKEN_TYPE_SPEC:
6952                 return g_strdup_printf ("Typespec 0x%08x", type_token);
6953         default:
6954                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6955         }
6956 }
6957
6958 static char *
6959 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
6960 {
6961         if (image->dynamic)
6962                 return g_strdup_printf ("DynamicAssembly %s", image->name);
6963         
6964         switch (type_token & 0xff000000){
6965         case MONO_TOKEN_TYPE_DEF:
6966                 if (image->assembly)
6967                         return mono_stringify_assembly_name (&image->assembly->aname);
6968                 else if (image->assembly_name)
6969                         return g_strdup (image->assembly_name);
6970                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
6971         case MONO_TOKEN_TYPE_REF: {
6972                 MonoError error;
6973                 MonoAssemblyName aname;
6974                 guint32 cols [MONO_TYPEREF_SIZE];
6975                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
6976                 guint32 idx = mono_metadata_token_index (type_token);
6977
6978                 if (idx > t->rows)
6979                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6980         
6981                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
6982                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6983                         mono_error_cleanup (&error);
6984                         return msg;
6985                 }
6986                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
6987
6988                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
6989                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
6990                 case MONO_RESOLTION_SCOPE_MODULE:
6991                         /* FIXME: */
6992                         return g_strdup ("");
6993                 case MONO_RESOLTION_SCOPE_MODULEREF:
6994                         /* FIXME: */
6995                         return g_strdup ("");
6996                 case MONO_RESOLTION_SCOPE_TYPEREF:
6997                         /* FIXME: */
6998                         return g_strdup ("");
6999                 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7000                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7001                         return mono_stringify_assembly_name (&aname);
7002                 default:
7003                         g_assert_not_reached ();
7004                 }
7005                 break;
7006         }
7007         case MONO_TOKEN_TYPE_SPEC:
7008                 /* FIXME: */
7009                 return g_strdup ("");
7010         default:
7011                 g_assert_not_reached ();
7012         }
7013
7014         return NULL;
7015 }
7016
7017 /**
7018  * mono_class_get_full:
7019  * @image: the image where the class resides
7020  * @type_token: the token for the class
7021  * @context: the generic context used to evaluate generic instantiations in
7022  *
7023  * Returns: the MonoClass that represents @type_token in @image
7024  */
7025 MonoClass *
7026 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7027 {
7028         MonoError error;
7029         MonoClass *class = NULL;
7030
7031         if (image->dynamic) {
7032                 int table = mono_metadata_token_table (type_token);
7033
7034                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7035                         mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7036                         return NULL;
7037                 }
7038                 return mono_lookup_dynamic_token (image, type_token, context);
7039         }
7040
7041         switch (type_token & 0xff000000){
7042         case MONO_TOKEN_TYPE_DEF:
7043                 class = mono_class_create_from_typedef (image, type_token, &error);
7044                 if (!mono_error_ok (&error)) {
7045                         mono_loader_set_error_from_mono_error (&error);
7046                         /*FIXME don't swallow the error message*/
7047                         mono_error_cleanup (&error);
7048                         return NULL;
7049                 }
7050                 break;          
7051         case MONO_TOKEN_TYPE_REF:
7052                 class = mono_class_from_typeref (image, type_token);
7053                 break;
7054         case MONO_TOKEN_TYPE_SPEC:
7055                 class = mono_class_create_from_typespec (image, type_token, context, &error);
7056                 if (!mono_error_ok (&error)) {
7057                         /*FIXME don't swallow the error message*/
7058                         mono_error_cleanup (&error);
7059                 }
7060                 break;
7061         default:
7062                 g_warning ("unknown token type %x", type_token & 0xff000000);
7063                 g_assert_not_reached ();
7064         }
7065
7066         if (!class){
7067                 char *name = mono_class_name_from_token (image, type_token);
7068                 char *assembly = mono_assembly_name_from_token (image, type_token);
7069                 mono_loader_set_error_type_load (name, assembly);
7070                 g_free (name);
7071                 g_free (assembly);
7072         }
7073
7074         return class;
7075 }
7076
7077
7078 /**
7079  * mono_type_get_full:
7080  * @image: the image where the type resides
7081  * @type_token: the token for the type
7082  * @context: the generic context used to evaluate generic instantiations in
7083  *
7084  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7085  * 
7086  * Returns: the MonoType that represents @type_token in @image
7087  */
7088 MonoType *
7089 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7090 {
7091         MonoError error;
7092         MonoType *type = NULL;
7093         gboolean inflated = FALSE;
7094
7095         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7096         if (image->dynamic)
7097                 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7098
7099         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7100                 MonoClass *class = mono_class_get_full (image, type_token, context);
7101                 return class ? mono_class_get_type (class) : NULL;
7102         }
7103
7104         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7105
7106         if (!mono_error_ok (&error)) {
7107                 /*FIXME don't swalloc the error message.*/
7108                 char *name = mono_class_name_from_token (image, type_token);
7109                 char *assembly = mono_assembly_name_from_token (image, type_token);
7110
7111                 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7112
7113                 mono_error_cleanup (&error);
7114                 mono_loader_set_error_type_load (name, assembly);
7115                 return NULL;
7116         }
7117
7118         if (inflated) {
7119                 MonoType *tmp = type;
7120                 type = mono_class_get_type (mono_class_from_mono_type (type));
7121                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7122                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7123                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7124                  *
7125                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7126                  * */
7127                 if (type->type != tmp->type)
7128                         type = tmp;
7129                 else
7130                         mono_metadata_free_type (tmp);
7131         }
7132         return type;
7133 }
7134
7135
7136 MonoClass *
7137 mono_class_get (MonoImage *image, guint32 type_token)
7138 {
7139         return mono_class_get_full (image, type_token, NULL);
7140 }
7141
7142 /**
7143  * mono_image_init_name_cache:
7144  *
7145  *  Initializes the class name cache stored in image->name_cache.
7146  *
7147  * LOCKING: Acquires the corresponding image lock.
7148  */
7149 void
7150 mono_image_init_name_cache (MonoImage *image)
7151 {
7152         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7153         guint32 cols [MONO_TYPEDEF_SIZE];
7154         const char *name;
7155         const char *nspace;
7156         guint32 i, visib, nspace_index;
7157         GHashTable *name_cache2, *nspace_table;
7158
7159         mono_image_lock (image);
7160
7161         if (image->name_cache) {
7162                 mono_image_unlock (image);
7163                 return;
7164         }
7165
7166         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7167
7168         if (image->dynamic) {
7169                 mono_image_unlock (image);
7170                 return;
7171         }
7172
7173         /* Temporary hash table to avoid lookups in the nspace_table */
7174         name_cache2 = g_hash_table_new (NULL, NULL);
7175
7176         for (i = 1; i <= t->rows; ++i) {
7177                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7178                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7179                 /*
7180                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7181                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7182                  */
7183                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7184                         continue;
7185                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7186                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7187
7188                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7189                 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7190                 if (!nspace_table) {
7191                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7192                         g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7193                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7194                                                                  nspace_table);
7195                 }
7196                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7197         }
7198
7199         /* Load type names from EXPORTEDTYPES table */
7200         {
7201                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7202                 guint32 cols [MONO_EXP_TYPE_SIZE];
7203                 int i;
7204
7205                 for (i = 0; i < t->rows; ++i) {
7206                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7207                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7208                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7209
7210                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7211                         nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7212                         if (!nspace_table) {
7213                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7214                                 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7215                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7216                                                                          nspace_table);
7217                         }
7218                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7219                 }
7220         }
7221
7222         g_hash_table_destroy (name_cache2);
7223         mono_image_unlock (image);
7224 }
7225
7226 /*FIXME Only dynamic assemblies should allow this operation.*/
7227 void
7228 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7229                                                           const char *name, guint32 index)
7230 {
7231         GHashTable *nspace_table;
7232         GHashTable *name_cache;
7233         guint32 old_index;
7234
7235         mono_image_lock (image);
7236
7237         if (!image->name_cache)
7238                 mono_image_init_name_cache (image);
7239
7240         name_cache = image->name_cache;
7241         if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7242                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7243                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7244         }
7245
7246         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7247                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7248
7249         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7250
7251         mono_image_unlock (image);
7252 }
7253
7254 typedef struct {
7255         gconstpointer key;
7256         gpointer value;
7257 } FindUserData;
7258
7259 static void
7260 find_nocase (gpointer key, gpointer value, gpointer user_data)
7261 {
7262         char *name = (char*)key;
7263         FindUserData *data = (FindUserData*)user_data;
7264
7265         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7266                 data->value = value;
7267 }
7268
7269 /**
7270  * mono_class_from_name_case:
7271  * @image: The MonoImage where the type is looked up in
7272  * @name_space: the type namespace
7273  * @name: the type short name.
7274  *
7275  * Obtains a MonoClass with a given namespace and a given name which
7276  * is located in the given MonoImage.   The namespace and name
7277  * lookups are case insensitive.
7278  */
7279 MonoClass *
7280 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7281 {
7282         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7283         guint32 cols [MONO_TYPEDEF_SIZE];
7284         const char *n;
7285         const char *nspace;
7286         guint32 i, visib;
7287
7288         if (image->dynamic) {
7289                 guint32 token = 0;
7290                 FindUserData user_data;
7291
7292                 mono_image_lock (image);
7293
7294                 if (!image->name_cache)
7295                         mono_image_init_name_cache (image);
7296
7297                 user_data.key = name_space;
7298                 user_data.value = NULL;
7299                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7300
7301                 if (user_data.value) {
7302                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7303
7304                         user_data.key = name;
7305                         user_data.value = NULL;
7306
7307                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7308                         
7309                         if (user_data.value)
7310                                 token = GPOINTER_TO_UINT (user_data.value);
7311                 }
7312
7313                 mono_image_unlock (image);
7314                 
7315                 if (token)
7316                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7317                 else
7318                         return NULL;
7319
7320         }
7321
7322         /* add a cache if needed */
7323         for (i = 1; i <= t->rows; ++i) {
7324                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7325                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7326                 /*
7327                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7328                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7329                  */
7330                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7331                         continue;
7332                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7333                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7334                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7335                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7336         }
7337         return NULL;
7338 }
7339
7340 static MonoClass*
7341 return_nested_in (MonoClass *class, char *nested)
7342 {
7343         MonoClass *found;
7344         char *s = strchr (nested, '/');
7345         gpointer iter = NULL;
7346
7347         if (s) {
7348                 *s = 0;
7349                 s++;
7350         }
7351
7352         while ((found = mono_class_get_nested_types (class, &iter))) {
7353                 if (strcmp (found->name, nested) == 0) {
7354                         if (s)
7355                                 return return_nested_in (found, s);
7356                         return found;
7357                 }
7358         }
7359         return NULL;
7360 }
7361
7362 static MonoClass*
7363 search_modules (MonoImage *image, const char *name_space, const char *name)
7364 {
7365         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7366         MonoImage *file_image;
7367         MonoClass *class;
7368         int i;
7369
7370         /* 
7371          * The EXPORTEDTYPES table only contains public types, so have to search the
7372          * modules as well.
7373          * Note: image->modules contains the contents of the MODULEREF table, while
7374          * the real module list is in the FILE table.
7375          */
7376         for (i = 0; i < file_table->rows; i++) {
7377                 guint32 cols [MONO_FILE_SIZE];
7378                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7379                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7380                         continue;
7381
7382                 file_image = mono_image_load_file_for_image (image, i + 1);
7383                 if (file_image) {
7384                         class = mono_class_from_name (file_image, name_space, name);
7385                         if (class)
7386                                 return class;
7387                 }
7388         }
7389
7390         return NULL;
7391 }
7392
7393 /**
7394  * mono_class_from_name:
7395  * @image: The MonoImage where the type is looked up in
7396  * @name_space: the type namespace
7397  * @name: the type short name.
7398  *
7399  * Obtains a MonoClass with a given namespace and a given name which
7400  * is located in the given MonoImage.   
7401  */
7402 MonoClass *
7403 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7404 {
7405         GHashTable *nspace_table;
7406         MonoImage *loaded_image;
7407         guint32 token = 0;
7408         int i;
7409         MonoClass *class;
7410         char *nested;
7411         char buf [1024];
7412
7413         if ((nested = strchr (name, '/'))) {
7414                 int pos = nested - name;
7415                 int len = strlen (name);
7416                 if (len > 1023)
7417                         return NULL;
7418                 memcpy (buf, name, len + 1);
7419                 buf [pos] = 0;
7420                 nested = buf + pos + 1;
7421                 name = buf;
7422         }
7423
7424         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7425         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7426                 gboolean res = get_class_from_name (image, name_space, name, &class);
7427                 if (res) {
7428                         if (!class)
7429                                 class = search_modules (image, name_space, name);
7430                         if (nested)
7431                                 return class ? return_nested_in (class, nested) : NULL;
7432                         else
7433                                 return class;
7434                 }
7435         }
7436
7437         mono_image_lock (image);
7438
7439         if (!image->name_cache)
7440                 mono_image_init_name_cache (image);
7441
7442         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7443
7444         if (nspace_table)
7445                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7446
7447         mono_image_unlock (image);
7448
7449         if (!token && image->dynamic && image->modules) {
7450                 /* Search modules as well */
7451                 for (i = 0; i < image->module_count; ++i) {
7452                         MonoImage *module = image->modules [i];
7453
7454                         class = mono_class_from_name (module, name_space, name);
7455                         if (class)
7456                                 return class;
7457                 }
7458         }
7459
7460         if (!token) {
7461                 class = search_modules (image, name_space, name);
7462                 if (class)
7463                         return class;
7464         }
7465
7466         if (!token)
7467                 return NULL;
7468
7469         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7470                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7471                 guint32 cols [MONO_EXP_TYPE_SIZE];
7472                 guint32 idx, impl;
7473
7474                 idx = mono_metadata_token_index (token);
7475
7476                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7477
7478                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7479                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7480                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7481                         if (!loaded_image)
7482                                 return NULL;
7483                         class = mono_class_from_name (loaded_image, name_space, name);
7484                         if (nested)
7485                                 return return_nested_in (class, nested);
7486                         return class;
7487                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7488                         guint32 assembly_idx;
7489
7490                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7491
7492                         mono_assembly_load_reference (image, assembly_idx - 1);
7493                         g_assert (image->references [assembly_idx - 1]);
7494                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7495                                 return NULL;                    
7496                         else
7497                                 /* FIXME: Cycle detection */
7498                                 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7499                 } else {
7500                         g_error ("not yet implemented");
7501                 }
7502         }
7503
7504         token = MONO_TOKEN_TYPE_DEF | token;
7505
7506         class = mono_class_get (image, token);
7507         if (nested)
7508                 return return_nested_in (class, nested);
7509         return class;
7510 }
7511
7512 /*FIXME test for interfaces with variant generic arguments*/
7513 gboolean
7514 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
7515                            gboolean check_interfaces)
7516 {
7517         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7518                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7519                         return TRUE;
7520         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7521                 int i;
7522
7523                 for (i = 0; i < klass->interface_count; i ++) {
7524                         MonoClass *ic =  klass->interfaces [i];
7525                         if (ic == klassc)
7526                                 return TRUE;
7527                 }
7528         } else {
7529                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7530                         return TRUE;
7531         }
7532
7533         /* 
7534          * MS.NET thinks interfaces are a subclass of Object, so we think it as
7535          * well.
7536          */
7537         if (klassc == mono_defaults.object_class)
7538                 return TRUE;
7539
7540         return FALSE;
7541 }
7542
7543 static gboolean
7544 mono_type_is_generic_argument (MonoType *type)
7545 {
7546         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7547 }
7548
7549 gboolean
7550 mono_class_has_variant_generic_params (MonoClass *klass)
7551 {
7552         int i;
7553         MonoGenericContainer *container;
7554
7555         if (!klass->generic_class)
7556                 return FALSE;
7557
7558         container = klass->generic_class->container_class->generic_container;
7559
7560         for (i = 0; i < container->type_argc; ++i)
7561                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7562                         return TRUE;
7563
7564         return FALSE;
7565 }
7566
7567 static gboolean
7568 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7569 {
7570         if (target == candidate)
7571                 return TRUE;
7572
7573         if (check_for_reference_conv &&
7574                 mono_type_is_generic_argument (&target->byval_arg) &&
7575                 mono_type_is_generic_argument (&candidate->byval_arg)) {
7576                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7577                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7578
7579                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7580                         return FALSE;
7581         }
7582         if (!mono_class_is_assignable_from (target, candidate))
7583                 return FALSE;
7584         return TRUE;
7585 }
7586
7587 /**
7588  * @container the generic container from the GTD
7589  * @klass: the class to be assigned to
7590  * @oklass: the source class
7591  * 
7592  * Both klass and oklass must be instances of the same generic interface.
7593  * Return true if @klass can be assigned to a @klass variable
7594  */
7595 gboolean
7596 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7597 {
7598         int j;
7599         MonoType **klass_argv, **oklass_argv;
7600         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7601         MonoGenericContainer *container = klass_gtd->generic_container;
7602
7603         if (klass == oklass)
7604                 return TRUE;
7605
7606         /*Viable candidates are instances of the same generic interface*/
7607         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7608                 return FALSE;
7609
7610         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7611         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7612
7613         for (j = 0; j < container->type_argc; ++j) {
7614                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7615                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7616
7617                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7618                         return FALSE;
7619
7620                 /*
7621                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7622                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7623                  */
7624                 if (param1_class != param2_class) {
7625                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7626                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7627                                         return FALSE;
7628                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7629                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7630                                         return FALSE;
7631                         } else
7632                                 return FALSE;
7633                 }
7634         }
7635         return TRUE;
7636 }
7637
7638 static gboolean
7639 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7640 {
7641         MonoGenericParam *gparam, *ogparam;
7642         MonoGenericParamInfo *tinfo, *cinfo;
7643         MonoClass **candidate_class;
7644         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7645         int tmask, cmask;
7646
7647         if (target == candidate)
7648                 return TRUE;
7649         if (target->byval_arg.type != candidate->byval_arg.type)
7650                 return FALSE;
7651
7652         gparam = target->byval_arg.data.generic_param;
7653         ogparam = candidate->byval_arg.data.generic_param;
7654         tinfo = mono_generic_param_info (gparam);
7655         cinfo = mono_generic_param_info (ogparam);
7656
7657         class_constraint_satisfied = FALSE;
7658         valuetype_constraint_satisfied = FALSE;
7659
7660         /*candidate must have a super set of target's special constraints*/
7661         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7662         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7663
7664         if (cinfo->constraints) {
7665                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7666                         MonoClass *cc = *candidate_class;
7667
7668                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7669                                 class_constraint_satisfied = TRUE;
7670                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7671                                 valuetype_constraint_satisfied = TRUE;
7672                 }
7673         }
7674         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7675         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7676
7677         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7678                 return FALSE;
7679         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7680                 return FALSE;
7681         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7682                 valuetype_constraint_satisfied)) {
7683                 return FALSE;
7684         }
7685
7686
7687         /*candidate type constraints must be a superset of target's*/
7688         if (tinfo->constraints) {
7689                 MonoClass **target_class;
7690                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7691                         MonoClass *tc = *target_class;
7692
7693                         /*
7694                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
7695                          * check it's constraints since it satisfy the constraint by itself.
7696                          */
7697                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7698                                 continue;
7699
7700                         if (!cinfo->constraints)
7701                                 return FALSE;
7702
7703                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7704                                 MonoClass *cc = *candidate_class;
7705
7706                                 if (mono_class_is_assignable_from (tc, cc))
7707                                         break;
7708
7709                                 /*
7710                                  * This happens when we have the following:
7711                                  *
7712                                  * Bar<K> where K : IFace
7713                                  * Foo<T, U> where T : U where U : IFace
7714                                  *      ...
7715                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7716                                  *
7717                                  */
7718                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7719                                         if (mono_gparam_is_assignable_from (target, cc))
7720                                                 break;
7721                                 }
7722                         }
7723                         if (!*candidate_class)
7724                                 return FALSE;
7725                 }
7726         }
7727
7728         /*candidate itself must have a constraint that satisfy target*/
7729         if (cinfo->constraints) {
7730                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7731                         MonoClass *cc = *candidate_class;
7732                         if (mono_class_is_assignable_from (target, cc))
7733                                 return TRUE;
7734                 }
7735         }
7736         return FALSE;
7737 }
7738
7739 /**
7740  * mono_class_is_assignable_from:
7741  * @klass: the class to be assigned to
7742  * @oklass: the source class
7743  *
7744  * Return: true if an instance of object oklass can be assigned to an
7745  * instance of object @klass
7746  */
7747 gboolean
7748 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7749 {
7750         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7751         if (!klass->inited)
7752                 mono_class_init (klass);
7753
7754         if (!oklass->inited)
7755                 mono_class_init (oklass);
7756
7757         if (klass->exception_type || oklass->exception_type)
7758                 return FALSE;
7759
7760         if (mono_type_is_generic_argument (&klass->byval_arg)) {
7761                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7762                         return FALSE;
7763                 return mono_gparam_is_assignable_from (klass, oklass);
7764         }
7765
7766         if (MONO_CLASS_IS_INTERFACE (klass)) {
7767                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7768                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7769                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7770                         int i;
7771
7772                         if (constraints) {
7773                                 for (i = 0; constraints [i]; ++i) {
7774                                         if (mono_class_is_assignable_from (klass, constraints [i]))
7775                                                 return TRUE;
7776                                 }
7777                         }
7778
7779                         return FALSE;
7780                 }
7781
7782                 /* interface_offsets might not be set for dynamic classes */
7783                 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7784                         /* 
7785                          * oklass might be a generic type parameter but they have 
7786                          * interface_offsets set.
7787                          */
7788                         return mono_reflection_call_is_assignable_to (oklass, klass);
7789                 if (!oklass->interface_bitmap)
7790                         /* Happens with generic instances of not-yet created dynamic types */
7791                         return FALSE;
7792                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7793                         return TRUE;
7794
7795                 if (mono_class_has_variant_generic_params (klass)) {
7796                         MonoError error;
7797                         int i;
7798                         mono_class_setup_interfaces (oklass, &error);
7799                         if (!mono_error_ok (&error)) {
7800                                 mono_error_cleanup (&error);
7801                                 return FALSE;
7802                         }
7803
7804                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7805                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
7806                                 MonoClass *iface = oklass->interfaces_packed [i];
7807
7808                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7809                                         return TRUE;
7810                         }
7811                 }
7812                 return FALSE;
7813         } else if (klass->delegate) {
7814                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7815                         return TRUE;
7816         }else if (klass->rank) {
7817                 MonoClass *eclass, *eoclass;
7818
7819                 if (oklass->rank != klass->rank)
7820                         return FALSE;
7821
7822                 /* vectors vs. one dimensional arrays */
7823                 if (oklass->byval_arg.type != klass->byval_arg.type)
7824                         return FALSE;
7825
7826                 eclass = klass->cast_class;
7827                 eoclass = oklass->cast_class;
7828
7829                 /* 
7830                  * a is b does not imply a[] is b[] when a is a valuetype, and
7831                  * b is a reference type.
7832                  */
7833
7834                 if (eoclass->valuetype) {
7835                         if ((eclass == mono_defaults.enum_class) || 
7836                                 (eclass == mono_defaults.enum_class->parent) ||
7837                                 (eclass == mono_defaults.object_class))
7838                                 return FALSE;
7839                 }
7840
7841                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7842         } else if (mono_class_is_nullable (klass)) {
7843                 if (mono_class_is_nullable (oklass))
7844                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7845                 else
7846                         return mono_class_is_assignable_from (klass->cast_class, oklass);
7847         } else if (klass == mono_defaults.object_class)
7848                 return TRUE;
7849
7850         return mono_class_has_parent (oklass, klass);
7851 }       
7852
7853 /*Check if @oklass is variant compatible with @klass.*/
7854 static gboolean
7855 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7856 {
7857         int j;
7858         MonoType **klass_argv, **oklass_argv;
7859         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7860         MonoGenericContainer *container = klass_gtd->generic_container;
7861
7862         /*Viable candidates are instances of the same generic interface*/
7863         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7864                 return FALSE;
7865
7866         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7867         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7868
7869         for (j = 0; j < container->type_argc; ++j) {
7870                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7871                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7872
7873                 if (param1_class->valuetype != param2_class->valuetype)
7874                         return FALSE;
7875
7876                 /*
7877                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7878                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7879                  */
7880                 if (param1_class != param2_class) {
7881                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7882                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7883                                         return FALSE;
7884                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7885                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7886                                         return FALSE;
7887                         } else
7888                                 return FALSE;
7889                 }
7890         }
7891         return TRUE;
7892 }
7893 /*Check if @candidate implements the interface @target*/
7894 static gboolean
7895 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7896 {
7897         MonoError error;
7898         int i;
7899         gboolean is_variant = mono_class_has_variant_generic_params (target);
7900
7901         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7902                 if (mono_class_is_variant_compatible_slow (target, candidate))
7903                         return TRUE;
7904         }
7905
7906         do {
7907                 if (candidate == target)
7908                         return TRUE;
7909
7910                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7911                 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7912                         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7913                         int j;
7914                         if (tb && tb->interfaces) {
7915                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7916                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7917                                         MonoClass *iface_class;
7918
7919                                         /* we can't realize the type here since it can do pretty much anything. */
7920                                         if (!iface->type)
7921                                                 continue;
7922                                         iface_class = mono_class_from_mono_type (iface->type);
7923                                         if (iface_class == target)
7924                                                 return TRUE;
7925                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
7926                                                 return TRUE;
7927                                         if (mono_class_implement_interface_slow (target, iface_class))
7928                                                 return TRUE;
7929                                 }
7930                         }
7931                 } else {
7932                         /*setup_interfaces don't mono_class_init anything*/
7933                         mono_class_setup_interfaces (candidate, &error);
7934                         if (!mono_error_ok (&error)) {
7935                                 mono_error_cleanup (&error);
7936                                 return FALSE;
7937                         }
7938
7939                         for (i = 0; i < candidate->interface_count; ++i) {
7940                                 if (candidate->interfaces [i] == target)
7941                                         return TRUE;
7942                                 
7943                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
7944                                         return TRUE;
7945
7946                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
7947                                         return TRUE;
7948                         }
7949                 }
7950                 candidate = candidate->parent;
7951         } while (candidate);
7952
7953         return FALSE;
7954 }
7955
7956 /*
7957  * Check if @oklass can be assigned to @klass.
7958  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
7959  */
7960 gboolean
7961 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
7962 {
7963         if (candidate == target)
7964                 return TRUE;
7965         if (target == mono_defaults.object_class)
7966                 return TRUE;
7967
7968         if (mono_class_has_parent (candidate, target))
7969                 return TRUE;
7970
7971         /*If target is not an interface there is no need to check them.*/
7972         if (MONO_CLASS_IS_INTERFACE (target))
7973                 return mono_class_implement_interface_slow (target, candidate);
7974
7975         if (target->delegate && mono_class_has_variant_generic_params (target))
7976                 return mono_class_is_variant_compatible (target, candidate, FALSE);
7977
7978         /*FIXME properly handle nullables and arrays */
7979         /*FIXME properly handle (M)VAR */
7980         return FALSE;
7981 }
7982
7983 /**
7984  * mono_class_get_cctor:
7985  * @klass: A MonoClass pointer
7986  *
7987  * Returns: the static constructor of @klass if it exists, NULL otherwise.
7988  */
7989 MonoMethod*
7990 mono_class_get_cctor (MonoClass *klass)
7991 {
7992         MonoCachedClassInfo cached_info;
7993
7994         if (klass->image->dynamic) {
7995                 /* 
7996                  * has_cctor is not set for these classes because mono_class_init () is
7997                  * not run for them.
7998                  */
7999                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8000         }
8001
8002         if (!klass->has_cctor)
8003                 return NULL;
8004
8005         if (mono_class_get_cached_class_info (klass, &cached_info))
8006                 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8007
8008         if (klass->generic_class && !klass->methods)
8009                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8010
8011         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8012 }
8013
8014 /**
8015  * mono_class_get_finalizer:
8016  * @klass: The MonoClass pointer
8017  *
8018  * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8019  */
8020 MonoMethod*
8021 mono_class_get_finalizer (MonoClass *klass)
8022 {
8023         MonoCachedClassInfo cached_info;
8024
8025         if (!klass->inited)
8026                 mono_class_init (klass);
8027         if (!mono_class_has_finalizer (klass))
8028                 return NULL;
8029
8030         if (mono_class_get_cached_class_info (klass, &cached_info))
8031                 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8032         else {
8033                 mono_class_setup_vtable (klass);
8034                 return klass->vtable [finalize_slot];
8035         }
8036 }
8037
8038 /**
8039  * mono_class_needs_cctor_run:
8040  * @klass: the MonoClass pointer
8041  * @caller: a MonoMethod describing the caller
8042  *
8043  * Determines whenever the class has a static constructor and whenever it
8044  * needs to be called when executing CALLER.
8045  */
8046 gboolean
8047 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8048 {
8049         MonoMethod *method;
8050
8051         method = mono_class_get_cctor (klass);
8052         if (method)
8053                 return (method == caller) ? FALSE : TRUE;
8054         else
8055                 return FALSE;
8056 }
8057
8058 /**
8059  * mono_class_array_element_size:
8060  * @klass: 
8061  *
8062  * Returns: the number of bytes an element of type @klass
8063  * uses when stored into an array.
8064  */
8065 gint32
8066 mono_class_array_element_size (MonoClass *klass)
8067 {
8068         MonoType *type = &klass->byval_arg;
8069         
8070 handle_enum:
8071         switch (type->type) {
8072         case MONO_TYPE_I1:
8073         case MONO_TYPE_U1:
8074         case MONO_TYPE_BOOLEAN:
8075                 return 1;
8076         case MONO_TYPE_I2:
8077         case MONO_TYPE_U2:
8078         case MONO_TYPE_CHAR:
8079                 return 2;
8080         case MONO_TYPE_I4:
8081         case MONO_TYPE_U4:
8082         case MONO_TYPE_R4:
8083                 return 4;
8084         case MONO_TYPE_I:
8085         case MONO_TYPE_U:
8086         case MONO_TYPE_PTR:
8087         case MONO_TYPE_CLASS:
8088         case MONO_TYPE_STRING:
8089         case MONO_TYPE_OBJECT:
8090         case MONO_TYPE_SZARRAY:
8091         case MONO_TYPE_ARRAY: 
8092         case MONO_TYPE_VAR:
8093         case MONO_TYPE_MVAR:   
8094                 return sizeof (gpointer);
8095         case MONO_TYPE_I8:
8096         case MONO_TYPE_U8:
8097         case MONO_TYPE_R8:
8098                 return 8;
8099         case MONO_TYPE_VALUETYPE:
8100                 if (type->data.klass->enumtype) {
8101                         type = mono_class_enum_basetype (type->data.klass);
8102                         klass = klass->element_class;
8103                         goto handle_enum;
8104                 }
8105                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8106         case MONO_TYPE_GENERICINST:
8107                 type = &type->data.generic_class->container_class->byval_arg;
8108                 goto handle_enum;
8109
8110         case MONO_TYPE_VOID:
8111                 return 0;
8112                 
8113         default:
8114                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8115         }
8116         return -1;
8117 }
8118
8119 /**
8120  * mono_array_element_size:
8121  * @ac: pointer to a #MonoArrayClass
8122  *
8123  * Returns: the size of single array element.
8124  */
8125 gint32
8126 mono_array_element_size (MonoClass *ac)
8127 {
8128         g_assert (ac->rank);
8129         return ac->sizes.element_size;
8130 }
8131
8132 gpointer
8133 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8134               MonoGenericContext *context)
8135 {
8136         if (image->dynamic) {
8137                 MonoClass *tmp_handle_class;
8138                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8139
8140                 g_assert (tmp_handle_class);
8141                 if (handle_class)
8142                         *handle_class = tmp_handle_class;
8143
8144                 if (tmp_handle_class == mono_defaults.typehandle_class)
8145                         return &((MonoClass*)obj)->byval_arg;
8146                 else
8147                         return obj;
8148         }
8149
8150         switch (token & 0xff000000) {
8151         case MONO_TOKEN_TYPE_DEF:
8152         case MONO_TOKEN_TYPE_REF:
8153         case MONO_TOKEN_TYPE_SPEC: {
8154                 MonoType *type;
8155                 if (handle_class)
8156                         *handle_class = mono_defaults.typehandle_class;
8157                 type = mono_type_get_full (image, token, context);
8158                 if (!type)
8159                         return NULL;
8160                 mono_class_init (mono_class_from_mono_type (type));
8161                 /* We return a MonoType* as handle */
8162                 return type;
8163         }
8164         case MONO_TOKEN_FIELD_DEF: {
8165                 MonoClass *class;
8166                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8167                 if (!type)
8168                         return NULL;
8169                 if (handle_class)
8170                         *handle_class = mono_defaults.fieldhandle_class;
8171                 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8172                 if (!class)
8173                         return NULL;
8174                 mono_class_init (class);
8175                 return mono_class_get_field (class, token);
8176         }
8177         case MONO_TOKEN_METHOD_DEF:
8178         case MONO_TOKEN_METHOD_SPEC: {
8179                 MonoMethod *meth;
8180                 meth = mono_get_method_full (image, token, NULL, context);
8181                 if (handle_class)
8182                         *handle_class = mono_defaults.methodhandle_class;
8183                 return meth;
8184         }
8185         case MONO_TOKEN_MEMBER_REF: {
8186                 guint32 cols [MONO_MEMBERREF_SIZE];
8187                 const char *sig;
8188                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8189                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8190                 mono_metadata_decode_blob_size (sig, &sig);
8191                 if (*sig == 0x6) { /* it's a field */
8192                         MonoClass *klass;
8193                         MonoClassField *field;
8194                         field = mono_field_from_token (image, token, &klass, context);
8195                         if (handle_class)
8196                                 *handle_class = mono_defaults.fieldhandle_class;
8197                         return field;
8198                 } else {
8199                         MonoMethod *meth;
8200                         meth = mono_get_method_full (image, token, NULL, context);
8201                         if (handle_class)
8202                                 *handle_class = mono_defaults.methodhandle_class;
8203                         return meth;
8204                 }
8205         }
8206         default:
8207                 g_warning ("Unknown token 0x%08x in ldtoken", token);
8208                 break;
8209         }
8210         return NULL;
8211 }
8212
8213 /**
8214  * This function might need to call runtime functions so it can't be part
8215  * of the metadata library.
8216  */
8217 static MonoLookupDynamicToken lookup_dynamic = NULL;
8218
8219 void
8220 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8221 {
8222         lookup_dynamic = func;
8223 }
8224
8225 gpointer
8226 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8227 {
8228         MonoClass *handle_class;
8229
8230         return lookup_dynamic (image, token, TRUE, &handle_class, context);
8231 }
8232
8233 gpointer
8234 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8235 {
8236         return lookup_dynamic (image, token, valid_token, handle_class, context);
8237 }
8238
8239 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8240
8241 void
8242 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8243 {
8244         get_cached_class_info = func;
8245 }
8246
8247 static gboolean
8248 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8249 {
8250         if (!get_cached_class_info)
8251                 return FALSE;
8252         else
8253                 return get_cached_class_info (klass, res);
8254 }
8255
8256 void
8257 mono_install_get_class_from_name (MonoGetClassFromName func)
8258 {
8259         get_class_from_name = func;
8260 }
8261
8262 MonoImage*
8263 mono_class_get_image (MonoClass *klass)
8264 {
8265         return klass->image;
8266 }
8267
8268 /**
8269  * mono_class_get_element_class:
8270  * @klass: the MonoClass to act on
8271  *
8272  * Returns: the element class of an array or an enumeration.
8273  */
8274 MonoClass*
8275 mono_class_get_element_class (MonoClass *klass)
8276 {
8277         return klass->element_class;
8278 }
8279
8280 /**
8281  * mono_class_is_valuetype:
8282  * @klass: the MonoClass to act on
8283  *
8284  * Returns: true if the MonoClass represents a ValueType.
8285  */
8286 gboolean
8287 mono_class_is_valuetype (MonoClass *klass)
8288 {
8289         return klass->valuetype;
8290 }
8291
8292 /**
8293  * mono_class_is_enum:
8294  * @klass: the MonoClass to act on
8295  *
8296  * Returns: true if the MonoClass represents an enumeration.
8297  */
8298 gboolean
8299 mono_class_is_enum (MonoClass *klass)
8300 {
8301         return klass->enumtype;
8302 }
8303
8304 /**
8305  * mono_class_enum_basetype:
8306  * @klass: the MonoClass to act on
8307  *
8308  * Returns: the underlying type representation for an enumeration.
8309  */
8310 MonoType*
8311 mono_class_enum_basetype (MonoClass *klass)
8312 {
8313         if (klass->element_class == klass)
8314                 /* SRE or broken types */
8315                 return NULL;
8316         else
8317                 return &klass->element_class->byval_arg;
8318 }
8319
8320 /**
8321  * mono_class_get_parent
8322  * @klass: the MonoClass to act on
8323  *
8324  * Returns: the parent class for this class.
8325  */
8326 MonoClass*
8327 mono_class_get_parent (MonoClass *klass)
8328 {
8329         return klass->parent;
8330 }
8331
8332 /**
8333  * mono_class_get_nesting_type;
8334  * @klass: the MonoClass to act on
8335  *
8336  * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8337  */
8338 MonoClass*
8339 mono_class_get_nesting_type (MonoClass *klass)
8340 {
8341         return klass->nested_in;
8342 }
8343
8344 /**
8345  * mono_class_get_rank:
8346  * @klass: the MonoClass to act on
8347  *
8348  * Returns: the rank for the array (the number of dimensions).
8349  */
8350 int
8351 mono_class_get_rank (MonoClass *klass)
8352 {
8353         return klass->rank;
8354 }
8355
8356 /**
8357  * mono_class_get_flags:
8358  * @klass: the MonoClass to act on
8359  *
8360  * The type flags from the TypeDef table from the metadata.
8361  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8362  * different values.
8363  *
8364  * Returns: the flags from the TypeDef table.
8365  */
8366 guint32
8367 mono_class_get_flags (MonoClass *klass)
8368 {
8369         return klass->flags;
8370 }
8371
8372 /**
8373  * mono_class_get_name
8374  * @klass: the MonoClass to act on
8375  *
8376  * Returns: the name of the class.
8377  */
8378 const char*
8379 mono_class_get_name (MonoClass *klass)
8380 {
8381         return klass->name;
8382 }
8383
8384 /**
8385  * mono_class_get_namespace:
8386  * @klass: the MonoClass to act on
8387  *
8388  * Returns: the namespace of the class.
8389  */
8390 const char*
8391 mono_class_get_namespace (MonoClass *klass)
8392 {
8393         return klass->name_space;
8394 }
8395
8396 /**
8397  * mono_class_get_type:
8398  * @klass: the MonoClass to act on
8399  *
8400  * This method returns the internal Type representation for the class.
8401  *
8402  * Returns: the MonoType from the class.
8403  */
8404 MonoType*
8405 mono_class_get_type (MonoClass *klass)
8406 {
8407         return &klass->byval_arg;
8408 }
8409
8410 /**
8411  * mono_class_get_type_token
8412  * @klass: the MonoClass to act on
8413  *
8414  * This method returns type token for the class.
8415  *
8416  * Returns: the type token for the class.
8417  */
8418 guint32
8419 mono_class_get_type_token (MonoClass *klass)
8420 {
8421   return klass->type_token;
8422 }
8423
8424 /**
8425  * mono_class_get_byref_type:
8426  * @klass: the MonoClass to act on
8427  *
8428  * 
8429  */
8430 MonoType*
8431 mono_class_get_byref_type (MonoClass *klass)
8432 {
8433         return &klass->this_arg;
8434 }
8435
8436 /**
8437  * mono_class_num_fields:
8438  * @klass: the MonoClass to act on
8439  *
8440  * Returns: the number of static and instance fields in the class.
8441  */
8442 int
8443 mono_class_num_fields (MonoClass *klass)
8444 {
8445         return klass->field.count;
8446 }
8447
8448 /**
8449  * mono_class_num_methods:
8450  * @klass: the MonoClass to act on
8451  *
8452  * Returns: the number of methods in the class.
8453  */
8454 int
8455 mono_class_num_methods (MonoClass *klass)
8456 {
8457         return klass->method.count;
8458 }
8459
8460 /**
8461  * mono_class_num_properties
8462  * @klass: the MonoClass to act on
8463  *
8464  * Returns: the number of properties in the class.
8465  */
8466 int
8467 mono_class_num_properties (MonoClass *klass)
8468 {
8469         mono_class_setup_properties (klass);
8470
8471         return klass->ext->property.count;
8472 }
8473
8474 /**
8475  * mono_class_num_events:
8476  * @klass: the MonoClass to act on
8477  *
8478  * Returns: the number of events in the class.
8479  */
8480 int
8481 mono_class_num_events (MonoClass *klass)
8482 {
8483         mono_class_setup_events (klass);
8484
8485         return klass->ext->event.count;
8486 }
8487
8488 /**
8489  * mono_class_get_fields:
8490  * @klass: the MonoClass to act on
8491  *
8492  * This routine is an iterator routine for retrieving the fields in a class.
8493  *
8494  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8495  * iterate over all of the elements.  When no more values are
8496  * available, the return value is NULL.
8497  *
8498  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8499  */
8500 MonoClassField*
8501 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8502 {
8503         MonoClassField* field;
8504         if (!iter)
8505                 return NULL;
8506         if (!*iter) {
8507                 mono_class_setup_fields_locking (klass);
8508                 if (klass->exception_type)
8509                         return NULL;
8510                 /* start from the first */
8511                 if (klass->field.count) {
8512                         return *iter = &klass->fields [0];
8513                 } else {
8514                         /* no fields */
8515                         return NULL;
8516                 }
8517         }
8518         field = *iter;
8519         field++;
8520         if (field < &klass->fields [klass->field.count]) {
8521                 return *iter = field;
8522         }
8523         return NULL;
8524 }
8525
8526 /**
8527  * mono_class_get_methods
8528  * @klass: the MonoClass to act on
8529  *
8530  * This routine is an iterator routine for retrieving the fields in a class.
8531  *
8532  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8533  * iterate over all of the elements.  When no more values are
8534  * available, the return value is NULL.
8535  *
8536  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8537  */
8538 MonoMethod*
8539 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8540 {
8541         MonoMethod** method;
8542         if (!iter)
8543                 return NULL;
8544         if (!*iter) {
8545                 mono_class_setup_methods (klass);
8546
8547                 /*
8548                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8549                  * FIXME we should better report this error to the caller
8550                  */
8551                 if (!klass->methods)
8552                         return NULL;
8553                 /* start from the first */
8554                 if (klass->method.count) {
8555                         *iter = &klass->methods [0];
8556                         return klass->methods [0];
8557                 } else {
8558                         /* no method */
8559                         return NULL;
8560                 }
8561         }
8562         method = *iter;
8563         method++;
8564         if (method < &klass->methods [klass->method.count]) {
8565                 *iter = method;
8566                 return *method;
8567         }
8568         return NULL;
8569 }
8570
8571 /*
8572  * mono_class_get_virtual_methods:
8573  *
8574  *   Iterate over the virtual methods of KLASS.
8575  *
8576  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8577  */
8578 static MonoMethod*
8579 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8580 {
8581         MonoMethod** method;
8582         if (!iter)
8583                 return NULL;
8584         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8585                 if (!*iter) {
8586                         mono_class_setup_methods (klass);
8587                         /*
8588                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8589                          * FIXME we should better report this error to the caller
8590                          */
8591                         if (!klass->methods)
8592                                 return NULL;
8593                         /* start from the first */
8594                         method = &klass->methods [0];
8595                 } else {
8596                         method = *iter;
8597                         method++;
8598                 }
8599                 while (method < &klass->methods [klass->method.count]) {
8600                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8601                                 break;
8602                         method ++;
8603                 }
8604                 if (method < &klass->methods [klass->method.count]) {
8605                         *iter = method;
8606                         return *method;
8607                 } else {
8608                         return NULL;
8609                 }
8610         } else {
8611                 /* Search directly in metadata to avoid calling setup_methods () */
8612                 MonoMethod *res = NULL;
8613                 int i, start_index;
8614
8615                 if (!*iter) {
8616                         start_index = 0;
8617                 } else {
8618                         start_index = GPOINTER_TO_UINT (*iter);
8619                 }
8620
8621                 for (i = start_index; i < klass->method.count; ++i) {
8622                         guint32 flags;
8623
8624                         /* class->method.first points into the methodptr table */
8625                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8626
8627                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8628                                 break;
8629                 }
8630
8631                 if (i < klass->method.count) {
8632                         res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8633                         /* Add 1 here so the if (*iter) check fails */
8634                         *iter = GUINT_TO_POINTER (i + 1);
8635                         return res;
8636                 } else {
8637                         return NULL;
8638                 }
8639         }
8640 }
8641
8642 /**
8643  * mono_class_get_properties:
8644  * @klass: the MonoClass to act on
8645  *
8646  * This routine is an iterator routine for retrieving the properties in a class.
8647  *
8648  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8649  * iterate over all of the elements.  When no more values are
8650  * available, the return value is NULL.
8651  *
8652  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8653  */
8654 MonoProperty*
8655 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8656 {
8657         MonoProperty* property;
8658         if (!iter)
8659                 return NULL;
8660         if (!*iter) {
8661                 mono_class_setup_properties (klass);
8662                 /* start from the first */
8663                 if (klass->ext->property.count) {
8664                         return *iter = &klass->ext->properties [0];
8665                 } else {
8666                         /* no fields */
8667                         return NULL;
8668                 }
8669         }
8670         property = *iter;
8671         property++;
8672         if (property < &klass->ext->properties [klass->ext->property.count]) {
8673                 return *iter = property;
8674         }
8675         return NULL;
8676 }
8677
8678 /**
8679  * mono_class_get_events:
8680  * @klass: the MonoClass to act on
8681  *
8682  * This routine is an iterator routine for retrieving the properties in a class.
8683  *
8684  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8685  * iterate over all of the elements.  When no more values are
8686  * available, the return value is NULL.
8687  *
8688  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8689  */
8690 MonoEvent*
8691 mono_class_get_events (MonoClass* klass, gpointer *iter)
8692 {
8693         MonoEvent* event;
8694         if (!iter)
8695                 return NULL;
8696         if (!*iter) {
8697                 mono_class_setup_events (klass);
8698                 /* start from the first */
8699                 if (klass->ext->event.count) {
8700                         return *iter = &klass->ext->events [0];
8701                 } else {
8702                         /* no fields */
8703                         return NULL;
8704                 }
8705         }
8706         event = *iter;
8707         event++;
8708         if (event < &klass->ext->events [klass->ext->event.count]) {
8709                 return *iter = event;
8710         }
8711         return NULL;
8712 }
8713
8714 /**
8715  * mono_class_get_interfaces
8716  * @klass: the MonoClass to act on
8717  *
8718  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8719  *
8720  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8721  * iterate over all of the elements.  When no more values are
8722  * available, the return value is NULL.
8723  *
8724  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8725  */
8726 MonoClass*
8727 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8728 {
8729         MonoError error;
8730         MonoClass** iface;
8731         if (!iter)
8732                 return NULL;
8733         if (!*iter) {
8734                 if (!klass->inited)
8735                         mono_class_init (klass);
8736                 if (!klass->interfaces_inited) {
8737                         mono_class_setup_interfaces (klass, &error);
8738                         if (!mono_error_ok (&error)) {
8739                                 mono_error_cleanup (&error);
8740                                 return NULL;
8741                         }
8742                 }
8743                 /* start from the first */
8744                 if (klass->interface_count) {
8745                         *iter = &klass->interfaces [0];
8746                         return klass->interfaces [0];
8747                 } else {
8748                         /* no interface */
8749                         return NULL;
8750                 }
8751         }
8752         iface = *iter;
8753         iface++;
8754         if (iface < &klass->interfaces [klass->interface_count]) {
8755                 *iter = iface;
8756                 return *iface;
8757         }
8758         return NULL;
8759 }
8760
8761 /**
8762  * mono_class_get_nested_types
8763  * @klass: the MonoClass to act on
8764  *
8765  * This routine is an iterator routine for retrieving the nested types of a class.
8766  * This works only if @klass is non-generic, or a generic type definition.
8767  *
8768  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8769  * iterate over all of the elements.  When no more values are
8770  * available, the return value is NULL.
8771  *
8772  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8773  */
8774 MonoClass*
8775 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8776 {
8777         MonoError error;
8778         GList *item;
8779         int i;
8780
8781         if (!iter)
8782                 return NULL;
8783         if (!klass->nested_classes_inited) {
8784                 if (!klass->type_token)
8785                         klass->nested_classes_inited = TRUE;
8786                 mono_loader_lock ();
8787                 if (!klass->nested_classes_inited) {
8788                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8789                         while (i) {
8790                                 MonoClass* nclass;
8791                                 guint32 cols [MONO_NESTED_CLASS_SIZE];
8792                                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8793                                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8794                                 if (!mono_error_ok (&error)) {
8795                                         /*FIXME don't swallow the error message*/
8796                                         mono_error_cleanup (&error);
8797
8798                                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8799                                         continue;
8800                                 }
8801                                 mono_class_alloc_ext (klass);
8802                                 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8803
8804                                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8805                         }
8806                 }
8807                 mono_memory_barrier ();
8808                 klass->nested_classes_inited = TRUE;
8809                 mono_loader_unlock ();
8810         }
8811
8812         if (!*iter) {
8813                 /* start from the first */
8814                 if (klass->ext && klass->ext->nested_classes) {
8815                         *iter = klass->ext->nested_classes;
8816                         return klass->ext->nested_classes->data;
8817                 } else {
8818                         /* no nested types */
8819                         return NULL;
8820                 }
8821         }
8822         item = *iter;
8823         item = item->next;
8824         if (item) {
8825                 *iter = item;
8826                 return item->data;
8827         }
8828         return NULL;
8829 }
8830
8831 /**
8832  * mono_field_get_name:
8833  * @field: the MonoClassField to act on
8834  *
8835  * Returns: the name of the field.
8836  */
8837 const char*
8838 mono_field_get_name (MonoClassField *field)
8839 {
8840         return field->name;
8841 }
8842
8843 /**
8844  * mono_field_get_type:
8845  * @field: the MonoClassField to act on
8846  *
8847  * Returns: MonoType of the field.
8848  */
8849 MonoType*
8850 mono_field_get_type (MonoClassField *field)
8851 {
8852         MonoError error;
8853         MonoType *type = mono_field_get_type_checked (field, &error);
8854         if (!mono_error_ok (&error)) {
8855                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8856                 mono_error_cleanup (&error);
8857         }
8858         return type;
8859 }
8860
8861
8862 /**
8863  * mono_field_get_type_checked:
8864  * @field: the MonoClassField to act on
8865  * @error: used to return any erro found while retrieving @field type
8866  *
8867  * Returns: MonoType of the field.
8868  */
8869 MonoType*
8870 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8871 {
8872         mono_error_init (error);
8873         if (!field->type)
8874                 mono_field_resolve_type (field, error);
8875         return field->type;
8876 }
8877
8878 /**
8879  * mono_field_get_parent:
8880  * @field: the MonoClassField to act on
8881  *
8882  * Returns: MonoClass where the field was defined.
8883  */
8884 MonoClass*
8885 mono_field_get_parent (MonoClassField *field)
8886 {
8887         return field->parent;
8888 }
8889
8890 /**
8891  * mono_field_get_flags;
8892  * @field: the MonoClassField to act on
8893  *
8894  * The metadata flags for a field are encoded using the
8895  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
8896  *
8897  * Returns: the flags for the field.
8898  */
8899 guint32
8900 mono_field_get_flags (MonoClassField *field)
8901 {
8902         if (!field->type)
8903                 return mono_field_resolve_flags (field);
8904         return field->type->attrs;
8905 }
8906
8907 /**
8908  * mono_field_get_offset;
8909  * @field: the MonoClassField to act on
8910  *
8911  * Returns: the field offset.
8912  */
8913 guint32
8914 mono_field_get_offset (MonoClassField *field)
8915 {
8916         return field->offset;
8917 }
8918
8919 static const char *
8920 mono_field_get_rva (MonoClassField *field)
8921 {
8922         guint32 rva;
8923         int field_index;
8924         MonoClass *klass = field->parent;
8925
8926         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
8927
8928         if (!klass->ext || !klass->ext->field_def_values) {
8929                 mono_loader_lock ();
8930                 mono_class_alloc_ext (klass);
8931                 if (!klass->ext->field_def_values)
8932                         klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
8933                 mono_loader_unlock ();
8934         }
8935
8936         field_index = mono_field_get_index (field);
8937                 
8938         if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
8939                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
8940                 if (!rva)
8941                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
8942                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
8943         }
8944
8945         return klass->ext->field_def_values [field_index].data;
8946 }
8947
8948 /**
8949  * mono_field_get_data;
8950  * @field: the MonoClassField to act on
8951  *
8952  * Returns: pointer to the metadata constant value or to the field
8953  * data if it has an RVA flag.
8954  */
8955 const char *
8956 mono_field_get_data (MonoClassField *field)
8957 {
8958         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
8959                 MonoTypeEnum def_type;
8960
8961                 return mono_class_get_field_default_value (field, &def_type);
8962         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
8963                 return mono_field_get_rva (field);
8964         } else {
8965                 return NULL;
8966         }
8967 }
8968
8969 /**
8970  * mono_property_get_name: 
8971  * @prop: the MonoProperty to act on
8972  *
8973  * Returns: the name of the property
8974  */
8975 const char*
8976 mono_property_get_name (MonoProperty *prop)
8977 {
8978         return prop->name;
8979 }
8980
8981 /**
8982  * mono_property_get_set_method
8983  * @prop: the MonoProperty to act on.
8984  *
8985  * Returns: the setter method of the property (A MonoMethod)
8986  */
8987 MonoMethod*
8988 mono_property_get_set_method (MonoProperty *prop)
8989 {
8990         return prop->set;
8991 }
8992
8993 /**
8994  * mono_property_get_get_method
8995  * @prop: the MonoProperty to act on.
8996  *
8997  * Returns: the setter method of the property (A MonoMethod)
8998  */
8999 MonoMethod*
9000 mono_property_get_get_method (MonoProperty *prop)
9001 {
9002         return prop->get;
9003 }
9004
9005 /**
9006  * mono_property_get_parent:
9007  * @prop: the MonoProperty to act on.
9008  *
9009  * Returns: the MonoClass where the property was defined.
9010  */
9011 MonoClass*
9012 mono_property_get_parent (MonoProperty *prop)
9013 {
9014         return prop->parent;
9015 }
9016
9017 /**
9018  * mono_property_get_flags:
9019  * @prop: the MonoProperty to act on.
9020  *
9021  * The metadata flags for a property are encoded using the
9022  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9023  *
9024  * Returns: the flags for the property.
9025  */
9026 guint32
9027 mono_property_get_flags (MonoProperty *prop)
9028 {
9029         return prop->attrs;
9030 }
9031
9032 /**
9033  * mono_event_get_name:
9034  * @event: the MonoEvent to act on
9035  *
9036  * Returns: the name of the event.
9037  */
9038 const char*
9039 mono_event_get_name (MonoEvent *event)
9040 {
9041         return event->name;
9042 }
9043
9044 /**
9045  * mono_event_get_add_method:
9046  * @event: The MonoEvent to act on.
9047  *
9048  * Returns: the @add' method for the event (a MonoMethod).
9049  */
9050 MonoMethod*
9051 mono_event_get_add_method (MonoEvent *event)
9052 {
9053         return event->add;
9054 }
9055
9056 /**
9057  * mono_event_get_remove_method:
9058  * @event: The MonoEvent to act on.
9059  *
9060  * Returns: the @remove method for the event (a MonoMethod).
9061  */
9062 MonoMethod*
9063 mono_event_get_remove_method (MonoEvent *event)
9064 {
9065         return event->remove;
9066 }
9067
9068 /**
9069  * mono_event_get_raise_method:
9070  * @event: The MonoEvent to act on.
9071  *
9072  * Returns: the @raise method for the event (a MonoMethod).
9073  */
9074 MonoMethod*
9075 mono_event_get_raise_method (MonoEvent *event)
9076 {
9077         return event->raise;
9078 }
9079
9080 /**
9081  * mono_event_get_parent:
9082  * @event: the MonoEvent to act on.
9083  *
9084  * Returns: the MonoClass where the event is defined.
9085  */
9086 MonoClass*
9087 mono_event_get_parent (MonoEvent *event)
9088 {
9089         return event->parent;
9090 }
9091
9092 /**
9093  * mono_event_get_flags
9094  * @event: the MonoEvent to act on.
9095  *
9096  * The metadata flags for an event are encoded using the
9097  * EVENT_* constants.  See the tabledefs.h file for details.
9098  *
9099  * Returns: the flags for the event.
9100  */
9101 guint32
9102 mono_event_get_flags (MonoEvent *event)
9103 {
9104         return event->attrs;
9105 }
9106
9107 /**
9108  * mono_class_get_method_from_name:
9109  * @klass: where to look for the method
9110  * @name_space: name of the method
9111  * @param_count: number of parameters. -1 for any number.
9112  *
9113  * Obtains a MonoMethod with a given name and number of parameters.
9114  * It only works if there are no multiple signatures for any given method name.
9115  */
9116 MonoMethod *
9117 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9118 {
9119         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9120 }
9121
9122 static MonoMethod*
9123 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9124 {
9125         MonoMethod *res = NULL;
9126         int i;
9127
9128         /* Search directly in the metadata to avoid calling setup_methods () */
9129         for (i = 0; i < klass->method.count; ++i) {
9130                 guint32 cols [MONO_METHOD_SIZE];
9131                 MonoMethod *method;
9132                 MonoMethodSignature *sig;
9133
9134                 /* class->method.first points into the methodptr table */
9135                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9136
9137                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9138                         method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9139                         if (param_count == -1) {
9140                                 res = method;
9141                                 break;
9142                         }
9143                         sig = mono_method_signature (method);
9144                         if (sig && sig->param_count == param_count) {
9145                                 res = method;
9146                                 break;
9147                         }
9148                 }
9149         }
9150
9151         return res;
9152 }
9153
9154 /**
9155  * mono_class_get_method_from_name_flags:
9156  * @klass: where to look for the method
9157  * @name_space: name of the method
9158  * @param_count: number of parameters. -1 for any number.
9159  * @flags: flags which must be set in the method
9160  *
9161  * Obtains a MonoMethod with a given name and number of parameters.
9162  * It only works if there are no multiple signatures for any given method name.
9163  */
9164 MonoMethod *
9165 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9166 {
9167         MonoMethod *res = NULL;
9168         int i;
9169
9170         mono_class_init (klass);
9171
9172         if (klass->generic_class && !klass->methods) {
9173                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9174                 if (res)
9175                         res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9176                 return res;
9177         }
9178
9179         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9180                 mono_class_setup_methods (klass);
9181                 /*
9182                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9183                 See mono/tests/array_load_exception.il
9184                 FIXME we should better report this error to the caller
9185                  */
9186                 if (!klass->methods)
9187                         return NULL;
9188                 for (i = 0; i < klass->method.count; ++i) {
9189                         MonoMethod *method = klass->methods [i];
9190
9191                         if (method->name[0] == name [0] && 
9192                                 !strcmp (name, method->name) &&
9193                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9194                                 ((method->flags & flags) == flags)) {
9195                                 res = method;
9196                                 break;
9197                         }
9198                 }
9199         }
9200         else {
9201             res = find_method_in_metadata (klass, name, param_count, flags);
9202         }
9203
9204         return res;
9205 }
9206
9207 /**
9208  * mono_class_set_failure:
9209  * @klass: class in which the failure was detected
9210  * @ex_type: the kind of exception/error to be thrown (later)
9211  * @ex_data: exception data (specific to each type of exception/error)
9212  *
9213  * Keep a detected failure informations in the class for later processing.
9214  * Note that only the first failure is kept.
9215  *
9216  * LOCKING: Acquires the loader lock.
9217  */
9218 gboolean
9219 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9220 {
9221         if (klass->exception_type)
9222                 return FALSE;
9223
9224         mono_loader_lock ();
9225         klass->exception_type = ex_type;
9226         if (ex_data)
9227                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9228         mono_loader_unlock ();
9229
9230         return TRUE;
9231 }
9232
9233 /*
9234  * mono_class_get_exception_data:
9235  *
9236  *   Return the exception_data property of KLASS.
9237  *
9238  * LOCKING: Acquires the loader lock.
9239  */
9240 gpointer
9241 mono_class_get_exception_data (MonoClass *klass)
9242 {
9243         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9244 }
9245
9246 /**
9247  * mono_classes_init:
9248  *
9249  * Initialize the resources used by this module.
9250  */
9251 void
9252 mono_classes_init (void)
9253 {
9254         mono_counters_register ("Inflated methods size",
9255                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9256         mono_counters_register ("Inflated classes",
9257                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9258         mono_counters_register ("Inflated classes size",
9259                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9260         mono_counters_register ("MonoClass size",
9261                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9262         mono_counters_register ("MonoClassExt size",
9263                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9264 }
9265
9266 /**
9267  * mono_classes_cleanup:
9268  *
9269  * Free the resources used by this module.
9270  */
9271 void
9272 mono_classes_cleanup (void)
9273 {
9274         if (global_interface_bitset)
9275                 mono_bitset_free (global_interface_bitset);
9276         global_interface_bitset = NULL;
9277 }
9278
9279 /**
9280  * mono_class_get_exception_for_failure:
9281  * @klass: class in which the failure was detected
9282  *
9283  * Return a constructed MonoException than the caller can then throw
9284  * using mono_raise_exception - or NULL if no failure is present (or
9285  * doesn't result in an exception).
9286  */
9287 MonoException*
9288 mono_class_get_exception_for_failure (MonoClass *klass)
9289 {
9290         gpointer exception_data = mono_class_get_exception_data (klass);
9291
9292         switch (klass->exception_type) {
9293 #ifndef DISABLE_SECURITY
9294         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9295                 MonoDomain *domain = mono_domain_get ();
9296                 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9297                 MonoMethod *method = exception_data;
9298                 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9299                 MonoObject *exc = NULL;
9300                 gpointer args [4];
9301
9302                 args [0] = &error;
9303                 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9304                 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9305                 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9306
9307                 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9308                 return (MonoException*) exc;
9309         }
9310 #endif
9311         case MONO_EXCEPTION_TYPE_LOAD: {
9312                 MonoString *name;
9313                 MonoException *ex;
9314                 char *str = mono_type_get_full_name (klass);
9315                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9316                 name = mono_string_new (mono_domain_get (), str);
9317                 g_free (str);
9318                 ex = mono_get_exception_type_load (name, astr);
9319                 g_free (astr);
9320                 return ex;
9321         }
9322         case MONO_EXCEPTION_MISSING_METHOD: {
9323                 char *class_name = exception_data;
9324                 char *assembly_name = class_name + strlen (class_name) + 1;
9325
9326                 return mono_get_exception_missing_method (class_name, assembly_name);
9327         }
9328         case MONO_EXCEPTION_MISSING_FIELD: {
9329                 char *class_name = exception_data;
9330                 char *member_name = class_name + strlen (class_name) + 1;
9331
9332                 return mono_get_exception_missing_field (class_name, member_name);
9333         }
9334         case MONO_EXCEPTION_FILE_NOT_FOUND: {
9335                 char *msg_format = exception_data;
9336                 char *assembly_name = msg_format + strlen (msg_format) + 1;
9337                 char *msg = g_strdup_printf (msg_format, assembly_name);
9338                 MonoException *ex;
9339
9340                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9341
9342                 g_free (msg);
9343
9344                 return ex;
9345         }
9346         case MONO_EXCEPTION_BAD_IMAGE: {
9347                 return mono_get_exception_bad_image_format (exception_data);
9348         }
9349         default: {
9350                 MonoLoaderError *error;
9351                 MonoException *ex;
9352                 
9353                 error = mono_loader_get_last_error ();
9354                 if (error != NULL){
9355                         ex = mono_loader_error_prepare_exception (error);
9356                         return ex;
9357                 }
9358                 
9359                 /* TODO - handle other class related failures */
9360                 return NULL;
9361         }
9362         }
9363 }
9364
9365 static gboolean
9366 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9367  {
9368         outer_klass = mono_class_get_generic_type_definition (outer_klass);
9369         inner_klass = mono_class_get_generic_type_definition (inner_klass);
9370         do {
9371                 if (outer_klass == inner_klass)
9372                         return TRUE;
9373                 inner_klass = inner_klass->nested_in;
9374         } while (inner_klass);
9375         return FALSE;
9376 }
9377
9378 MonoClass *
9379 mono_class_get_generic_type_definition (MonoClass *klass)
9380 {
9381         return klass->generic_class ? klass->generic_class->container_class : klass;
9382 }
9383
9384 /*
9385  * Check if @klass is a subtype of @parent ignoring generic instantiations.
9386  * 
9387  * Generic instantiations are ignored for all super types of @klass.
9388  * 
9389  * Visibility checks ignoring generic instantiations.  
9390  */
9391 gboolean
9392 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9393 {
9394         int i;
9395         klass = mono_class_get_generic_type_definition (klass);
9396         parent = mono_class_get_generic_type_definition (parent);
9397         mono_class_setup_supertypes (klass);
9398
9399         for (i = 0; i < klass->idepth; ++i) {
9400                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9401                         return TRUE;
9402         }
9403         return FALSE;
9404 }
9405 /*
9406  * Subtype can only access parent members with family protection if the site object
9407  * is subclass of Subtype. For example:
9408  * class A { protected int x; }
9409  * class B : A {
9410  *      void valid_access () {
9411  *              B b;
9412  *              b.x = 0;
9413  *  }
9414  *  void invalid_access () {
9415  *              A a;
9416  *              a.x = 0;
9417  *  }
9418  * }
9419  * */
9420 static gboolean
9421 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9422 {
9423         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9424                 return FALSE;
9425
9426         if (context_klass == NULL)
9427                 return TRUE;
9428         /*if access_klass is not member_klass context_klass must be type compat*/
9429         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9430                 return FALSE;
9431         return TRUE;
9432 }
9433
9434 static gboolean
9435 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9436 {
9437         GSList *tmp;
9438         if (accessing == accessed)
9439                 return TRUE;
9440         if (!accessed || !accessing)
9441                 return FALSE;
9442
9443         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9444          * anywhere so untrusted friends are not safe to access platform's code internals */
9445         if (mono_security_core_clr_enabled ()) {
9446                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9447                         return FALSE;
9448         }
9449
9450         mono_assembly_load_friends (accessed);
9451         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9452                 MonoAssemblyName *friend = tmp->data;
9453                 /* Be conservative with checks */
9454                 if (!friend->name)
9455                         continue;
9456                 if (strcmp (accessing->aname.name, friend->name))
9457                         continue;
9458                 if (friend->public_key_token [0]) {
9459                         if (!accessing->aname.public_key_token [0])
9460                                 continue;
9461                         if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9462                                 continue;
9463                 }
9464                 return TRUE;
9465         }
9466         return FALSE;
9467 }
9468
9469 /*
9470  * If klass is a generic type or if it is derived from a generic type, return the
9471  * MonoClass of the generic definition
9472  * Returns NULL if not found
9473  */
9474 static MonoClass*
9475 get_generic_definition_class (MonoClass *klass)
9476 {
9477         while (klass) {
9478                 if (klass->generic_class && klass->generic_class->container_class)
9479                         return klass->generic_class->container_class;
9480                 klass = klass->parent;
9481         }
9482         return NULL;
9483 }
9484
9485 static gboolean
9486 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9487 {
9488         int i;
9489         for (i = 0; i < ginst->type_argc; ++i) {
9490                 MonoType *type = ginst->type_argv[i];
9491                 switch (type->type) {
9492                 case MONO_TYPE_SZARRAY:
9493                         if (!can_access_type (access_klass, type->data.klass))
9494                                 return FALSE;
9495                         break;
9496                 case MONO_TYPE_ARRAY:
9497                         if (!can_access_type (access_klass, type->data.array->eklass))
9498                                 return FALSE;
9499                         break;
9500                 case MONO_TYPE_PTR:
9501                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9502                                 return FALSE;
9503                         break;
9504                 case MONO_TYPE_CLASS:
9505                 case MONO_TYPE_VALUETYPE:
9506                 case MONO_TYPE_GENERICINST:
9507                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9508                                 return FALSE;
9509                 }
9510         }
9511         return TRUE;
9512 }
9513
9514 static gboolean
9515 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9516 {
9517         int access_level;
9518
9519         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9520                 return TRUE;
9521
9522         if (access_klass->element_class && !access_klass->enumtype)
9523                 access_klass = access_klass->element_class;
9524
9525         if (member_klass->element_class && !member_klass->enumtype)
9526                 member_klass = member_klass->element_class;
9527
9528         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9529
9530         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9531                 return TRUE;
9532
9533         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9534                 return FALSE;
9535
9536         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9537                 return TRUE;
9538
9539         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9540                 return FALSE;
9541
9542         /*Non nested type with nested visibility. We just fail it.*/
9543         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9544                 return FALSE;
9545
9546         switch (access_level) {
9547         case TYPE_ATTRIBUTE_NOT_PUBLIC:
9548                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9549
9550         case TYPE_ATTRIBUTE_PUBLIC:
9551                 return TRUE;
9552
9553         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9554                 return TRUE;
9555
9556         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9557                 return is_nesting_type (member_klass, access_klass);
9558
9559         case TYPE_ATTRIBUTE_NESTED_FAMILY:
9560                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
9561
9562         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9563                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9564
9565         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9566                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9567                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9568
9569         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9570                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9571                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9572         }
9573         return FALSE;
9574 }
9575
9576 /* FIXME: check visibility of type, too */
9577 static gboolean
9578 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9579 {
9580         MonoClass *member_generic_def;
9581         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9582                 return TRUE;
9583
9584         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9585                                         access_klass->generic_container) && 
9586                         (member_generic_def = get_generic_definition_class (member_klass))) {
9587                 MonoClass *access_container;
9588
9589                 if (access_klass->generic_container)
9590                         access_container = access_klass;
9591                 else
9592                         access_container = access_klass->generic_class->container_class;
9593
9594                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9595                         return TRUE;
9596         }
9597
9598         /* Partition I 8.5.3.2 */
9599         /* the access level values are the same for fields and methods */
9600         switch (access_level) {
9601         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9602                 /* same compilation unit */
9603                 return access_klass->image == member_klass->image;
9604         case FIELD_ATTRIBUTE_PRIVATE:
9605                 return access_klass == member_klass;
9606         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9607                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9608                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9609                         return TRUE;
9610                 return FALSE;
9611         case FIELD_ATTRIBUTE_ASSEMBLY:
9612                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9613         case FIELD_ATTRIBUTE_FAMILY:
9614                 if (is_valid_family_access (access_klass, member_klass, context_klass))
9615                         return TRUE;
9616                 return FALSE;
9617         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9618                 if (is_valid_family_access (access_klass, member_klass, context_klass))
9619                         return TRUE;
9620                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9621         case FIELD_ATTRIBUTE_PUBLIC:
9622                 return TRUE;
9623         }
9624         return FALSE;
9625 }
9626
9627 gboolean
9628 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9629 {
9630         /* FIXME: check all overlapping fields */
9631         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9632         if (!can) {
9633                 MonoClass *nested = method->klass->nested_in;
9634                 while (nested) {
9635                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9636                         if (can)
9637                                 return TRUE;
9638                         nested = nested->nested_in;
9639                 }
9640         }
9641         return can;
9642 }
9643
9644 gboolean
9645 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9646 {
9647         int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9648         if (!can) {
9649                 MonoClass *nested = method->klass->nested_in;
9650                 while (nested) {
9651                         can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9652                         if (can)
9653                                 return TRUE;
9654                         nested = nested->nested_in;
9655                 }
9656         }
9657         /* 
9658          * FIXME:
9659          * with generics calls to explicit interface implementations can be expressed
9660          * directly: the method is private, but we must allow it. This may be opening
9661          * a hole or the generics code should handle this differently.
9662          * Maybe just ensure the interface type is public.
9663          */
9664         if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9665                 return TRUE;
9666         return can;
9667 }
9668
9669 /*
9670  * mono_method_can_access_method_full:
9671  * @method: The caller method 
9672  * @called: The called method 
9673  * @context_klass: The static type on stack of the owner @called object used
9674  * 
9675  * This function must be used with instance calls, as they have more strict family accessibility.
9676  * It can be used with static methods, but context_klass should be NULL.
9677  * 
9678  * Returns: TRUE if caller have proper visibility and acessibility to @called
9679  */
9680 gboolean
9681 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9682 {
9683         MonoClass *access_class = method->klass;
9684         MonoClass *member_class = called->klass;
9685         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9686         if (!can) {
9687                 MonoClass *nested = access_class->nested_in;
9688                 while (nested) {
9689                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9690                         if (can)
9691                                 break;
9692                         nested = nested->nested_in;
9693                 }
9694         }
9695
9696         if (!can)
9697                 return FALSE;
9698
9699         can = can_access_type (access_class, member_class);
9700         if (!can) {
9701                 MonoClass *nested = access_class->nested_in;
9702                 while (nested) {
9703                         can = can_access_type (nested, member_class);
9704                         if (can)
9705                                 break;
9706                         nested = nested->nested_in;
9707                 }
9708         }
9709
9710         if (!can)
9711                 return FALSE;
9712
9713         if (called->is_inflated) {
9714                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9715                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9716                         return FALSE;
9717         }
9718                 
9719         return TRUE;
9720 }
9721
9722
9723 /*
9724  * mono_method_can_access_field_full:
9725  * @method: The caller method 
9726  * @field: The accessed field
9727  * @context_klass: The static type on stack of the owner @field object used
9728  * 
9729  * This function must be used with instance fields, as they have more strict family accessibility.
9730  * It can be used with static fields, but context_klass should be NULL.
9731  * 
9732  * Returns: TRUE if caller have proper visibility and acessibility to @field
9733  */
9734 gboolean
9735 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9736 {
9737         MonoClass *access_class = method->klass;
9738         MonoClass *member_class = field->parent;
9739         /* FIXME: check all overlapping fields */
9740         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9741         if (!can) {
9742                 MonoClass *nested = access_class->nested_in;
9743                 while (nested) {
9744                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9745                         if (can)
9746                                 break;
9747                         nested = nested->nested_in;
9748                 }
9749         }
9750
9751         if (!can)
9752                 return FALSE;
9753
9754         can = can_access_type (access_class, member_class);
9755         if (!can) {
9756                 MonoClass *nested = access_class->nested_in;
9757                 while (nested) {
9758                         can = can_access_type (nested, member_class);
9759                         if (can)
9760                                 break;
9761                         nested = nested->nested_in;
9762                 }
9763         }
9764
9765         if (!can)
9766                 return FALSE;
9767         return TRUE;
9768 }
9769
9770 /*
9771  * mono_class_can_access_class:
9772  * @source_class: The source class 
9773  * @target_class: The accessed class
9774  * 
9775  * This function returns is @target_class is visible to @source_class
9776  * 
9777  * Returns: TRUE if source have proper visibility and acessibility to target
9778  */
9779 gboolean
9780 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9781 {
9782         return can_access_type (source_class, target_class);
9783 }
9784
9785 /**
9786  * mono_type_is_valid_enum_basetype:
9787  * @type: The MonoType to check
9788  *
9789  * Returns: TRUE if the type can be used as the basetype of an enum
9790  */
9791 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9792         switch (type->type) {
9793         case MONO_TYPE_I1:
9794         case MONO_TYPE_U1:
9795         case MONO_TYPE_BOOLEAN:
9796         case MONO_TYPE_I2:
9797         case MONO_TYPE_U2:
9798         case MONO_TYPE_CHAR:
9799         case MONO_TYPE_I4:
9800         case MONO_TYPE_U4:
9801         case MONO_TYPE_I8:
9802         case MONO_TYPE_U8:
9803         case MONO_TYPE_I:
9804         case MONO_TYPE_U:
9805                 return TRUE;
9806         }
9807         return FALSE;
9808 }
9809
9810 /**
9811  * mono_class_is_valid_enum:
9812  * @klass: An enum class to be validated
9813  *
9814  * This method verify the required properties an enum should have.
9815  *  
9816  * Returns: TRUE if the informed enum class is valid 
9817  *
9818  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9819  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9820  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9821  */
9822 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9823         MonoClassField * field;
9824         gpointer iter = NULL;
9825         gboolean found_base_field = FALSE;
9826
9827         g_assert (klass->enumtype);
9828         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9829         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9830                 return FALSE;
9831         }
9832
9833         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9834                 return FALSE;
9835
9836         while ((field = mono_class_get_fields (klass, &iter))) {
9837                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9838                         if (found_base_field)
9839                                 return FALSE;
9840                         found_base_field = TRUE;
9841                         if (!mono_type_is_valid_enum_basetype (field->type))
9842                                 return FALSE;
9843                 }
9844         }
9845
9846         if (!found_base_field)
9847                 return FALSE;
9848
9849         if (klass->method.count > 0) 
9850                 return FALSE;
9851
9852         return TRUE;
9853 }
9854
9855 gboolean
9856 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9857 {
9858         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9859 }
9860
9861 /*
9862  * mono_class_setup_interface_id:
9863  *
9864  * Initializes MonoClass::interface_id if required.
9865  *
9866  * LOCKING: Acquires the loader lock.
9867  */
9868 void
9869 mono_class_setup_interface_id (MonoClass *class)
9870 {
9871         mono_loader_lock ();
9872         if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9873                 class->interface_id = mono_get_unique_iid (class);
9874         mono_loader_unlock ();
9875 }
9876
9877 /*
9878  * mono_class_alloc_ext:
9879  *
9880  *   Allocate klass->ext if not already done.
9881  * LOCKING: Assumes the loader lock is held.
9882  */
9883 void
9884 mono_class_alloc_ext (MonoClass *klass)
9885 {
9886         if (!klass->ext) {
9887                 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9888                 class_ext_size += sizeof (MonoClassExt);
9889         }
9890 }
9891
9892 /*
9893  * mono_class_setup_interfaces:
9894  *
9895  *   Initialize class->interfaces/interfaces_count.
9896  * LOCKING: Acquires the loader lock.
9897  * This function can fail the type.
9898  */
9899 void
9900 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9901 {
9902         int i;
9903
9904         mono_error_init (error);
9905
9906         if (klass->interfaces_inited)
9907                 return;
9908
9909         mono_loader_lock ();
9910
9911         if (klass->interfaces_inited) {
9912                 mono_loader_unlock ();
9913                 return;
9914         }
9915
9916         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
9917                 MonoType *args [1];
9918
9919                 /* generic IList, ICollection, IEnumerable */
9920                 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
9921                 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9922
9923                 args [0] = &klass->element_class->byval_arg;
9924                 klass->interfaces [0] = mono_class_bind_generic_parameters (
9925                         mono_defaults.generic_ilist_class, 1, args, FALSE);
9926                 if (klass->interface_count > 1)
9927                         klass->interfaces [1] = mono_class_bind_generic_parameters (
9928                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
9929         } else if (klass->generic_class) {
9930                 MonoClass *gklass = klass->generic_class->container_class;
9931
9932                 klass->interface_count = gklass->interface_count;
9933                 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
9934                 for (i = 0; i < klass->interface_count; i++) {
9935                         klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
9936                         if (!mono_error_ok (error)) {
9937                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
9938                                 klass->interfaces = NULL;
9939                                 return;
9940                         }
9941                 }
9942         }
9943
9944         mono_memory_barrier ();
9945
9946         klass->interfaces_inited = TRUE;
9947
9948         mono_loader_unlock ();
9949 }
9950
9951 static void
9952 mono_field_resolve_type (MonoClassField *field, MonoError *error)
9953 {
9954         MonoClass *class = field->parent;
9955         MonoImage *image = class->image;
9956         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
9957         int field_idx = field - class->fields;
9958
9959         mono_error_init (error);
9960
9961         if (gtd) {
9962                 MonoClassField *gfield = &gtd->fields [field_idx];
9963                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
9964                 if (!mono_error_ok (error)) {
9965                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9966                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9967                         g_free (err_msg);
9968                 }
9969
9970                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
9971                 if (!mono_error_ok (error)) {
9972                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9973                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9974                         g_free (err_msg);
9975                 }
9976         } else {
9977                 const char *sig;
9978                 guint32 cols [MONO_FIELD_SIZE];
9979                 MonoGenericContainer *container = NULL;
9980                 int idx = class->field.first + field_idx;
9981
9982                 /*FIXME, in theory we do not lazy load SRE fields*/
9983                 g_assert (!image->dynamic);
9984
9985                 if (class->generic_container) {
9986                         container = class->generic_container;
9987                 } else if (gtd) {
9988                         container = gtd->generic_container;
9989                         g_assert (container);
9990                 }
9991
9992                 /* class->field.first and idx points into the fieldptr table */
9993                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
9994
9995                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
9996                         mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
9997                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
9998                         return;
9999                 }
10000
10001                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10002
10003                 mono_metadata_decode_value (sig, &sig);
10004                 /* FIELD signature == 0x06 */
10005                 g_assert (*sig == 0x06);
10006                 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10007                 if (!field->type)
10008                         mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10009         }
10010 }
10011
10012 static guint32
10013 mono_field_resolve_flags (MonoClassField *field)
10014 {
10015         MonoClass *class = field->parent;
10016         MonoImage *image = class->image;
10017         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10018         int field_idx = field - class->fields;
10019
10020
10021         if (gtd) {
10022                 MonoClassField *gfield = &gtd->fields [field_idx];
10023                 return mono_field_get_flags (gfield);
10024         } else {
10025                 int idx = class->field.first + field_idx;
10026
10027                 /*FIXME, in theory we do not lazy load SRE fields*/
10028                 g_assert (!image->dynamic);
10029
10030                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10031         }
10032 }
10033
10034 /**
10035  * mono_class_setup_basic_field_info:
10036  * @class: The class to initialize
10037  *
10038  * Initializes the class->fields array of fields.
10039  * Aquires the loader lock.
10040  */
10041 static void
10042 mono_class_setup_basic_field_info_locking (MonoClass *class)
10043 {
10044         mono_loader_lock ();
10045         mono_class_setup_basic_field_info (class);
10046         mono_loader_unlock ();
10047 }
10048
10049 /**
10050  * mono_class_get_fields_lazy:
10051  * @klass: the MonoClass to act on
10052  *
10053  * This routine is an iterator routine for retrieving the fields in a class.
10054  * Only minimal information about fields are loaded. Accessors must be used
10055  * for all MonoClassField returned.
10056  *
10057  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10058  * iterate over all of the elements.  When no more values are
10059  * available, the return value is NULL.
10060  *
10061  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10062  */
10063 MonoClassField*
10064 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10065 {
10066         MonoClassField* field;
10067         if (!iter)
10068                 return NULL;
10069         if (!*iter) {
10070                 mono_class_setup_basic_field_info_locking (klass);
10071                 if (!klass->fields)
10072                         return NULL;
10073                 /* start from the first */
10074                 if (klass->field.count) {
10075                         return *iter = &klass->fields [0];
10076                 } else {
10077                         /* no fields */
10078                         return NULL;
10079                 }
10080         }
10081         field = *iter;
10082         field++;
10083         if (field < &klass->fields [klass->field.count]) {
10084                 return *iter = field;
10085         }
10086         return NULL;
10087 }
10088
10089 char*
10090 mono_class_full_name (MonoClass *klass)
10091 {
10092         return mono_type_full_name (&klass->byval_arg);
10093 }
10094