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