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