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