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