[runtime] Add support for jagged array ctors which create an array of arrays. Fixes...
[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, klass->image->dynamic);
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                 method->klass->image->dynamic && !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 && class->generic_class->container_class->image->dynamic && !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 && class->generic_class->container_class->image->dynamic && !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         MonoClassField *field;
1753
1754         /*
1755          * When we do generic sharing we need to have layout
1756          * information for open generic classes (either with a generic
1757          * context containing type variables or with a generic
1758          * container), so we don't return in that case anymore.
1759          */
1760
1761         /*
1762          * Enable GC aware auto layout: in this mode, reference
1763          * fields are grouped together inside objects, increasing collector 
1764          * performance.
1765          * Requires that all classes whose layout is known to native code be annotated
1766          * with [StructLayout (LayoutKind.Sequential)]
1767          * Value types have gc_aware_layout disabled by default, as per
1768          * what the default is for other runtimes.
1769          */
1770          /* corlib is missing [StructLayout] directives in many places */
1771         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1772                 if (!class->valuetype)
1773                         gc_aware_layout = TRUE;
1774         }
1775
1776         /* Compute klass->has_references */
1777         /* 
1778          * Process non-static fields first, since static fields might recursively
1779          * refer to the class itself.
1780          */
1781         for (i = 0; i < top; i++) {
1782                 MonoType *ftype;
1783
1784                 field = &class->fields [i];
1785
1786                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1787                         ftype = mono_type_get_underlying_type (field->type);
1788                         ftype = mono_type_get_basic_type_from_generic (ftype);
1789                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1790                                 class->has_references = TRUE;
1791                 }
1792         }
1793
1794         for (i = 0; i < top; i++) {
1795                 MonoType *ftype;
1796
1797                 field = &class->fields [i];
1798
1799                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1800                         ftype = mono_type_get_underlying_type (field->type);
1801                         ftype = mono_type_get_basic_type_from_generic (ftype);
1802                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1803                                 class->has_static_refs = TRUE;
1804                 }
1805         }
1806
1807         for (i = 0; i < top; i++) {
1808                 MonoType *ftype;
1809
1810                 field = &class->fields [i];
1811
1812                 ftype = mono_type_get_underlying_type (field->type);
1813                 ftype = mono_type_get_basic_type_from_generic (ftype);
1814                 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1815                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1816                                 class->has_static_refs = TRUE;
1817                         else
1818                                 class->has_references = TRUE;
1819                 }
1820         }
1821
1822         /*
1823          * Compute field layout and total size (not considering static fields)
1824          */
1825
1826         switch (layout) {
1827         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1828         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1829
1830                 if (gc_aware_layout)
1831                         passes = 2;
1832                 else
1833                         passes = 1;
1834
1835                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1836                         passes = 1;
1837
1838                 if (class->parent) {
1839                         mono_class_setup_fields (class->parent);
1840                         if (class->parent->exception_type) {
1841                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1842                                 return;
1843                         }
1844                         real_size = class->parent->instance_size;
1845                 } else {
1846                         real_size = sizeof (MonoObject);
1847                 }
1848
1849                 for (pass = 0; pass < passes; ++pass) {
1850                         for (i = 0; i < top; i++){
1851                                 gint32 align;
1852                                 guint32 size;
1853                                 MonoType *ftype;
1854
1855                                 field = &class->fields [i];
1856
1857                                 if (mono_field_is_deleted (field))
1858                                         continue;
1859                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1860                                         continue;
1861
1862                                 ftype = mono_type_get_underlying_type (field->type);
1863                                 ftype = mono_type_get_basic_type_from_generic (ftype);
1864                                 if (gc_aware_layout) {
1865                                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1866                                                 if (pass == 1)
1867                                                         continue;
1868                                         } else {
1869                                                 if (pass == 0)
1870                                                         continue;
1871                                         }
1872                                 }
1873
1874                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1875                                         (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1876                                         /* This field is a hack inserted by MCS to empty structures */
1877                                         continue;
1878                                 }
1879
1880                                 size = mono_type_size (field->type, &align);
1881                         
1882                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1883                                 align = class->packing_size ? MIN (class->packing_size, align): align;
1884                                 /* if the field has managed references, we need to force-align it
1885                                  * see bug #77788
1886                                  */
1887                                 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1888                                         align = MAX (align, sizeof (gpointer));
1889
1890                                 class->min_align = MAX (align, class->min_align);
1891                                 field->offset = real_size;
1892                                 if (align) {
1893                                         field->offset += align - 1;
1894                                         field->offset &= ~(align - 1);
1895                                 }
1896                                 /*TypeBuilders produce all sort of weird things*/
1897                                 g_assert (class->image->dynamic || field->offset > 0);
1898                                 real_size = field->offset + size;
1899                         }
1900
1901                         class->instance_size = MAX (real_size, class->instance_size);
1902        
1903                         if (class->instance_size & (class->min_align - 1)) {
1904                                 class->instance_size += class->min_align - 1;
1905                                 class->instance_size &= ~(class->min_align - 1);
1906                         }
1907                 }
1908                 break;
1909         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1910                 real_size = 0;
1911                 for (i = 0; i < top; i++) {
1912                         gint32 align;
1913                         guint32 size;
1914                         MonoType *ftype;
1915
1916                         field = &class->fields [i];
1917
1918                         /*
1919                          * There must be info about all the fields in a type if it
1920                          * uses explicit layout.
1921                          */
1922
1923                         if (mono_field_is_deleted (field))
1924                                 continue;
1925                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1926                                 continue;
1927
1928                         size = mono_type_size (field->type, &align);
1929                         align = class->packing_size ? MIN (class->packing_size, align): align;
1930                         class->min_align = MAX (align, class->min_align);
1931
1932                         /*
1933                          * When we get here, field->offset is already set by the
1934                          * loader (for either runtime fields or fields loaded from metadata).
1935                          * The offset is from the start of the object: this works for both
1936                          * classes and valuetypes.
1937                          */
1938                         field->offset += sizeof (MonoObject);
1939                         ftype = mono_type_get_underlying_type (field->type);
1940                         ftype = mono_type_get_basic_type_from_generic (ftype);
1941                         if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1942                                 if (field->offset % sizeof (gpointer)) {
1943                                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1944                                 }
1945                         }
1946
1947                         /*
1948                          * Calc max size.
1949                          */
1950                         real_size = MAX (real_size, size + field->offset);
1951                 }
1952                 class->instance_size = MAX (real_size, class->instance_size);
1953                 if (class->instance_size & (class->min_align - 1)) {
1954                         class->instance_size += class->min_align - 1;
1955                         class->instance_size &= ~(class->min_align - 1);
1956                 }
1957                 break;
1958         }
1959
1960         if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1961                 /*
1962                  * For small structs, set min_align to at least the struct size to improve
1963                  * performance, and since the JIT memset/memcpy code assumes this and generates 
1964                  * unaligned accesses otherwise. See #78990 for a testcase.
1965                  */
1966                 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1967                         class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1968         }
1969
1970         mono_memory_barrier ();
1971         class->size_inited = 1;
1972
1973         /*
1974          * Compute static field layout and size
1975          */
1976         for (i = 0; i < top; i++){
1977                 gint32 align;
1978                 guint32 size;
1979
1980                 field = &class->fields [i];
1981                         
1982                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1983                         continue;
1984                 if (mono_field_is_deleted (field))
1985                         continue;
1986
1987                 if (mono_type_has_exceptions (field->type)) {
1988                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1989                         break;
1990                 }
1991
1992                 size = mono_type_size (field->type, &align);
1993                 field->offset = class->sizes.class_size;
1994                 /*align is always non-zero here*/
1995                 field->offset += align - 1;
1996                 field->offset &= ~(align - 1);
1997                 class->sizes.class_size = field->offset + size;
1998         }
1999 }
2000
2001 static MonoMethod*
2002 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2003 {
2004         MonoMethod *method;
2005
2006         method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2007         method->klass = class;
2008         method->flags = METHOD_ATTRIBUTE_PUBLIC;
2009         method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2010         method->signature = sig;
2011         method->name = name;
2012         method->slot = -1;
2013         /* .ctor */
2014         if (name [0] == '.') {
2015                 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2016         } else {
2017                 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2018         }
2019         return method;
2020 }
2021
2022 /*
2023  * mono_class_setup_methods:
2024  * @class: a class
2025  *
2026  *   Initializes the 'methods' array in the klass.
2027  * Calling this method should be avoided if possible since it allocates a lot 
2028  * of long-living MonoMethod structures.
2029  * Methods belonging to an interface are assigned a sequential slot starting
2030  * from 0.
2031  *
2032  * On failure this function sets class->exception_type
2033  */
2034 void
2035 mono_class_setup_methods (MonoClass *class)
2036 {
2037         int i;
2038         MonoMethod **methods;
2039
2040         if (class->methods)
2041                 return;
2042
2043         mono_loader_lock ();
2044
2045         if (class->methods) {
2046                 mono_loader_unlock ();
2047                 return;
2048         }
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                         mono_loader_unlock ();
2061                         return;
2062                 }
2063
2064                 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2065                 class->method.count = gklass->method.count;
2066                 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2067
2068                 for (i = 0; i < class->method.count; i++) {
2069                         methods [i] = mono_class_inflate_generic_method_full_checked (
2070                                 gklass->methods [i], class, mono_class_get_context (class), &error);
2071                         if (!mono_error_ok (&error)) {
2072                                 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2073                                 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)));
2074
2075                                 g_free (method);
2076                                 mono_error_cleanup (&error);
2077                                 mono_loader_unlock ();
2078                                 return;                         
2079                         }
2080                 }
2081         } else if (class->rank) {
2082                 MonoError error;
2083                 MonoMethod *amethod;
2084                 MonoMethodSignature *sig;
2085                 int count_generic = 0, first_generic = 0;
2086                 int method_num = 0;
2087                 gboolean jagged_ctor = FALSE;
2088
2089                 class->method.count = 3 + (class->rank > 1? 2: 1);
2090
2091                 mono_class_setup_interfaces (class, &error);
2092                 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2093
2094                 if (class->rank == 1 && class->element_class->rank) {
2095                         jagged_ctor = TRUE;
2096                         class->method.count ++;
2097                 }
2098
2099                 if (class->interface_count) {
2100                         count_generic = generic_array_methods (class);
2101                         first_generic = class->method.count;
2102                         class->method.count += class->interface_count * count_generic;
2103                 }
2104
2105                 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2106
2107                 sig = mono_metadata_signature_alloc (class->image, class->rank);
2108                 sig->ret = &mono_defaults.void_class->byval_arg;
2109                 sig->pinvoke = TRUE;
2110                 sig->hasthis = TRUE;
2111                 for (i = 0; i < class->rank; ++i)
2112                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2113
2114                 amethod = create_array_method (class, ".ctor", sig);
2115                 methods [method_num++] = amethod;
2116                 if (class->rank > 1) {
2117                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2118                         sig->ret = &mono_defaults.void_class->byval_arg;
2119                         sig->pinvoke = TRUE;
2120                         sig->hasthis = TRUE;
2121                         for (i = 0; i < class->rank * 2; ++i)
2122                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2123
2124                         amethod = create_array_method (class, ".ctor", sig);
2125                         methods [method_num++] = amethod;
2126                 }
2127
2128                 if (jagged_ctor) {
2129                         /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2130                         sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2131                         sig->ret = &mono_defaults.void_class->byval_arg;
2132                         sig->pinvoke = TRUE;
2133                         sig->hasthis = TRUE;
2134                         for (i = 0; i < class->rank + 1; ++i)
2135                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2136                         amethod = create_array_method (class, ".ctor", sig);
2137                         methods [method_num++] = amethod;
2138                 }
2139
2140                 /* element Get (idx11, [idx2, ...]) */
2141                 sig = mono_metadata_signature_alloc (class->image, class->rank);
2142                 sig->ret = &class->element_class->byval_arg;
2143                 sig->pinvoke = TRUE;
2144                 sig->hasthis = TRUE;
2145                 for (i = 0; i < class->rank; ++i)
2146                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2147                 amethod = create_array_method (class, "Get", sig);
2148                 methods [method_num++] = amethod;
2149                 /* element& Address (idx11, [idx2, ...]) */
2150                 sig = mono_metadata_signature_alloc (class->image, class->rank);
2151                 sig->ret = &class->element_class->this_arg;
2152                 sig->pinvoke = TRUE;
2153                 sig->hasthis = TRUE;
2154                 for (i = 0; i < class->rank; ++i)
2155                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2156                 amethod = create_array_method (class, "Address", sig);
2157                 methods [method_num++] = amethod;
2158                 /* void Set (idx11, [idx2, ...], element) */
2159                 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2160                 sig->ret = &mono_defaults.void_class->byval_arg;
2161                 sig->pinvoke = TRUE;
2162                 sig->hasthis = TRUE;
2163                 for (i = 0; i < class->rank; ++i)
2164                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2165                 sig->params [i] = &class->element_class->byval_arg;
2166                 amethod = create_array_method (class, "Set", sig);
2167                 methods [method_num++] = amethod;
2168
2169                 for (i = 0; i < class->interface_count; i++)
2170                         setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2171         } else {
2172                 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2173                 for (i = 0; i < class->method.count; ++i) {
2174                         int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2175                         methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2176                 }
2177         }
2178
2179         if (MONO_CLASS_IS_INTERFACE (class)) {
2180                 int slot = 0;
2181                 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2182                 for (i = 0; i < class->method.count; ++i) {
2183                         if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2184                                 methods [i]->slot = slot++;
2185                 }
2186         }
2187
2188         /* Needed because of the double-checking locking pattern */
2189         mono_memory_barrier ();
2190
2191         class->methods = methods;
2192
2193         mono_loader_unlock ();
2194 }
2195
2196 /*
2197  * mono_class_get_method_by_index:
2198  *
2199  *   Returns class->methods [index], initializing class->methods if neccesary.
2200  *
2201  * LOCKING: Acquires the loader lock.
2202  */
2203 MonoMethod*
2204 mono_class_get_method_by_index (MonoClass *class, int index)
2205 {
2206         /* Avoid calling setup_methods () if possible */
2207         if (class->generic_class && !class->methods) {
2208                 MonoClass *gklass = class->generic_class->container_class;
2209                 MonoMethod *m;
2210
2211                 m = mono_class_inflate_generic_method_full (
2212                                 gklass->methods [index], class, mono_class_get_context (class));
2213                 /*
2214                  * If setup_methods () is called later for this class, no duplicates are created,
2215                  * since inflate_generic_method guarantees that only one instance of a method
2216                  * is created for each context.
2217                  */
2218                 /*
2219                 mono_class_setup_methods (class);
2220                 g_assert (m == class->methods [index]);
2221                 */
2222                 return m;
2223         } else {
2224                 mono_class_setup_methods (class);
2225                 if (class->exception_type) /*FIXME do proper error handling*/
2226                         return NULL;
2227                 g_assert (index >= 0 && index < class->method.count);
2228                 return class->methods [index];
2229         }
2230 }       
2231
2232 /*
2233  * mono_class_get_inflated_method:
2234  *
2235  *   Given an inflated class CLASS and a method METHOD which should be a method of
2236  * CLASS's generic definition, return the inflated method corresponding to METHOD.
2237  */
2238 MonoMethod*
2239 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2240 {
2241         MonoClass *gklass = class->generic_class->container_class;
2242         int i;
2243
2244         g_assert (method->klass == gklass);
2245
2246         mono_class_setup_methods (gklass);
2247         g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2248
2249         for (i = 0; i < gklass->method.count; ++i) {
2250                 if (gklass->methods [i] == method) {
2251                         if (class->methods)
2252                                 return class->methods [i];
2253                         else
2254                                 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2255                 }
2256         }
2257
2258         return NULL;
2259 }       
2260
2261 /*
2262  * mono_class_get_vtable_entry:
2263  *
2264  *   Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2265  * LOCKING: Acquires the loader lock.
2266  */
2267 MonoMethod*
2268 mono_class_get_vtable_entry (MonoClass *class, int offset)
2269 {
2270         MonoMethod *m;
2271
2272         if (class->rank == 1) {
2273                 /* 
2274                  * szarrays do not overwrite any methods of Array, so we can avoid
2275                  * initializing their vtables in some cases.
2276                  */
2277                 mono_class_setup_vtable (class->parent);
2278                 if (offset < class->parent->vtable_size)
2279                         return class->parent->vtable [offset];
2280         }
2281
2282         if (class->generic_class) {
2283                 MonoClass *gklass = class->generic_class->container_class;
2284                 mono_class_setup_vtable (gklass);
2285                 m = gklass->vtable [offset];
2286
2287                 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2288         } else {
2289                 mono_class_setup_vtable (class);
2290                 if (class->exception_type)
2291                         return NULL;
2292                 m = class->vtable [offset];
2293         }
2294
2295         return m;
2296 }
2297
2298 /*
2299  * mono_class_get_vtable_size:
2300  *
2301  *   Return the vtable size for KLASS.
2302  */
2303 int
2304 mono_class_get_vtable_size (MonoClass *klass)
2305 {
2306         mono_class_setup_vtable (klass);
2307
2308         return klass->vtable_size;
2309 }
2310
2311 /*This method can fail the class.*/
2312 static void
2313 mono_class_setup_properties (MonoClass *class)
2314 {
2315         guint startm, endm, i, j;
2316         guint32 cols [MONO_PROPERTY_SIZE];
2317         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2318         MonoProperty *properties;
2319         guint32 last;
2320
2321         if (class->ext && class->ext->properties)
2322                 return;
2323
2324         mono_loader_lock ();
2325
2326         if (class->ext && class->ext->properties) {
2327                 mono_loader_unlock ();
2328                 return;
2329         }
2330
2331         mono_class_alloc_ext (class);
2332
2333         if (class->generic_class) {
2334                 MonoClass *gklass = class->generic_class->container_class;
2335
2336                 mono_class_init (gklass);
2337                 mono_class_setup_properties (gklass);
2338                 if (gklass->exception_type) {
2339                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2340                         mono_loader_unlock ();                  
2341                         return;
2342                 }
2343
2344                 class->ext->property = gklass->ext->property;
2345
2346                 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2347
2348                 for (i = 0; i < class->ext->property.count; i++) {
2349                         MonoProperty *prop = &properties [i];
2350
2351                         *prop = gklass->ext->properties [i];
2352
2353                         if (prop->get)
2354                                 prop->get = mono_class_inflate_generic_method_full (
2355                                         prop->get, class, mono_class_get_context (class));
2356                         if (prop->set)
2357                                 prop->set = mono_class_inflate_generic_method_full (
2358                                         prop->set, class, mono_class_get_context (class));
2359
2360                         prop->parent = class;
2361                 }
2362         } else {
2363                 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2364                 int count = last - first;
2365
2366                 if (count) {
2367                         mono_class_setup_methods (class);
2368                         if (class->exception_type) {
2369                                 mono_loader_unlock ();
2370                                 return;
2371                         }
2372                 }
2373
2374                 class->ext->property.first = first;
2375                 class->ext->property.count = count;
2376                 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2377                 for (i = first; i < last; ++i) {
2378                         mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2379                         properties [i - first].parent = class;
2380                         properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2381                         properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2382
2383                         startm = mono_metadata_methods_from_property (class->image, i, &endm);
2384                         for (j = startm; j < endm; ++j) {
2385                                 MonoMethod *method;
2386
2387                                 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2388
2389                                 if (class->image->uncompressed_metadata)
2390                                         /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2391                                         method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2392                                 else
2393                                         method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2394
2395                                 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2396                                 case METHOD_SEMANTIC_SETTER:
2397                                         properties [i - first].set = method;
2398                                         break;
2399                                 case METHOD_SEMANTIC_GETTER:
2400                                         properties [i - first].get = method;
2401                                         break;
2402                                 default:
2403                                         break;
2404                                 }
2405                         }
2406                 }
2407         }
2408         /*Flush any pending writes as we do double checked locking on class->properties */
2409         mono_memory_barrier ();
2410
2411         /* Leave this assignment as the last op in the function */
2412         class->ext->properties = properties;
2413
2414         mono_loader_unlock ();
2415 }
2416
2417 static MonoMethod**
2418 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2419 {
2420         MonoMethod **om, **retval;
2421         int count;
2422
2423         for (om = methods, count = 0; *om; ++om, ++count)
2424                 ;
2425
2426         retval = g_new0 (MonoMethod*, count + 1);
2427         count = 0;
2428         for (om = methods, count = 0; *om; ++om, ++count)
2429                 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2430
2431         return retval;
2432 }
2433
2434 /*This method can fail the class.*/
2435 static void
2436 mono_class_setup_events (MonoClass *class)
2437 {
2438         int first, count;
2439         guint startm, endm, i, j;
2440         guint32 cols [MONO_EVENT_SIZE];
2441         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2442         guint32 last;
2443         MonoEvent *events;
2444
2445         if (class->ext && class->ext->events)
2446                 return;
2447
2448         mono_loader_lock ();
2449
2450         if (class->ext && class->ext->events) {
2451                 mono_loader_unlock ();
2452                 return;
2453         }
2454
2455         mono_class_alloc_ext (class);
2456
2457         if (class->generic_class) {
2458                 MonoClass *gklass = class->generic_class->container_class;
2459                 MonoGenericContext *context;
2460
2461                 mono_class_setup_events (gklass);
2462                 if (gklass->exception_type) {
2463                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2464                         mono_loader_unlock ();
2465                         return;
2466                 }
2467
2468                 class->ext->event = gklass->ext->event;
2469                 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2470
2471                 if (class->ext->event.count)
2472                         context = mono_class_get_context (class);
2473
2474                 for (i = 0; i < class->ext->event.count; i++) {
2475                         MonoEvent *event = &class->ext->events [i];
2476                         MonoEvent *gevent = &gklass->ext->events [i];
2477
2478                         event->parent = class;
2479                         event->name = gevent->name;
2480                         event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2481                         event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2482                         event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2483 #ifndef MONO_SMALL_CONFIG
2484                         event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2485 #endif
2486                         event->attrs = gevent->attrs;
2487                 }
2488
2489                 mono_loader_unlock ();
2490                 return;
2491         }
2492
2493         first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2494         count = last - first;
2495
2496         if (count) {
2497                 mono_class_setup_methods (class);
2498                 if (class->exception_type) {
2499                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2500                         mono_loader_unlock ();
2501                         return;
2502                 }
2503         }
2504         class->ext->event.first = first;
2505         class->ext->event.count = count;
2506         events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2507         for (i = first; i < last; ++i) {
2508                 MonoEvent *event = &events [i - first];
2509
2510                 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2511                 event->parent = class;
2512                 event->attrs = cols [MONO_EVENT_FLAGS];
2513                 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2514
2515                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2516                 for (j = startm; j < endm; ++j) {
2517                         MonoMethod *method;
2518
2519                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2520
2521                         if (class->image->uncompressed_metadata)
2522                                 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2523                                 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2524                         else
2525                                 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2526
2527                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2528                         case METHOD_SEMANTIC_ADD_ON:
2529                                 event->add = method;
2530                                 break;
2531                         case METHOD_SEMANTIC_REMOVE_ON:
2532                                 event->remove = method;
2533                                 break;
2534                         case METHOD_SEMANTIC_FIRE:
2535                                 event->raise = method;
2536                                 break;
2537                         case METHOD_SEMANTIC_OTHER: {
2538 #ifndef MONO_SMALL_CONFIG
2539                                 int n = 0;
2540
2541                                 if (event->other == NULL) {
2542                                         event->other = g_new0 (MonoMethod*, 2);
2543                                 } else {
2544                                         while (event->other [n])
2545                                                 n++;
2546                                         event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2547                                 }
2548                                 event->other [n] = method;
2549                                 /* NULL terminated */
2550                                 event->other [n + 1] = NULL;
2551 #endif
2552                                 break;
2553                         }
2554                         default:
2555                                 break;
2556                         }
2557                 }
2558         }
2559         /*Flush any pending writes as we do double checked locking on class->properties */
2560         mono_memory_barrier ();
2561
2562         /* Leave this assignment as the last op in the function */
2563         class->ext->events = events;
2564
2565         mono_loader_unlock ();
2566 }
2567
2568 /*
2569  * Global pool of interface IDs, represented as a bitset.
2570  * LOCKING: this is supposed to be accessed with the loader lock held.
2571  */
2572 static MonoBitSet *global_interface_bitset = NULL;
2573
2574 /*
2575  * mono_unload_interface_ids:
2576  * @bitset: bit set of interface IDs
2577  *
2578  * When an image is unloaded, the interface IDs associated with
2579  * the image are put back in the global pool of IDs so the numbers
2580  * can be reused.
2581  */
2582 void
2583 mono_unload_interface_ids (MonoBitSet *bitset)
2584 {
2585         mono_loader_lock ();
2586         mono_bitset_sub (global_interface_bitset, bitset);
2587         mono_loader_unlock ();
2588 }
2589
2590 void
2591 mono_unload_interface_id (MonoClass *class)
2592 {
2593         if (global_interface_bitset && class->interface_id) {
2594                 mono_loader_lock ();
2595                 mono_bitset_clear (global_interface_bitset, class->interface_id);
2596                 mono_loader_unlock ();
2597         }
2598 }
2599
2600 /*
2601  * mono_get_unique_iid:
2602  * @class: interface
2603  *
2604  * Assign a unique integer ID to the interface represented by @class.
2605  * The ID will positive and as small as possible.
2606  * LOCKING: this is supposed to be called with the loader lock held.
2607  * Returns: the new ID.
2608  */
2609 static guint
2610 mono_get_unique_iid (MonoClass *class)
2611 {
2612         int iid;
2613         
2614         g_assert (MONO_CLASS_IS_INTERFACE (class));
2615
2616         if (!global_interface_bitset) {
2617                 global_interface_bitset = mono_bitset_new (128, 0);
2618         }
2619
2620         iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2621         if (iid < 0) {
2622                 int old_size = mono_bitset_size (global_interface_bitset);
2623                 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2624                 mono_bitset_free (global_interface_bitset);
2625                 global_interface_bitset = new_set;
2626                 iid = old_size;
2627         }
2628         mono_bitset_set (global_interface_bitset, iid);
2629         /* set the bit also in the per-image set */
2630         if (!class->generic_class) {
2631                 if (class->image->interface_bitset) {
2632                         if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2633                                 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2634                                 mono_bitset_free (class->image->interface_bitset);
2635                                 class->image->interface_bitset = new_set;
2636                         }
2637                 } else {
2638                         class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2639                 }
2640                 mono_bitset_set (class->image->interface_bitset, iid);
2641         }
2642
2643 #ifndef MONO_SMALL_CONFIG
2644         if (mono_print_vtable) {
2645                 int generic_id;
2646                 char *type_name = mono_type_full_name (&class->byval_arg);
2647                 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2648                         generic_id = class->generic_class->context.class_inst->id;
2649                         g_assert (generic_id != 0);
2650                 } else {
2651                         generic_id = 0;
2652                 }
2653                 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2654                 g_free (type_name);
2655         }
2656 #endif
2657
2658         g_assert (iid <= 65535);
2659         return iid;
2660 }
2661
2662 static void
2663 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2664 {
2665         int i;
2666         MonoClass *ic;
2667
2668         mono_class_setup_interfaces (klass, error);
2669         if (!mono_error_ok (error))
2670                 return;
2671
2672         for (i = 0; i < klass->interface_count; i++) {
2673                 ic = klass->interfaces [i];
2674
2675                 if (*res == NULL)
2676                         *res = g_ptr_array_new ();
2677                 g_ptr_array_add (*res, ic);
2678                 mono_class_init (ic);
2679                 if (ic->exception_type) {
2680                         mono_error_set_type_load_class (error, ic, "Error Loading class");
2681                         return;
2682                 }
2683
2684                 collect_implemented_interfaces_aux (ic, res, error);
2685                 if (!mono_error_ok (error))
2686                         return;
2687         }
2688 }
2689
2690 GPtrArray*
2691 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2692 {
2693         GPtrArray *res = NULL;
2694
2695         collect_implemented_interfaces_aux (klass, &res, error);
2696         if (!mono_error_ok (error)) {
2697                 if (res)
2698                         g_ptr_array_free (res, TRUE);
2699                 return NULL;
2700         }
2701         return res;
2702 }
2703
2704 static int
2705 compare_interface_ids (const void *p_key, const void *p_element) {
2706         const MonoClass *key = p_key;
2707         const MonoClass *element = *(MonoClass**) p_element;
2708         
2709         return (key->interface_id - element->interface_id);
2710 }
2711
2712 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2713 int
2714 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2715         MonoClass **result = mono_binary_search (
2716                         itf,
2717                         klass->interfaces_packed,
2718                         klass->interface_offsets_count,
2719                         sizeof (MonoClass *),
2720                         compare_interface_ids);
2721         if (result) {
2722                 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2723         } else {
2724                 return -1;
2725         }
2726 }
2727
2728 /*
2729  * mono_class_interface_offset_with_variance:
2730  * 
2731  * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2732  * If @itf is an interface with generic variant arguments, try to find the compatible one.
2733  *
2734  * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2735  *
2736  * FIXME figure out MS disambiguation rules and fix this function.
2737  */
2738 int
2739 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2740         int i = mono_class_interface_offset (klass, itf);
2741         *non_exact_match = FALSE;
2742         if (i >= 0)
2743                 return i;
2744         
2745         if (!mono_class_has_variant_generic_params (itf))
2746                 return -1;
2747
2748         for (i = 0; i < klass->interface_offsets_count; i++) {
2749                 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2750                         *non_exact_match = TRUE;
2751                         return klass->interface_offsets_packed [i];
2752                 }
2753         }
2754
2755         return -1;
2756 }
2757
2758 static void
2759 print_implemented_interfaces (MonoClass *klass) {
2760         char *name;
2761         MonoError error;
2762         GPtrArray *ifaces = NULL;
2763         int i;
2764         int ancestor_level = 0;
2765
2766         name = mono_type_get_full_name (klass);
2767         printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2768         g_free (name);
2769
2770         for (i = 0; i < klass->interface_offsets_count; i++)
2771                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
2772                                 klass->interfaces_packed [i]->interface_id,
2773                                 klass->interface_offsets_packed [i],
2774                                 klass->interfaces_packed [i]->method.count,
2775                                 klass->interfaces_packed [i]->name_space,
2776                                 klass->interfaces_packed [i]->name );
2777         printf ("Interface flags: ");
2778         for (i = 0; i <= klass->max_interface_id; i++)
2779                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2780                         printf ("(%d,T)", i);
2781                 else
2782                         printf ("(%d,F)", i);
2783         printf ("\n");
2784         printf ("Dump interface flags:");
2785 #ifdef COMPRESSED_INTERFACE_BITMAP
2786         {
2787                 const uint8_t* p = klass->interface_bitmap;
2788                 i = klass->max_interface_id;
2789                 while (i > 0) {
2790                         printf (" %d x 00 %02X", p [0], p [1]);
2791                         i -= p [0] * 8;
2792                         i -= 8;
2793                 }
2794         }
2795 #else
2796         for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2797                 printf (" %02X", klass->interface_bitmap [i]);
2798 #endif
2799         printf ("\n");
2800         while (klass != NULL) {
2801                 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2802                 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2803                 if (!mono_error_ok (&error)) {
2804                         printf ("  Type failed due to %s\n", mono_error_get_message (&error));
2805                         mono_error_cleanup (&error);
2806                 } else if (ifaces) {
2807                         for (i = 0; i < ifaces->len; i++) {
2808                                 MonoClass *ic = g_ptr_array_index (ifaces, i);
2809                                 printf ("  [UIID %d] interface %s\n", ic->interface_id, ic->name);
2810                                 printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
2811                                                 ic->interface_id,
2812                                                 mono_class_interface_offset (klass, ic),
2813                                                 ic->method.count,
2814                                                 ic->name_space,
2815                                                 ic->name );
2816                         }
2817                         g_ptr_array_free (ifaces, TRUE);
2818                 }
2819                 ancestor_level ++;
2820                 klass = klass->parent;
2821         }
2822 }
2823
2824 static MonoClass*
2825 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2826 {
2827         MonoType *args [1];
2828         args [0] = &arg0->byval_arg;
2829
2830         return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2831 }
2832
2833 static MonoClass*
2834 array_class_get_if_rank (MonoClass *class, guint rank)
2835 {
2836         return rank ? mono_array_class_get (class, rank) :  class;
2837 }
2838
2839 static void
2840 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2841 {
2842         valuetype_types [0] = eclass;
2843         if (eclass == mono_defaults.int16_class)
2844                 valuetype_types [1] = mono_defaults.uint16_class;
2845         else if (eclass == mono_defaults.uint16_class)
2846                 valuetype_types [1] = mono_defaults.int16_class;
2847         else if (eclass == mono_defaults.int32_class)
2848                 valuetype_types [1] = mono_defaults.uint32_class;
2849         else if (eclass == mono_defaults.uint32_class)
2850                 valuetype_types [1] = mono_defaults.int32_class;
2851         else if (eclass == mono_defaults.int64_class)
2852                 valuetype_types [1] = mono_defaults.uint64_class;
2853         else if (eclass == mono_defaults.uint64_class)
2854                 valuetype_types [1] = mono_defaults.int64_class;
2855         else if (eclass == mono_defaults.byte_class)
2856                 valuetype_types [1] = mono_defaults.sbyte_class;
2857         else if (eclass == mono_defaults.sbyte_class)
2858                 valuetype_types [1] = mono_defaults.byte_class;
2859         else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2860                 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2861 }
2862
2863 /* this won't be needed once bug #325495 is completely fixed
2864  * though we'll need something similar to know which interfaces to allow
2865  * in arrays when they'll be lazyly created
2866  * 
2867  * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2868  * MS returns diferrent types based on which instance is called. For example:
2869  *      object obj = new byte[10][];
2870  *      Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2871  *      Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2872  *      a != b ==> true
2873  * 
2874  * Fixing this should kill quite some code, save some bits and improve compatibility.
2875  */
2876 static MonoClass**
2877 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2878 {
2879         MonoClass *eclass = class->element_class;
2880         static MonoClass* generic_icollection_class = NULL;
2881         static MonoClass* generic_ienumerable_class = NULL;
2882         static MonoClass* generic_ienumerator_class = NULL;
2883         static MonoClass* generic_ireadonlylist_class = NULL;
2884         static MonoClass* generic_ireadonlycollection_class = NULL;
2885         MonoClass *valuetype_types[2] = { NULL, NULL };
2886         MonoClass **interfaces = NULL;
2887         int i, nifaces, interface_count, real_count, original_rank;
2888         int all_interfaces;
2889         gboolean internal_enumerator;
2890         gboolean eclass_is_valuetype;
2891
2892         if (!mono_defaults.generic_ilist_class) {
2893                 *num = 0;
2894                 return NULL;
2895         }
2896         internal_enumerator = FALSE;
2897         eclass_is_valuetype = FALSE;
2898         original_rank = eclass->rank;
2899         if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2900                 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0)  {
2901                         /*
2902                          * For a Enumerator<T[]> we need to get the list of interfaces for T.
2903                          */
2904                         eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2905                         original_rank = eclass->rank;
2906                         if (!eclass->rank)
2907                                 eclass = eclass->element_class;
2908                         internal_enumerator = TRUE;
2909                         *is_enumerator = TRUE;
2910                 } else {
2911                         *num = 0;
2912                         return NULL;
2913                 }
2914         }
2915
2916         /* 
2917          * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2918          * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2919          */
2920         all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2921
2922         if (!generic_icollection_class) {
2923                 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2924                         "System.Collections.Generic", "ICollection`1");
2925                 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2926                         "System.Collections.Generic", "IEnumerable`1");
2927                 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2928                         "System.Collections.Generic", "IEnumerator`1");
2929                 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2930                         "System.Collections.Generic", "IReadOnlyList`1");
2931                 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2932                         "System.Collections.Generic", "IReadOnlyCollection`1");
2933         }
2934
2935         mono_class_init (eclass);
2936
2937         /*
2938          * Arrays in 2.0 need to implement a number of generic interfaces
2939          * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2940          * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2941          * We collect the types needed to build the
2942          * instantiations in interfaces at intervals of 3/5, because 3/5 are
2943          * the generic interfaces needed to implement.
2944          *
2945          * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2946          * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2947          */
2948         if (eclass->valuetype) {
2949                 nifaces = generic_ireadonlylist_class ? 5 : 3;
2950                 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2951
2952                 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2953                 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2954                 if (internal_enumerator) {
2955                         ++real_count;
2956                         if (valuetype_types [1])
2957                                 ++real_count;
2958                 }
2959
2960                 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2961                 interfaces [0] = valuetype_types [0];
2962                 if (valuetype_types [1])
2963                         interfaces [nifaces] = valuetype_types [1];
2964
2965                 eclass_is_valuetype = TRUE;
2966         } else {
2967                 int j;
2968                 int idepth = eclass->idepth;
2969                 if (!internal_enumerator)
2970                         idepth--;
2971                 nifaces = generic_ireadonlylist_class ? 2 : 3;
2972
2973                 // FIXME: This doesn't seem to work/required for generic params
2974                 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2975                         mono_class_setup_interface_offsets (eclass);
2976
2977                 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2978                 /* we add object for interfaces and the supertypes for the other
2979                  * types. The last of the supertypes is the element class itself which we
2980                  * already created the explicit interfaces for (so we include it for IEnumerator
2981                  * and exclude it for arrays).
2982                  */
2983                 if (MONO_CLASS_IS_INTERFACE (eclass))
2984                         interface_count++;
2985                 else
2986                         interface_count += idepth;
2987                 if (eclass->rank && eclass->element_class->valuetype) {
2988                         fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2989                         if (valuetype_types [1])
2990                                 ++interface_count;
2991                 }
2992                 /* IList, ICollection, IEnumerable, IReadOnlyList */
2993                 interface_count *= nifaces;
2994                 real_count = interface_count;
2995                 if (internal_enumerator) {
2996                         real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2997                         if (valuetype_types [1])
2998                                 ++real_count;
2999                 }
3000                 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3001                 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3002                         interfaces [0] = mono_defaults.object_class;
3003                         j = nifaces;
3004                 } else {
3005                         j = 0;
3006                         for (i = 0; i < idepth; i++) {
3007                                 mono_class_init (eclass->supertypes [i]);
3008                                 interfaces [j] = eclass->supertypes [i];
3009                                 j += nifaces;
3010                         }
3011                 }
3012                 if (all_interfaces) {
3013                         for (i = 0; i < eclass->interface_offsets_count; i++) {
3014                                 interfaces [j] = eclass->interfaces_packed [i];
3015                                 j += nifaces;
3016                         }
3017                 } else {
3018                         for (i = 0; i < eclass->interface_count; i++) {
3019                                 interfaces [j] = eclass->interfaces [i];
3020                                 j += nifaces;
3021                         }
3022                 }
3023                 if (valuetype_types [1]) {
3024                         interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3025                         j += nifaces;
3026                 }
3027         }
3028
3029         /* instantiate the generic interfaces */
3030         for (i = 0; i < interface_count; i += nifaces) {
3031                 MonoClass *iface = interfaces [i];
3032
3033                 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3034                 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3035
3036                 if (eclass->valuetype) {
3037                         interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3038                         if (generic_ireadonlylist_class) {
3039                                 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3040                                 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3041                         }
3042                 } else {
3043                         if (!generic_ireadonlylist_class)
3044                                 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3045                 }
3046         }
3047         if (internal_enumerator) {
3048                 int j;
3049                 /* instantiate IEnumerator<iface> */
3050                 for (i = 0; i < interface_count; i++) {
3051                         interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3052                 }
3053                 j = interface_count;
3054                 if (!eclass_is_valuetype) {
3055                         if (MONO_CLASS_IS_INTERFACE (eclass)) {
3056                                 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3057                                 j ++;
3058                         } else {
3059                                 for (i = 0; i < eclass->idepth; i++) {
3060                                         interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3061                                         j ++;
3062                                 }
3063                         }
3064                         for (i = 0; i < eclass->interface_offsets_count; i++) {
3065                                 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3066                                 j ++;
3067                         }
3068                 } else {
3069                         interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3070                 }
3071                 if (valuetype_types [1])
3072                         interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3073         }
3074 #if 0
3075         {
3076         char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3077         for (i = 0; i  < real_count; ++i) {
3078                 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3079                 g_print ("%s implements %s\n", type_name, name);
3080                 g_free (name);
3081         }
3082         g_free (type_name);
3083         }
3084 #endif
3085         *num = real_count;
3086         return interfaces;
3087 }
3088
3089 static int
3090 find_array_interface (MonoClass *klass, const char *name)
3091 {
3092         int i;
3093         for (i = 0; i < klass->interface_count; ++i) {
3094                 if (strcmp (klass->interfaces [i]->name, name) == 0)
3095                         return i;
3096         }
3097         return -1;
3098 }
3099
3100 /*
3101  * Return the number of virtual methods.
3102  * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3103  * Return -1 on failure.
3104  * FIXME It would be nice if this information could be cached somewhere.
3105  */
3106 static int
3107 count_virtual_methods (MonoClass *class)
3108 {
3109         int i, count = 0;
3110         guint32 flags;
3111         class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3112
3113         if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3114                 mono_class_setup_methods (class);
3115                 if (class->exception_type)
3116                         return -1;
3117
3118                 for (i = 0; i < class->method.count; ++i) {
3119                         flags = class->methods [i]->flags;
3120                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3121                                 ++count;
3122                 }
3123         } else {
3124                 for (i = 0; i < class->method.count; ++i) {
3125                         flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3126
3127                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3128                                 ++count;
3129                 }
3130         }
3131         return count;
3132 }
3133
3134 static int
3135 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3136 {
3137         int m, l = 0;
3138         if (!num_ifaces)
3139                 return -1;
3140         while (1) {
3141                 if (l > num_ifaces)
3142                         return -1;
3143                 m = (l + num_ifaces) / 2;
3144                 if (interfaces_full [m] == ic)
3145                         return m;
3146                 if (l == num_ifaces)
3147                         return -1;
3148                 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3149                         num_ifaces = m - 1;
3150                 } else {
3151                         l =  m + 1;
3152                 }
3153         }
3154 }
3155
3156 static int
3157 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3158 {
3159         int i = find_interface (num_ifaces, interfaces_full, ic);
3160         if (ic >= 0)
3161                 return interface_offsets_full [i];
3162         return -1;
3163 }
3164
3165 static mono_bool
3166 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3167 {
3168         int i = find_interface (num_ifaces, interfaces_full, ic);
3169         if (i >= 0) {
3170                 if (!force_set)
3171                         return TRUE;
3172                 interface_offsets_full [i] = offset;
3173                 return FALSE;
3174         }
3175         for (i = 0; i < num_ifaces; ++i) {
3176                 if (interfaces_full [i]) {
3177                         int end;
3178                         if (interfaces_full [i]->interface_id < ic->interface_id)
3179                                 continue;
3180                         end = i + 1;
3181                         while (end < num_ifaces && interfaces_full [end]) end++;
3182                         memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3183                         memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3184                 }
3185                 interfaces_full [i] = ic;
3186                 interface_offsets_full [i] = offset;
3187                 break;
3188         }
3189         return FALSE;
3190 }
3191
3192 #ifdef COMPRESSED_INTERFACE_BITMAP
3193
3194 /*
3195  * Compressed interface bitmap design.
3196  *
3197  * Interface bitmaps take a large amount of memory, because their size is
3198  * linear with the maximum interface id assigned in the process (each interface
3199  * is assigned a unique id as it is loaded). The number of interface classes
3200  * is high because of the many implicit interfaces implemented by arrays (we'll
3201  * need to lazy-load them in the future).
3202  * Most classes implement a very small number of interfaces, so the bitmap is
3203  * sparse. This bitmap needs to be checked by interface casts, so access to the
3204  * needed bit must be fast and doable with few jit instructions.
3205  *
3206  * The current compression format is as follows:
3207  * *) it is a sequence of one or more two-byte elements
3208  * *) the first byte in the element is the count of empty bitmap bytes
3209  * at the current bitmap position
3210  * *) the second byte in the element is an actual bitmap byte at the current
3211  * bitmap position
3212  *
3213  * As an example, the following compressed bitmap bytes:
3214  *      0x07 0x01 0x00 0x7
3215  * correspond to the following bitmap:
3216  *      0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3217  *
3218  * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3219  * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3220  * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3221  */
3222
3223 /**
3224  * mono_compress_bitmap:
3225  * @dest: destination buffer
3226  * @bitmap: bitmap buffer
3227  * @size: size of @bitmap in bytes
3228  *
3229  * This is a mono internal function.
3230  * The @bitmap data is compressed into a format that is small but
3231  * still searchable in few instructions by the JIT and runtime.
3232  * The compressed data is stored in the buffer pointed to by the
3233  * @dest array. Passing a #NULL value for @dest allows to just compute
3234  * the size of the buffer.
3235  * This compression algorithm assumes the bits set in the bitmap are
3236  * few and far between, like in interface bitmaps.
3237  * Returns: the size of the compressed bitmap in bytes.
3238  */
3239 int
3240 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3241 {
3242         int numz = 0;
3243         int res = 0;
3244         const uint8_t *end = bitmap + size;
3245         while (bitmap < end) {
3246                 if (*bitmap || numz == 255) {
3247                         if (dest) {
3248                                 *dest++ = numz;
3249                                 *dest++ = *bitmap;
3250                         }
3251                         res += 2;
3252                         numz = 0;
3253                         bitmap++;
3254                         continue;
3255                 }
3256                 bitmap++;
3257                 numz++;
3258         }
3259         if (numz) {
3260                 res += 2;
3261                 if (dest) {
3262                         *dest++ = numz;
3263                         *dest++ = 0;
3264                 }
3265         }
3266         return res;
3267 }
3268
3269 /**
3270  * mono_class_interface_match:
3271  * @bitmap: a compressed bitmap buffer
3272  * @id: the index to check in the bitmap
3273  *
3274  * This is a mono internal function.
3275  * Checks if a bit is set in a compressed interface bitmap. @id must
3276  * be already checked for being smaller than the maximum id encoded in the
3277  * bitmap.
3278  *
3279  * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3280  * #FALSE otherwise.
3281  */
3282 int
3283 mono_class_interface_match (const uint8_t *bitmap, int id)
3284 {
3285         while (TRUE) {
3286                 id -= bitmap [0] * 8;
3287                 if (id < 8) {
3288                         if (id < 0)
3289                                 return 0;
3290                         return bitmap [1] & (1 << id);
3291                 }
3292                 bitmap += 2;
3293                 id -= 8;
3294         }
3295 }
3296 #endif
3297
3298 /*
3299  * LOCKING: this is supposed to be called with the loader lock held.
3300  * Return -1 on failure and set exception_type
3301  */
3302 static int
3303 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3304 {
3305         MonoError error;
3306         MonoClass *k, *ic;
3307         int i, j, max_iid, num_ifaces;
3308         MonoClass **interfaces_full = NULL;
3309         int *interface_offsets_full = NULL;
3310         GPtrArray *ifaces;
3311         GPtrArray **ifaces_array = NULL;
3312         int interface_offsets_count;
3313         MonoClass **array_interfaces = NULL;
3314         int num_array_interfaces;
3315         int is_enumerator = FALSE;
3316
3317         mono_class_setup_supertypes (class);
3318         /* 
3319          * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3320          * implicit interfaces have the property that they are assigned the same slot in the
3321          * vtables for compatible interfaces
3322          */
3323         array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3324
3325         /* compute maximum number of slots and maximum interface id */
3326         max_iid = 0;
3327         num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3328         ifaces_array = g_new0 (GPtrArray *, class->idepth);
3329         for (j = 0; j < class->idepth; j++) {
3330                 k = class->supertypes [j];
3331                 num_ifaces += k->interface_count;
3332                 for (i = 0; i < k->interface_count; i++) {
3333                         ic = k->interfaces [i];
3334
3335                         if (!ic->inited)
3336                                 mono_class_init (ic);
3337
3338                         if (max_iid < ic->interface_id)
3339                                 max_iid = ic->interface_id;
3340                 }
3341                 ifaces = mono_class_get_implemented_interfaces (k, &error);
3342                 if (!mono_error_ok (&error)) {
3343                         char *name = mono_type_get_full_name (k);
3344                         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)));
3345                         g_free (name);
3346                         mono_error_cleanup (&error);
3347                         cur_slot = -1;
3348                         goto end;
3349                 }
3350                 if (ifaces) {
3351                         num_ifaces += ifaces->len;
3352                         for (i = 0; i < ifaces->len; ++i) {
3353                                 ic = g_ptr_array_index (ifaces, i);
3354                                 if (max_iid < ic->interface_id)
3355                                         max_iid = ic->interface_id;
3356                         }
3357                         ifaces_array [j] = ifaces;
3358                 }
3359         }
3360
3361         for (i = 0; i < num_array_interfaces; ++i) {
3362                 ic = array_interfaces [i];
3363                 mono_class_init (ic);
3364                 if (max_iid < ic->interface_id)
3365                         max_iid = ic->interface_id;
3366         }
3367
3368         if (MONO_CLASS_IS_INTERFACE (class)) {
3369                 num_ifaces++;
3370                 if (max_iid < class->interface_id)
3371                         max_iid = class->interface_id;
3372         }
3373         class->max_interface_id = max_iid;
3374         /* compute vtable offset for interfaces */
3375         interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3376         interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3377
3378         for (i = 0; i < num_ifaces; i++) {
3379                 interface_offsets_full [i] = -1;
3380         }
3381
3382         /* skip the current class */
3383         for (j = 0; j < class->idepth - 1; j++) {
3384                 k = class->supertypes [j];
3385                 ifaces = ifaces_array [j];
3386
3387                 if (ifaces) {
3388                         for (i = 0; i < ifaces->len; ++i) {
3389                                 int io;
3390                                 ic = g_ptr_array_index (ifaces, i);
3391                                 
3392                                 /*Force the sharing of interface offsets between parent and subtypes.*/
3393                                 io = mono_class_interface_offset (k, ic);
3394                                 g_assert (io >= 0);
3395                                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3396                         }
3397                 }
3398         }
3399
3400         g_assert (class == class->supertypes [class->idepth - 1]);
3401         ifaces = ifaces_array [class->idepth - 1];
3402         if (ifaces) {
3403                 for (i = 0; i < ifaces->len; ++i) {
3404                         int count;
3405                         ic = g_ptr_array_index (ifaces, i);
3406                         if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3407                                 continue;
3408                         count = count_virtual_methods (ic);
3409                         if (count == -1) {
3410                                 char *name = mono_type_get_full_name (ic);
3411                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3412                                 g_free (name);
3413                                 cur_slot = -1;
3414                                 goto end;
3415                         }
3416                         cur_slot += count;
3417                 }
3418         }
3419
3420         if (MONO_CLASS_IS_INTERFACE (class))
3421                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3422
3423         if (num_array_interfaces) {
3424                 if (is_enumerator) {
3425                         int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3426                         int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3427                         g_assert (ienumerator_offset >= 0);
3428                         for (i = 0; i < num_array_interfaces; ++i) {
3429                                 ic = array_interfaces [i];
3430                                 if (strcmp (ic->name, "IEnumerator`1") == 0)
3431                                         set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3432                                 else
3433                                         g_assert_not_reached ();
3434                                 /*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);*/
3435                         }
3436                 } else {
3437                         int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3438                         int ilist_iface_idx = find_array_interface (class, "IList`1");
3439                         MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3440                         int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3441                         MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3442                         int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3443                         int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3444                         int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3445                         ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3446                         icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3447                         ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3448                         ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3449                         ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3450                         g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3451                         for (i = 0; i < num_array_interfaces; ++i) {
3452                                 int offset;
3453                                 ic = array_interfaces [i];
3454                                 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3455                                         offset = ilist_offset;
3456                                 else if (strcmp (ic->name, "ICollection`1") == 0)
3457                                         offset = icollection_offset;
3458                                 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3459                                         offset = ienumerable_offset;
3460                                 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3461                                         offset = ireadonlylist_offset;
3462                                 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3463                                         offset = ireadonlycollection_offset;
3464                                 else
3465                                         g_assert_not_reached ();
3466                                 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3467                                 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3468                         }
3469                 }
3470         }
3471
3472         for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3473                 if (interface_offsets_full [i] != -1) {
3474                         interface_offsets_count ++;
3475                 }
3476         }
3477
3478         /*
3479          * We might get called multiple times:
3480          * - mono_class_init ()
3481          * - mono_class_setup_vtable ().
3482          * - mono_class_setup_interface_offsets ().
3483          * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3484          * means we have to overwrite those when called from other places (#4440).
3485          */
3486         if (class->interfaces_packed && !overwrite) {
3487                 g_assert (class->interface_offsets_count == interface_offsets_count);
3488         } else {
3489                 uint8_t *bitmap;
3490                 int bsize;
3491                 class->interface_offsets_count = interface_offsets_count;
3492                 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3493                 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3494                 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3495 #ifdef COMPRESSED_INTERFACE_BITMAP
3496                 bitmap = g_malloc0 (bsize);
3497 #else
3498                 bitmap = mono_class_alloc0 (class, bsize);
3499 #endif
3500                 for (i = 0; i < interface_offsets_count; i++) {
3501                         int id = interfaces_full [i]->interface_id;
3502                         bitmap [id >> 3] |= (1 << (id & 7));
3503                         class->interfaces_packed [i] = interfaces_full [i];
3504                         class->interface_offsets_packed [i] = interface_offsets_full [i];
3505                         /*if (num_array_interfaces)
3506                           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]);*/
3507                 }
3508 #ifdef COMPRESSED_INTERFACE_BITMAP
3509                 i = mono_compress_bitmap (NULL, bitmap, bsize);
3510                 class->interface_bitmap = mono_class_alloc0 (class, i);
3511                 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3512                 g_free (bitmap);
3513 #else
3514                 class->interface_bitmap = bitmap;
3515 #endif
3516         }
3517
3518 end:
3519         g_free (interfaces_full);
3520         g_free (interface_offsets_full);
3521         g_free (array_interfaces);
3522         for (i = 0; i < class->idepth; i++) {
3523                 ifaces = ifaces_array [i];
3524                 if (ifaces)
3525                         g_ptr_array_free (ifaces, TRUE);
3526         }
3527         g_free (ifaces_array);
3528         
3529         //printf ("JUST DONE: ");
3530         //print_implemented_interfaces (class);
3531  
3532         return cur_slot;
3533 }
3534
3535 /*
3536  * Setup interface offsets for interfaces. 
3537  * Initializes:
3538  * - class->max_interface_id
3539  * - class->interface_offsets_count
3540  * - class->interfaces_packed
3541  * - class->interface_offsets_packed
3542  * - class->interface_bitmap
3543  *
3544  * This function can fail @class.
3545  */
3546 void
3547 mono_class_setup_interface_offsets (MonoClass *class)
3548 {
3549         mono_loader_lock ();
3550
3551         setup_interface_offsets (class, 0, FALSE);
3552
3553         mono_loader_unlock ();
3554 }
3555
3556 /*Checks if @klass has @parent as one of it's parents type gtd
3557  *
3558  * For example:
3559  *      Foo<T>
3560  *      Bar<T> : Foo<Bar<Bar<T>>>
3561  *
3562  */
3563 static gboolean
3564 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3565 {
3566         klass = mono_class_get_generic_type_definition (klass);
3567         parent = mono_class_get_generic_type_definition (parent);
3568         mono_class_setup_supertypes (klass);
3569         mono_class_setup_supertypes (parent);
3570
3571         return klass->idepth >= parent->idepth &&
3572                 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3573 }
3574
3575 gboolean
3576 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3577 {
3578         MonoGenericInst *ginst;
3579         int i;
3580         if (!class->generic_class) {
3581                 mono_class_setup_vtable_full (class, in_setup);
3582                 return class->exception_type == 0;
3583         }
3584
3585         mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3586         if (class->generic_class->container_class->exception_type) {
3587                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3588                 return FALSE;
3589         }
3590
3591         ginst = class->generic_class->context.class_inst;
3592         for (i = 0; i < ginst->type_argc; ++i) {
3593                 MonoClass *arg;
3594                 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3595                         continue;
3596                 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3597                 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3598                 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3599                         continue;
3600                 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3601                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3602                         return FALSE;
3603                 }
3604         }
3605         return TRUE;
3606 }
3607  
3608 /*
3609  * mono_class_setup_vtable:
3610  *
3611  *   Creates the generic vtable of CLASS.
3612  * Initializes the following fields in MonoClass:
3613  * - vtable
3614  * - vtable_size
3615  * Plus all the fields initialized by setup_interface_offsets ().
3616  * If there is an error during vtable construction, class->exception_type is set.
3617  *
3618  * LOCKING: Acquires the loader lock.
3619  */
3620 void
3621 mono_class_setup_vtable (MonoClass *class)
3622 {
3623         mono_class_setup_vtable_full (class, NULL);
3624 }
3625
3626 static void
3627 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3628 {
3629         MonoMethod **overrides;
3630         MonoGenericContext *context;
3631         guint32 type_token;
3632         int onum = 0;
3633         gboolean ok = TRUE;
3634
3635         if (class->vtable)
3636                 return;
3637
3638         if (MONO_CLASS_IS_INTERFACE (class)) {
3639                 /* This sets method->slot for all methods if this is an interface */
3640                 mono_class_setup_methods (class);
3641                 return;
3642         }
3643
3644         if (class->exception_type)
3645                 return;
3646
3647         if (g_list_find (in_setup, class))
3648                 return;
3649
3650         mono_loader_lock ();
3651
3652         if (class->vtable) {
3653                 mono_loader_unlock ();
3654                 return;
3655         }
3656
3657         mono_stats.generic_vtable_count ++;
3658         in_setup = g_list_prepend (in_setup, class);
3659
3660         if (class->generic_class) {
3661                 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3662                         mono_loader_unlock ();
3663                         g_list_remove (in_setup, class);
3664                         return;
3665                 }
3666
3667                 context = mono_class_get_context (class);
3668                 type_token = class->generic_class->container_class->type_token;
3669         } else {
3670                 context = (MonoGenericContext *) class->generic_container;              
3671                 type_token = class->type_token;
3672         }
3673
3674         if (class->image->dynamic) {
3675                 /* Generic instances can have zero method overrides without causing any harm.
3676                  * This is true since we don't do layout all over again for them, we simply inflate
3677                  * the layout of the parent.
3678                  */
3679                 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3680         } else {
3681                 /* The following call fails if there are missing methods in the type */
3682                 /* FIXME it's probably a good idea to avoid this for generic instances. */
3683                 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3684         }
3685
3686         if (ok)
3687                 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3688         else
3689                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3690                 
3691         g_free (overrides);
3692
3693         mono_loader_unlock ();
3694         g_list_remove (in_setup, class);
3695
3696         return;
3697 }
3698
3699 #define DEBUG_INTERFACE_VTABLE_CODE 0
3700 #define TRACE_INTERFACE_VTABLE_CODE 0
3701 #define VERIFY_INTERFACE_VTABLE_CODE 0
3702 #define VTABLE_SELECTOR (1)
3703
3704 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3705 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3706         if (!(VTABLE_SELECTOR)) break; \
3707         stmt;\
3708 } while (0)
3709 #else
3710 #define DEBUG_INTERFACE_VTABLE(stmt)
3711 #endif
3712
3713 #if TRACE_INTERFACE_VTABLE_CODE
3714 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3715         if (!(VTABLE_SELECTOR)) break; \
3716         stmt;\
3717 } while (0)
3718 #else
3719 #define TRACE_INTERFACE_VTABLE(stmt)
3720 #endif
3721
3722 #if VERIFY_INTERFACE_VTABLE_CODE
3723 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3724         if (!(VTABLE_SELECTOR)) break; \
3725         stmt;\
3726 } while (0)
3727 #else
3728 #define VERIFY_INTERFACE_VTABLE(stmt)
3729 #endif
3730
3731
3732 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3733 static char*
3734 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3735 {
3736         int i;
3737         char *result;
3738         GString *res = g_string_new ("");
3739         
3740         g_string_append_c (res, '(');
3741         for (i = 0; i < sig->param_count; ++i) {
3742                 if (i > 0)
3743                         g_string_append_c (res, ',');
3744                 mono_type_get_desc (res, sig->params [i], include_namespace);
3745         }
3746         g_string_append (res, ")=>");
3747         if (sig->ret != NULL) {
3748                 mono_type_get_desc (res, sig->ret, include_namespace);
3749         } else {
3750                 g_string_append (res, "NULL");
3751         }
3752         result = res->str;
3753         g_string_free (res, FALSE);
3754         return result;
3755 }
3756 static void
3757 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3758         char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3759         char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3760         printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3761         g_free (im_sig);
3762         g_free (cm_sig);
3763         
3764 }
3765
3766 #endif
3767 static gboolean
3768 is_wcf_hack_disabled (void)
3769 {
3770         static gboolean disabled;
3771         static gboolean inited = FALSE;
3772         if (!inited) {
3773                 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3774                 inited = TRUE;
3775         }
3776         return disabled;
3777 }
3778
3779 static gboolean
3780 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) {
3781         MonoMethodSignature *cmsig, *imsig;
3782         if (strcmp (im->name, cm->name) == 0) {
3783                 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3784                         TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3785                         return FALSE;
3786                 }
3787                 if (! slot_is_empty) {
3788                         if (require_newslot) {
3789                                 if (! interface_is_explicitly_implemented_by_class) {
3790                                         TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3791                                         return FALSE;
3792                                 }
3793                                 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3794                                         TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3795                                         return FALSE;
3796                                 }
3797                         } else {
3798                                 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3799                         }
3800                 }
3801                 cmsig = mono_method_signature (cm);
3802                 imsig = mono_method_signature (im);
3803                 if (!cmsig || !imsig) {
3804                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3805                         return FALSE;
3806                 }
3807
3808                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3809                         TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED  "));
3810                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3811                         TRACE_INTERFACE_VTABLE (printf ("]"));
3812                         return FALSE;
3813                 }
3814                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3815                 /* CAS - SecurityAction.InheritanceDemand on interface */
3816                 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3817                         mono_secman_inheritancedemand_method (cm, im);
3818                 }
3819
3820                 if (mono_security_core_clr_enabled ())
3821                         mono_security_core_clr_check_override (class, cm, im);
3822
3823                 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3824                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3825                         char *body_name = mono_method_full_name (cm, TRUE);
3826                         char *decl_name = mono_method_full_name (im, TRUE);
3827                         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));
3828                         g_free (body_name);
3829                         g_free (decl_name);
3830                         return FALSE;
3831                 }
3832
3833                 return TRUE;
3834         } else {
3835                 MonoClass *ic = im->klass;
3836                 const char *ic_name_space = ic->name_space;
3837                 const char *ic_name = ic->name;
3838                 char *subname;
3839                 
3840                 if (! require_newslot) {
3841                         TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3842                         return FALSE;
3843                 }
3844                 if (cm->klass->rank == 0) {
3845                         TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3846                         return FALSE;
3847                 }
3848                 cmsig = mono_method_signature (cm);
3849                 imsig = mono_method_signature (im);
3850                 if (!cmsig || !imsig) {
3851                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3852                         return FALSE;
3853                 }
3854
3855                 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3856                         TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED  "));
3857                         TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3858                         TRACE_INTERFACE_VTABLE (printf ("]"));
3859                         return FALSE;
3860                 }
3861                 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3862                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3863                         return FALSE;
3864                 }
3865                 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3866                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3867                         return FALSE;
3868                 }
3869                 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))) {
3870                         TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3871                         return FALSE;
3872                 }
3873                 
3874                 subname = strstr (cm->name, ic_name_space);
3875                 if (subname != cm->name) {
3876                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3877                         return FALSE;
3878                 }
3879                 subname += strlen (ic_name_space);
3880                 if (subname [0] != '.') {
3881                         TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3882                         return FALSE;
3883                 }
3884                 subname ++;
3885                 if (strstr (subname, ic_name) != subname) {
3886                         TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3887                         return FALSE;
3888                 }
3889                 subname += strlen (ic_name);
3890                 if (subname [0] != '.') {
3891                         TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3892                         return FALSE;
3893                 }
3894                 subname ++;
3895                 if (strcmp (subname, im->name) != 0) {
3896                         TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3897                         return FALSE;
3898                 }
3899                 
3900                 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3901                 /* CAS - SecurityAction.InheritanceDemand on interface */
3902                 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3903                         mono_secman_inheritancedemand_method (cm, im);
3904                 }
3905
3906                 if (mono_security_core_clr_enabled ())
3907                         mono_security_core_clr_check_override (class, cm, im);
3908
3909                 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3910                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3911                         char *body_name = mono_method_full_name (cm, TRUE);
3912                         char *decl_name = mono_method_full_name (im, TRUE);
3913                         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));
3914                         g_free (body_name);
3915                         g_free (decl_name);
3916                         return FALSE;
3917                 }
3918                 
3919                 return TRUE;
3920         }
3921 }
3922
3923 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3924 static void
3925 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3926         MonoMethod *method = key;
3927         MonoMethod *override = value;
3928         MonoClass *method_class = mono_method_get_class (method);
3929         MonoClass *override_class = mono_method_get_class (override);
3930         
3931         printf ("  Method '%s.%s:%s' has override '%s.%s:%s'\n",
3932                         mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3933                         mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3934 }
3935 static void
3936 print_overrides (GHashTable *override_map, const char *message) {
3937         if (override_map) {
3938                 printf ("Override map \"%s\" START:\n", message);
3939                 g_hash_table_foreach (override_map, foreach_override, NULL);
3940                 printf ("Override map \"%s\" END.\n", message);
3941         } else {
3942                 printf ("Override map \"%s\" EMPTY.\n", message);
3943         }
3944 }
3945 static void
3946 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3947         char *full_name = mono_type_full_name (&class->byval_arg);
3948         int i;
3949         int parent_size;
3950         
3951         printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3952         
3953         if (print_interfaces) {
3954                 print_implemented_interfaces (class);
3955                 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3956         }
3957         
3958         if (class->parent) {
3959                 parent_size = class->parent->vtable_size;
3960         } else {
3961                 parent_size = 0;
3962         }
3963         for (i = 0; i < size; ++i) {
3964                 MonoMethod *cm = vtable [i];
3965                 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3966                 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3967
3968                 printf ("  [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3969                 g_free (cm_name);
3970         }
3971
3972         g_free (full_name);
3973 }
3974 #endif
3975
3976 #if VERIFY_INTERFACE_VTABLE_CODE
3977 static int
3978 mono_method_try_get_vtable_index (MonoMethod *method)
3979 {
3980         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3981                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3982                 if (imethod->declaring->is_generic)
3983                         return imethod->declaring->slot;
3984         }
3985         return method->slot;
3986 }
3987
3988 static void
3989 mono_class_verify_vtable (MonoClass *class)
3990 {
3991         int i;
3992         char *full_name = mono_type_full_name (&class->byval_arg);
3993
3994         printf ("*** Verifying VTable of class '%s' \n", full_name);
3995         g_free (full_name);
3996         full_name = NULL;
3997         
3998         if (!class->methods)
3999                 return;
4000
4001         for (i = 0; i < class->method.count; ++i) {
4002                 MonoMethod *cm = class->methods [i];
4003                 int slot;
4004
4005                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4006                         continue;
4007
4008                 g_free (full_name);
4009                 full_name = mono_method_full_name (cm, TRUE);
4010
4011                 slot = mono_method_try_get_vtable_index (cm);
4012                 if (slot >= 0) {
4013                         if (slot >= class->vtable_size) {
4014                                 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4015                                 continue;
4016                         }
4017
4018                         if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4019                                 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4020                                 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4021                                 g_free (other_name);
4022                         }
4023                 } else
4024                         printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4025         }
4026         g_free (full_name);
4027 }
4028 #endif
4029
4030 static void
4031 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4032         int index;
4033         char *method_signature;
4034         char *type_name;
4035         
4036         for (index = 0; index < onum; ++index) {
4037                 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name, 
4038                          overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4039         }
4040         method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4041         type_name = mono_type_full_name (&class->byval_arg);
4042         mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4043                 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4044         g_free (method_signature);
4045         g_free (type_name);
4046         mono_class_setup_methods (class);
4047         if (class->exception_type) {
4048                 char *name = mono_type_get_full_name (class);
4049                 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4050                 g_free (name);
4051                 return;
4052         }
4053         for (index = 0; index < class->method.count; ++index) {
4054                 MonoMethod *cm = class->methods [index];
4055                 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4056
4057                 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4058                 g_free (method_signature);
4059         }
4060 }
4061
4062 static MonoMethod*
4063 mono_method_get_method_definition (MonoMethod *method)
4064 {
4065         while (method->is_inflated)
4066                 method = ((MonoMethodInflated*)method)->declaring;
4067         return method;
4068 }
4069
4070 static gboolean
4071 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4072 {
4073         int i;
4074
4075         for (i = 0; i < onum; ++i) {
4076                 MonoMethod *decl = overrides [i * 2];
4077                 MonoMethod *body = overrides [i * 2 + 1];
4078
4079                 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4080                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4081                         return FALSE;
4082                 }
4083
4084                 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4085                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
4086                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4087                         else
4088                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4089                         return FALSE;
4090                 }
4091
4092                 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4093                         if (body->flags & METHOD_ATTRIBUTE_STATIC)
4094                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4095                         else
4096                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4097                         return FALSE;
4098                 }
4099
4100                 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4101                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4102                         return FALSE;
4103                 }
4104
4105                 body = mono_method_get_method_definition (body);
4106                 decl = mono_method_get_method_definition (decl);
4107
4108                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4109                         char *body_name = mono_method_full_name (body, TRUE);
4110                         char *decl_name = mono_method_full_name (decl, TRUE);
4111                         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));
4112                         g_free (body_name);
4113                         g_free (decl_name);
4114                         return FALSE;
4115                 }
4116         }
4117         return TRUE;
4118 }
4119
4120 static gboolean
4121 mono_class_need_stelemref_method (MonoClass *class)
4122 {
4123         return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4124 }
4125
4126 /*
4127  * LOCKING: this is supposed to be called with the loader lock held.
4128  */
4129 void
4130 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4131 {
4132         MonoError error;
4133         MonoClass *k, *ic;
4134         MonoMethod **vtable;
4135         int i, max_vtsize = 0, max_iid, cur_slot = 0;
4136         GPtrArray *ifaces = NULL;
4137         GHashTable *override_map = NULL;
4138         gboolean security_enabled = mono_security_enabled ();
4139         MonoMethod *cm;
4140         gpointer class_iter;
4141 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4142         int first_non_interface_slot;
4143 #endif
4144         GSList *virt_methods = NULL, *l;
4145         int stelemref_slot = 0;
4146
4147         if (class->vtable)
4148                 return;
4149
4150         if (overrides && !verify_class_overrides (class, overrides, onum))
4151                 return;
4152
4153         ifaces = mono_class_get_implemented_interfaces (class, &error);
4154         if (!mono_error_ok (&error)) {
4155                 char *name = mono_type_get_full_name (class);
4156                 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)));
4157                 g_free (name);
4158                 mono_error_cleanup (&error);
4159                 return;
4160         } else if (ifaces) {
4161                 for (i = 0; i < ifaces->len; i++) {
4162                         MonoClass *ic = g_ptr_array_index (ifaces, i);
4163                         max_vtsize += ic->method.count;
4164                 }
4165                 g_ptr_array_free (ifaces, TRUE);
4166                 ifaces = NULL;
4167         }
4168         
4169         if (class->parent) {
4170                 mono_class_init (class->parent);
4171                 mono_class_setup_vtable_full (class->parent, in_setup);
4172
4173                 if (class->parent->exception_type) {
4174                         char *name = mono_type_get_full_name (class->parent);
4175                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4176                         g_free (name);
4177                         return;
4178                 }
4179
4180                 max_vtsize += class->parent->vtable_size;
4181                 cur_slot = class->parent->vtable_size;
4182         }
4183
4184         max_vtsize += class->method.count;
4185
4186         /*Array have a slot for stelemref*/
4187         if (mono_class_need_stelemref_method (class)) {
4188                 stelemref_slot = cur_slot;
4189                 ++max_vtsize;
4190                 ++cur_slot;
4191         }
4192
4193         vtable = alloca (sizeof (gpointer) * max_vtsize);
4194         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4195
4196         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4197
4198         cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4199         if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4200                 return;
4201
4202         max_iid = class->max_interface_id;
4203         DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4204
4205         /* Optimized version for generic instances */
4206         if (class->generic_class) {
4207                 MonoError error;
4208                 MonoClass *gklass = class->generic_class->container_class;
4209                 MonoMethod **tmp;
4210
4211                 mono_class_setup_vtable_full (gklass, in_setup);
4212                 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4213                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4214                         return;
4215                 }
4216
4217                 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4218                 class->vtable_size = gklass->vtable_size;
4219                 for (i = 0; i < gklass->vtable_size; ++i)
4220                         if (gklass->vtable [i]) {
4221                                 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4222                                 if (!mono_error_ok (&error)) {
4223                                         char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4224                                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4225                                         g_free (err_msg);
4226                                         mono_error_cleanup (&error);
4227                                         return;
4228                                 }
4229                                 tmp [i] = inflated;
4230                                 tmp [i]->slot = gklass->vtable [i]->slot;
4231                         }
4232                 mono_memory_barrier ();
4233                 class->vtable = tmp;
4234
4235                 /* Have to set method->slot for abstract virtual methods */
4236                 if (class->methods && gklass->methods) {
4237                         for (i = 0; i < class->method.count; ++i)
4238                                 if (class->methods [i]->slot == -1)
4239                                         class->methods [i]->slot = gklass->methods [i]->slot;
4240                 }
4241
4242                 return;
4243         }
4244
4245         if (class->parent && class->parent->vtable_size) {
4246                 MonoClass *parent = class->parent;
4247                 int i;
4248                 
4249                 memcpy (vtable, parent->vtable,  sizeof (gpointer) * parent->vtable_size);
4250                 
4251                 // Also inherit parent interface vtables, just as a starting point.
4252                 // This is needed otherwise bug-77127.exe fails when the property methods
4253                 // have different names in the iterface and the class, because for child
4254                 // classes the ".override" information is not used anymore.
4255                 for (i = 0; i < parent->interface_offsets_count; i++) {
4256                         MonoClass *parent_interface = parent->interfaces_packed [i];
4257                         int interface_offset = mono_class_interface_offset (class, parent_interface);
4258                         /*FIXME this is now dead code as this condition will never hold true.
4259                         Since interface offsets are inherited then the offset of an interface implemented
4260                         by a parent will never be the out of it's vtable boundary.
4261                         */
4262                         if (interface_offset >= parent->vtable_size) {
4263                                 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4264                                 int j;
4265                                 
4266                                 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4267                                 TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4268                                 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4269                                         vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4270                                         TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4271                                                         parent_interface_offset + j, parent_interface_offset, j,
4272                                                         interface_offset + j, interface_offset, j));
4273                                 }
4274                         }
4275                         
4276                 }
4277         }
4278
4279         /*Array have a slot for stelemref*/
4280         if (mono_class_need_stelemref_method (class)) {
4281                 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4282                 if (!method->slot)
4283                         method->slot = stelemref_slot;
4284                 else
4285                         g_assert (method->slot == stelemref_slot);
4286
4287                 vtable [stelemref_slot] = method;
4288         }
4289
4290         TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4291         /* override interface methods */
4292         for (i = 0; i < onum; i++) {
4293                 MonoMethod *decl = overrides [i*2];
4294                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4295                         int dslot;
4296                         dslot = mono_method_get_vtable_slot (decl);
4297                         if (dslot == -1) {
4298                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4299                                 return;
4300                         }
4301
4302                         dslot += mono_class_interface_offset (class, decl->klass);
4303                         vtable [dslot] = overrides [i*2 + 1];
4304                         vtable [dslot]->slot = dslot;
4305                         if (!override_map)
4306                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4307
4308                         g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4309
4310                         if (mono_security_core_clr_enabled ())
4311                                 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4312                 }
4313         }
4314         TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4315         TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4316
4317         /*
4318          * Create a list of virtual methods to avoid calling 
4319          * mono_class_get_virtual_methods () which is slow because of the metadata
4320          * optimization.
4321          */
4322         {
4323                 gpointer iter = NULL;
4324                 MonoMethod *cm;
4325
4326                 virt_methods = NULL;
4327                 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4328                         virt_methods = g_slist_prepend (virt_methods, cm);
4329                 }
4330                 if (class->exception_type)
4331                         goto fail;
4332         }
4333         
4334         // Loop on all implemented interfaces...
4335         for (i = 0; i < class->interface_offsets_count; i++) {
4336                 MonoClass *parent = class->parent;
4337                 int ic_offset;
4338                 gboolean interface_is_explicitly_implemented_by_class;
4339                 int im_index;
4340                 
4341                 ic = class->interfaces_packed [i];
4342                 ic_offset = mono_class_interface_offset (class, ic);
4343
4344                 mono_class_setup_methods (ic);
4345                 if (ic->exception_type)
4346                         goto fail;
4347                 
4348                 // Check if this interface is explicitly implemented (instead of just inherited)
4349                 if (parent != NULL) {
4350                         int implemented_interfaces_index;
4351                         interface_is_explicitly_implemented_by_class = FALSE;
4352                         for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4353                                 if (ic == class->interfaces [implemented_interfaces_index]) {
4354                                         interface_is_explicitly_implemented_by_class = TRUE;
4355                                         break;
4356                                 }
4357                         }
4358                 } else {
4359                         interface_is_explicitly_implemented_by_class = TRUE;
4360                 }
4361                 
4362                 // Loop on all interface methods...
4363                 for (im_index = 0; im_index < ic->method.count; im_index++) {
4364                         MonoMethod *im = ic->methods [im_index];
4365                         int im_slot = ic_offset + im->slot;
4366                         MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4367                         
4368                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
4369                                 continue;
4370
4371                         TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4372
4373                         // If there is an explicit implementation, just use it right away,
4374                         // otherwise look for a matching method
4375                         if (override_im == NULL) {
4376                                 int cm_index;
4377                                 gpointer iter;
4378                                 MonoMethod *cm;
4379
4380                                 // First look for a suitable method among the class methods
4381                                 iter = NULL;
4382                                 for (l = virt_methods; l; l = l->next) {
4383                                         cm = l->data;
4384                                         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)));
4385                                         if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4386                                                 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4387                                                 vtable [im_slot] = cm;
4388                                                 /* Why do we need this? */
4389                                                 if (cm->slot < 0) {
4390                                                         cm->slot = im_slot;
4391                                                 }
4392                                         }
4393                                         TRACE_INTERFACE_VTABLE (printf ("\n"));
4394                                         if (class->exception_type)  /*Might be set by check_interface_method_override*/ 
4395                                                 goto fail;
4396                                 }
4397                                 
4398                                 // If the slot is still empty, look in all the inherited virtual methods...
4399                                 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4400                                         MonoClass *parent = class->parent;
4401                                         // Reverse order, so that last added methods are preferred
4402                                         for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4403                                                 MonoMethod *cm = parent->vtable [cm_index];
4404                                                 
4405                                                 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));
4406                                                 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4407                                                         TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4408                                                         vtable [im_slot] = cm;
4409                                                         /* Why do we need this? */
4410                                                         if (cm->slot < 0) {
4411                                                                 cm->slot = im_slot;
4412                                                         }
4413                                                         break;
4414                                                 }
4415                                                 if (class->exception_type) /*Might be set by check_interface_method_override*/ 
4416                                                         goto fail;
4417                                                 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4418                                         }
4419                                 }
4420                         } else {
4421                                 g_assert (vtable [im_slot] == override_im);
4422                         }
4423                 }
4424         }
4425         
4426         // If the class is not abstract, check that all its interface slots are full.
4427         // The check is done here and not directly at the end of the loop above because
4428         // it can happen (for injected generic array interfaces) that the same slot is
4429         // processed multiple times (those interfaces have overlapping slots), and it
4430         // will not always be the first pass the one that fills the slot.
4431         if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4432                 for (i = 0; i < class->interface_offsets_count; i++) {
4433                         int ic_offset;
4434                         int im_index;
4435                         
4436                         ic = class->interfaces_packed [i];
4437                         ic_offset = mono_class_interface_offset (class, ic);
4438                         
4439                         for (im_index = 0; im_index < ic->method.count; im_index++) {
4440                                 MonoMethod *im = ic->methods [im_index];
4441                                 int im_slot = ic_offset + im->slot;
4442                                 
4443                                 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4444                                         continue;
4445
4446                                 TRACE_INTERFACE_VTABLE (printf ("      [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4447                                                 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4448                                 if (vtable [im_slot] == NULL) {
4449                                         print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4450                                         goto fail;
4451                                 }
4452                         }
4453                 }
4454         }
4455
4456         TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4457         class_iter = NULL;
4458         for (l = virt_methods; l; l = l->next) {
4459                 cm = l->data;
4460                 /*
4461                  * If the method is REUSE_SLOT, we must check in the
4462                  * base class for a method to override.
4463                  */
4464                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4465                         int slot = -1;
4466                         for (k = class->parent; k ; k = k->parent) {
4467                                 gpointer k_iter;
4468                                 MonoMethod *m1;
4469
4470                                 k_iter = NULL;
4471                                 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4472                                         MonoMethodSignature *cmsig, *m1sig;
4473
4474                                         cmsig = mono_method_signature (cm);
4475                                         m1sig = mono_method_signature (m1);
4476
4477                                         if (!cmsig || !m1sig) {
4478                                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4479                                                 return;
4480                                         }
4481
4482                                         if (!strcmp(cm->name, m1->name) && 
4483                                             mono_metadata_signature_equal (cmsig, m1sig)) {
4484
4485                                                 /* CAS - SecurityAction.InheritanceDemand */
4486                                                 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4487                                                         mono_secman_inheritancedemand_method (cm, m1);
4488                                                 }
4489
4490                                                 if (mono_security_core_clr_enabled ())
4491                                                         mono_security_core_clr_check_override (class, cm, m1);
4492
4493                                                 slot = mono_method_get_vtable_slot (m1);
4494                                                 if (slot == -1)
4495                                                         goto fail;
4496
4497                                                 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4498                                                         char *body_name = mono_method_full_name (cm, TRUE);
4499                                                         char *decl_name = mono_method_full_name (m1, TRUE);
4500                                                         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));
4501                                                         g_free (body_name);
4502                                                         g_free (decl_name);
4503                                                         goto fail;
4504                                                 }
4505
4506                                                 g_assert (cm->slot < max_vtsize);
4507                                                 if (!override_map)
4508                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4509                                                 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4510                                                         mono_method_full_name (m1, 1), m1,
4511                                                         mono_method_full_name (cm, 1), cm));
4512                                                 g_hash_table_insert (override_map, m1, cm);
4513                                                 break;
4514                                         }
4515                                 }
4516                                 if (k->exception_type)
4517                                         goto fail;
4518                                 
4519                                 if (slot >= 0) 
4520                                         break;
4521                         }
4522                         if (slot >= 0)
4523                                 cm->slot = slot;
4524                 }
4525
4526                 /*Non final newslot methods must be given a non-interface vtable slot*/
4527                 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4528                         cm->slot = -1;
4529
4530                 if (cm->slot < 0)
4531                         cm->slot = cur_slot++;
4532
4533                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4534                         vtable [cm->slot] = cm;
4535         }
4536
4537         /* override non interface methods */
4538         for (i = 0; i < onum; i++) {
4539                 MonoMethod *decl = overrides [i*2];
4540                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4541                         g_assert (decl->slot != -1);
4542                         vtable [decl->slot] = overrides [i*2 + 1];
4543                         overrides [i * 2 + 1]->slot = decl->slot;
4544                         if (!override_map)
4545                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4546                         TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n", 
4547                                 mono_method_full_name (decl, 1), decl,
4548                                 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4549                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4550
4551                         if (mono_security_core_clr_enabled ())
4552                                 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4553                 }
4554         }
4555
4556         /*
4557          * If a method occupies more than one place in the vtable, and it is
4558          * overriden, then change the other occurances too.
4559          */
4560         if (override_map) {
4561                 MonoMethod *cm;
4562
4563                 for (i = 0; i < max_vtsize; ++i)
4564                         if (vtable [i]) {
4565                                 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4566
4567                                 cm = g_hash_table_lookup (override_map, vtable [i]);
4568                                 if (cm)
4569                                         vtable [i] = cm;
4570                         }
4571
4572                 g_hash_table_destroy (override_map);
4573                 override_map = NULL;
4574         }
4575
4576         g_slist_free (virt_methods);
4577         virt_methods = NULL;
4578
4579         /* Ensure that all vtable slots are filled with concrete instance methods */
4580         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4581                 for (i = 0; i < cur_slot; ++i) {
4582                         if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4583                                 char *type_name = mono_type_get_full_name (class);
4584                                 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4585                                 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));
4586                                 g_free (type_name);
4587                                 g_free (method_name);
4588                                 return;
4589                         }
4590                 }
4591         }
4592
4593         if (class->generic_class) {
4594                 MonoClass *gklass = class->generic_class->container_class;
4595
4596                 mono_class_init (gklass);
4597
4598                 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4599         } else {
4600                 /* Check that the vtable_size value computed in mono_class_init () is correct */
4601                 if (class->vtable_size)
4602                         g_assert (cur_slot == class->vtable_size);
4603                 class->vtable_size = cur_slot;
4604         }
4605
4606         /* Try to share the vtable with our parent. */
4607         if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4608                 mono_memory_barrier ();
4609                 class->vtable = class->parent->vtable;
4610         } else {
4611                 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4612                 memcpy (tmp, vtable,  sizeof (gpointer) * class->vtable_size);
4613                 mono_memory_barrier ();
4614                 class->vtable = tmp;
4615         }
4616
4617         DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4618         if (mono_print_vtable) {
4619                 int icount = 0;
4620
4621                 print_implemented_interfaces (class);
4622                 
4623                 for (i = 0; i <= max_iid; i++)
4624                         if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4625                                 icount++;
4626
4627                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg), 
4628                         class->vtable_size, icount); 
4629
4630                 for (i = 0; i < cur_slot; ++i) {
4631                         MonoMethod *cm;
4632                
4633                         cm = vtable [i];
4634                         if (cm) {
4635                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4636                                         mono_method_full_name (cm, TRUE));
4637                         }
4638                 }
4639
4640
4641                 if (icount) {
4642                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
4643                                 class->name, max_iid);
4644         
4645                         for (i = 0; i < class->interface_count; i++) {
4646                                 ic = class->interfaces [i];
4647                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4648                                         mono_class_interface_offset (class, ic),
4649                                         count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4650                         }
4651
4652                         for (k = class->parent; k ; k = k->parent) {
4653                                 for (i = 0; i < k->interface_count; i++) {
4654                                         ic = k->interfaces [i]; 
4655                                         printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4656                                                 mono_class_interface_offset (class, ic),
4657                                                 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4658                                 }
4659                         }
4660                 }
4661         }
4662
4663         VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4664         return;
4665
4666 fail:
4667         {
4668         char *name = mono_type_get_full_name (class);
4669         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4670         g_free (name);
4671         if (override_map)
4672                 g_hash_table_destroy (override_map);
4673         if (virt_methods)
4674                 g_slist_free (virt_methods);
4675         }
4676 }
4677
4678 /*
4679  * mono_method_get_vtable_slot:
4680  *
4681  *   Returns method->slot, computing it if neccesary. Return -1 on failure.
4682  * LOCKING: Acquires the loader lock.
4683  *
4684  * FIXME Use proper MonoError machinery here.
4685  */
4686 int
4687 mono_method_get_vtable_slot (MonoMethod *method)
4688 {
4689         if (method->slot == -1) {
4690                 mono_class_setup_vtable (method->klass);
4691                 if (method->klass->exception_type)
4692                         return -1;
4693                 if (method->slot == -1) {
4694                         MonoClass *gklass;
4695                         int i;
4696
4697                         /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4698                         g_assert (method->klass->generic_class);
4699                         gklass = method->klass->generic_class->container_class;
4700                         mono_class_setup_methods (method->klass);
4701                         g_assert (method->klass->methods);
4702                         for (i = 0; i < method->klass->method.count; ++i) {
4703                                 if (method->klass->methods [i] == method)
4704                                         break;
4705                         }
4706                         g_assert (i < method->klass->method.count);
4707                         g_assert (gklass->methods);
4708                         method->slot = gklass->methods [i]->slot;
4709                 }
4710                 g_assert (method->slot != -1);
4711         }
4712         return method->slot;
4713 }
4714
4715 /**
4716  * mono_method_get_vtable_index:
4717  * @method: a method
4718  *
4719  * Returns the index into the runtime vtable to access the method or,
4720  * in the case of a virtual generic method, the virtual generic method
4721  * thunk. Returns -1 on failure.
4722  *
4723  * FIXME Use proper MonoError machinery here.
4724  */
4725 int
4726 mono_method_get_vtable_index (MonoMethod *method)
4727 {
4728         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4729                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4730                 if (imethod->declaring->is_generic)
4731                         return mono_method_get_vtable_slot (imethod->declaring);
4732         }
4733         return mono_method_get_vtable_slot (method);
4734 }
4735
4736 static MonoMethod *default_ghc = NULL;
4737 static MonoMethod *default_finalize = NULL;
4738 static int finalize_slot = -1;
4739 static int ghc_slot = -1;
4740
4741 static void
4742 initialize_object_slots (MonoClass *class)
4743 {
4744         int i;
4745         if (default_ghc)
4746                 return;
4747         if (class == mono_defaults.object_class) { 
4748                 mono_class_setup_vtable (class);                       
4749                 for (i = 0; i < class->vtable_size; ++i) {
4750                         MonoMethod *cm = class->vtable [i];
4751        
4752                         if (!strcmp (cm->name, "GetHashCode"))
4753                                 ghc_slot = i;
4754                         else if (!strcmp (cm->name, "Finalize"))
4755                                 finalize_slot = i;
4756                 }
4757
4758                 g_assert (ghc_slot > 0);
4759                 default_ghc = class->vtable [ghc_slot];
4760
4761                 g_assert (finalize_slot > 0);
4762                 default_finalize = class->vtable [finalize_slot];
4763         }
4764 }
4765
4766 typedef struct {
4767         MonoMethod *array_method;
4768         char *name;
4769 } GenericArrayMethodInfo;
4770
4771 static int generic_array_method_num = 0;
4772 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4773
4774 static int
4775 generic_array_methods (MonoClass *class)
4776 {
4777         int i, count_generic = 0;
4778         GList *list = NULL, *tmp;
4779         if (generic_array_method_num)
4780                 return generic_array_method_num;
4781         mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4782         g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4783         for (i = 0; i < class->parent->method.count; i++) {
4784                 MonoMethod *m = class->parent->methods [i];
4785                 if (!strncmp (m->name, "InternalArray__", 15)) {
4786                         count_generic++;
4787                         list = g_list_prepend (list, m);
4788                 }
4789         }
4790         list = g_list_reverse (list);
4791         generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4792         i = 0;
4793         for (tmp = list; tmp; tmp = tmp->next) {
4794                 const char *mname, *iname;
4795                 gchar *name;
4796                 MonoMethod *m = tmp->data;
4797                 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4798                 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4799
4800                 generic_array_method_info [i].array_method = m;
4801                 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4802                         iname = "System.Collections.Generic.ICollection`1.";
4803                         mname = m->name + 27;
4804                 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4805                         iname = "System.Collections.Generic.IEnumerable`1.";
4806                         mname = m->name + 27;
4807                 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4808                         iname = "System.Collections.Generic.IReadOnlyList`1.";
4809                         mname = m->name + strlen (ireadonlylist_prefix);
4810                 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4811                         iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4812                         mname = m->name + strlen (ireadonlycollection_prefix);
4813                 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4814                         iname = "System.Collections.Generic.IList`1.";
4815                         mname = m->name + 15;
4816                 } else {
4817                         g_assert_not_reached ();
4818                 }
4819
4820                 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4821                 strcpy (name, iname);
4822                 strcpy (name + strlen (iname), mname);
4823                 generic_array_method_info [i].name = name;
4824                 i++;
4825         }
4826         /*g_print ("array generic methods: %d\n", count_generic);*/
4827
4828         generic_array_method_num = count_generic;
4829         g_list_free (list);
4830         return generic_array_method_num;
4831 }
4832
4833 static void
4834 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4835 {
4836         MonoGenericContext tmp_context;
4837         int i;
4838
4839         tmp_context.class_inst = NULL;
4840         tmp_context.method_inst = iface->generic_class->context.class_inst;
4841         //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4842
4843         for (i = 0; i < generic_array_method_num; i++) {
4844                 MonoMethod *m = generic_array_method_info [i].array_method;
4845                 MonoMethod *inflated;
4846
4847                 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4848                 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4849         }
4850 }
4851
4852 static char*
4853 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4854 {
4855         int null_length = strlen ("(null)");
4856         int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4857         char *s = mono_image_alloc (image, len);
4858         int result;
4859
4860         result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4861         g_assert (result == len - 1);
4862
4863         return s;
4864 }
4865
4866 static void
4867 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4868 {
4869         gpointer exception_data = NULL;
4870
4871         switch (error->exception_type) {
4872         case MONO_EXCEPTION_TYPE_LOAD:
4873                 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4874                 break;
4875
4876         case MONO_EXCEPTION_MISSING_METHOD:
4877                 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4878                 break;
4879
4880         case MONO_EXCEPTION_MISSING_FIELD: {
4881                 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4882                 const char *class_name;
4883
4884                 if (name_space)
4885                         class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4886                 else
4887                         class_name = error->klass->name;
4888
4889                 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4890                 
4891                 if (name_space)
4892                         g_free ((void*)class_name);
4893                 break;
4894         }
4895
4896         case MONO_EXCEPTION_FILE_NOT_FOUND: {
4897                 const char *msg;
4898
4899                 if (error->ref_only)
4900                         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.";
4901                 else
4902                         msg = "Could not load file or assembly '%s' or one of its dependencies.";
4903
4904                 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4905                 break;
4906         }
4907
4908         case MONO_EXCEPTION_BAD_IMAGE:
4909                 exception_data = error->msg;
4910                 break;
4911
4912         default :
4913                 g_assert_not_reached ();
4914         }
4915
4916         mono_class_set_failure (class, error->exception_type, exception_data);
4917 }
4918
4919 /**
4920  * mono_class_init:
4921  * @class: the class to initialize
4922  *
4923  *   Compute the instance_size, class_size and other infos that cannot be 
4924  * computed at mono_class_get() time. Also compute vtable_size if possible. 
4925  * Returns TRUE on success or FALSE if there was a problem in loading
4926  * the type (incorrect assemblies, missing assemblies, methods, etc). 
4927  *
4928  * LOCKING: Acquires the loader lock.
4929  */
4930 gboolean
4931 mono_class_init (MonoClass *class)
4932 {
4933         int i;
4934         MonoCachedClassInfo cached_info;
4935         gboolean has_cached_info;
4936         
4937         g_assert (class);
4938
4939         /* Double-checking locking pattern */
4940         if (class->inited || class->exception_type)
4941                 return class->exception_type == MONO_EXCEPTION_NONE;
4942
4943         /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4944
4945         /* We do everything inside the lock to prevent races */
4946         mono_loader_lock ();
4947
4948         if (class->inited || class->exception_type) {
4949                 mono_loader_unlock ();
4950                 /* Somebody might have gotten in before us */
4951                 return class->exception_type == MONO_EXCEPTION_NONE;
4952         }
4953
4954         if (class->init_pending) {
4955                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4956                 goto leave;
4957         }
4958
4959         class->init_pending = 1;
4960
4961         if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4962                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4963                 goto leave;
4964         }
4965
4966
4967         if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4968                 MonoClass *element_class = class->element_class;
4969                 if (!element_class->inited) 
4970                         mono_class_init (element_class);
4971                 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4972                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4973                         goto leave;
4974                 }
4975         }
4976
4977         /* CAS - SecurityAction.InheritanceDemand */
4978         if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4979                 mono_secman_inheritancedemand_class (class, class->parent);
4980         }
4981
4982         mono_stats.initialized_class_count++;
4983
4984         if (class->generic_class && !class->generic_class->is_dynamic) {
4985                 MonoClass *gklass = class->generic_class->container_class;
4986
4987                 mono_stats.generic_class_count++;
4988
4989                 class->method = gklass->method;
4990                 class->field = gklass->field;
4991
4992                 mono_class_init (gklass);
4993                 // FIXME: Why is this needed ?
4994                 if (!gklass->exception_type)
4995                         mono_class_setup_methods (gklass);
4996                 if (gklass->exception_type) {
4997                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4998                         goto leave;
4999                 }
5000
5001                 if (MONO_CLASS_IS_INTERFACE (class))
5002                         class->interface_id = mono_get_unique_iid (class);
5003         }
5004
5005         if (class->parent && !class->parent->inited)
5006                 mono_class_init (class->parent);
5007
5008         has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5009
5010         if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5011                 class->nested_classes_inited = TRUE;
5012
5013         /*
5014          * Computes the size used by the fields, and their locations
5015          */
5016         if (has_cached_info) {
5017                 class->instance_size = cached_info.instance_size;
5018                 class->sizes.class_size = cached_info.class_size;
5019                 class->packing_size = cached_info.packing_size;
5020                 class->min_align = cached_info.min_align;
5021                 class->blittable = cached_info.blittable;
5022                 class->has_references = cached_info.has_references;
5023                 class->has_static_refs = cached_info.has_static_refs;
5024                 class->no_special_static_fields = cached_info.no_special_static_fields;
5025         }
5026         else
5027                 if (!class->size_inited){
5028                         mono_class_setup_fields (class);
5029                         if (class->exception_type || mono_loader_get_last_error ())
5030                                 goto leave;
5031                 }
5032                                 
5033         /* Initialize arrays */
5034         if (class->rank) {
5035                 class->method.count = 3 + (class->rank > 1? 2: 1);
5036
5037                 if (class->interface_count) {
5038                         int count_generic = generic_array_methods (class);
5039                         class->method.count += class->interface_count * count_generic;
5040                 }
5041         }
5042
5043         mono_class_setup_supertypes (class);
5044
5045         if (!default_ghc)
5046                 initialize_object_slots (class);
5047
5048         /* 
5049          * Initialize the rest of the data without creating a generic vtable if possible.
5050          * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5051          * also avoid computing a generic vtable.
5052          */
5053         if (has_cached_info) {
5054                 /* AOT case */
5055                 class->vtable_size = cached_info.vtable_size;
5056                 class->has_finalize = cached_info.has_finalize;
5057                 class->has_finalize_inited = TRUE;
5058                 class->ghcimpl = cached_info.ghcimpl;
5059                 class->has_cctor = cached_info.has_cctor;
5060         } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5061                 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5062                  * The first slot if for array with.
5063                  */
5064                 static int szarray_vtable_size[2] = { 0 };
5065
5066                 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5067
5068                 /* SZARRAY case */
5069                 if (!szarray_vtable_size [slot]) {
5070                         mono_class_setup_vtable (class);
5071                         szarray_vtable_size [slot] = class->vtable_size;
5072                 } else {
5073                         class->vtable_size = szarray_vtable_size[slot];
5074                 }
5075                 class->has_finalize_inited = TRUE;
5076         } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5077                 MonoClass *gklass = class->generic_class->container_class;
5078
5079                 /* Generic instance case */
5080                 class->ghcimpl = gklass->ghcimpl;
5081                 class->has_finalize = mono_class_has_finalizer (gklass);
5082                 class->has_finalize_inited = TRUE;
5083                 class->has_cctor = gklass->has_cctor;
5084
5085                 mono_class_setup_vtable (gklass);
5086                 if (gklass->exception_type) {
5087                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5088                         goto leave;
5089                 }
5090
5091                 class->vtable_size = gklass->vtable_size;
5092         } else {
5093                 /* General case */
5094
5095                 /* ghcimpl is not currently used
5096                 class->ghcimpl = 1;
5097                 if (class->parent) { 
5098                         MonoMethod *cmethod = class->vtable [ghc_slot];
5099                         if (cmethod->is_inflated)
5100                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5101                         if (cmethod == default_ghc) {
5102                                 class->ghcimpl = 0;
5103                         }
5104                 }
5105                 */
5106
5107                 /* C# doesn't allow interfaces to have cctors */
5108                 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5109                         MonoMethod *cmethod = NULL;
5110
5111                         if (class->type_token) {
5112                                 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5113                                 /* The find_method function ignores the 'flags' argument */
5114                                 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5115                                         class->has_cctor = 1;
5116                         } else {
5117                                 mono_class_setup_methods (class);
5118                                 if (class->exception_type)
5119                                         goto leave;
5120
5121                                 for (i = 0; i < class->method.count; ++i) {
5122                                         MonoMethod *method = class->methods [i];
5123                                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
5124                                                 (strcmp (".cctor", method->name) == 0)) {
5125                                                 class->has_cctor = 1;
5126                                                 break;
5127                                         }
5128                                 }
5129                         }
5130                 }
5131         }
5132
5133         if (class->parent) {
5134                 int first_iface_slot;
5135                 /* This will compute class->parent->vtable_size for some classes */
5136                 mono_class_init (class->parent);
5137                 if (class->parent->exception_type) {
5138                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5139                         goto leave;
5140                 }
5141                 if (mono_loader_get_last_error ())
5142                         goto leave;
5143                 if (!class->parent->vtable_size) {
5144                         /* FIXME: Get rid of this somehow */
5145                         mono_class_setup_vtable (class->parent);
5146                         if (class->parent->exception_type) {
5147                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5148                                 goto leave;
5149                         }
5150                         if (mono_loader_get_last_error ())
5151                                 goto leave;
5152                 }
5153                 first_iface_slot = class->parent->vtable_size;
5154                 if (mono_class_need_stelemref_method (class))
5155                         ++first_iface_slot;
5156                 setup_interface_offsets (class, first_iface_slot, TRUE);
5157         } else {
5158                 setup_interface_offsets (class, 0, TRUE);
5159         }
5160
5161         if (mono_security_core_clr_enabled ())
5162                 mono_security_core_clr_check_inheritance (class);
5163
5164         if (mono_loader_get_last_error ()) {
5165                 if (class->exception_type == MONO_EXCEPTION_NONE) {
5166                         set_failure_from_loader_error (class, mono_loader_get_last_error ());
5167                 }
5168                 mono_loader_clear_error ();
5169         }
5170
5171         if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5172                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5173
5174         goto leave;
5175
5176  leave:
5177         /* Because of the double-checking locking pattern */
5178         mono_memory_barrier ();
5179         class->inited = 1;
5180         class->init_pending = 0;
5181
5182         mono_loader_unlock ();
5183
5184         if (mono_debugger_class_init_func)
5185                 mono_debugger_class_init_func (class);
5186
5187         return class->exception_type == MONO_EXCEPTION_NONE;
5188 }
5189
5190 /*
5191  * mono_class_has_finalizer:
5192  *
5193  *   Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5194  * process.
5195  */
5196 gboolean
5197 mono_class_has_finalizer (MonoClass *klass)
5198 {
5199         if (!klass->has_finalize_inited) {
5200                 MonoClass *class = klass;
5201
5202                 mono_loader_lock ();
5203
5204                 /* Interfaces and valuetypes are not supposed to have finalizers */
5205                 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5206                         MonoMethod *cmethod = NULL;
5207
5208                         if (class->parent && class->parent->has_finalize) {
5209                                 class->has_finalize = 1;
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                                                 goto leave;
5219                                         cmethod = class->vtable [finalize_slot];
5220                                 }
5221
5222                                 if (cmethod) {
5223                                         g_assert (class->vtable_size > finalize_slot);
5224
5225                                         class->has_finalize = 0;
5226                                         if (class->parent) { 
5227                                                 if (cmethod->is_inflated)
5228                                                         cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5229                                                 if (cmethod != default_finalize) {
5230                                                         class->has_finalize = 1;
5231                                                 }
5232                                         }
5233                                 }
5234                         }
5235                 }
5236
5237                 mono_memory_barrier ();
5238                 klass->has_finalize_inited = TRUE;
5239
5240                 mono_loader_unlock ();
5241         }
5242
5243         return klass->has_finalize;
5244
5245  leave:
5246         mono_loader_unlock ();
5247         return FALSE;
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->dynamic)
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                 EnterCriticalSection (&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                 LeaveCriticalSection (&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 && image->assembly->dynamic && 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                 EnterCriticalSection (&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                 LeaveCriticalSection (&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 (klass->image->dynamic) {
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->dynamic)
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->dynamic)
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->dynamic) {
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->dynamic)
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->dynamic) {
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->dynamic) {
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->dynamic && 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 (candidate->image->dynamic && !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 (klass->image->dynamic) {
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->dynamic) {
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 && !klass->image->dynamic) {
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_space: 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;
10061
10062         mono_error_init (error);
10063
10064         if (klass->interfaces_inited)
10065                 return;
10066
10067         mono_loader_lock ();
10068
10069         if (klass->interfaces_inited) {
10070                 mono_loader_unlock ();
10071                 return;
10072         }
10073
10074         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10075                 MonoType *args [1];
10076
10077                 /* generic IList, ICollection, IEnumerable */
10078                 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10079                 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
10080
10081                 args [0] = &klass->element_class->byval_arg;
10082                 klass->interfaces [0] = mono_class_bind_generic_parameters (
10083                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10084                 if (klass->interface_count > 1)
10085                         klass->interfaces [1] = mono_class_bind_generic_parameters (
10086                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10087         } else if (klass->generic_class) {
10088                 MonoClass *gklass = klass->generic_class->container_class;
10089
10090                 klass->interface_count = gklass->interface_count;
10091                 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10092                 for (i = 0; i < klass->interface_count; i++) {
10093                         klass->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                                 klass->interfaces = NULL;
10097                                 return;
10098                         }
10099                 }
10100         }
10101
10102         mono_memory_barrier ();
10103
10104         klass->interfaces_inited = TRUE;
10105
10106         mono_loader_unlock ();
10107 }
10108
10109 static void
10110 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10111 {
10112         MonoClass *class = field->parent;
10113         MonoImage *image = class->image;
10114         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10115         int field_idx = field - class->fields;
10116
10117         mono_error_init (error);
10118
10119         if (gtd) {
10120                 MonoClassField *gfield = &gtd->fields [field_idx];
10121                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10122                 if (!mono_error_ok (error)) {
10123                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10124                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10125                         g_free (err_msg);
10126                 }
10127
10128                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10129                 if (!mono_error_ok (error)) {
10130                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10131                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10132                         g_free (err_msg);
10133                 }
10134         } else {
10135                 const char *sig;
10136                 guint32 cols [MONO_FIELD_SIZE];
10137                 MonoGenericContainer *container = NULL;
10138                 int idx = class->field.first + field_idx;
10139
10140                 /*FIXME, in theory we do not lazy load SRE fields*/
10141                 g_assert (!image->dynamic);
10142
10143                 if (class->generic_container) {
10144                         container = class->generic_container;
10145                 } else if (gtd) {
10146                         container = gtd->generic_container;
10147                         g_assert (container);
10148                 }
10149
10150                 /* class->field.first and idx points into the fieldptr table */
10151                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10152
10153                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10154                         mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10155                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10156                         return;
10157                 }
10158
10159                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10160
10161                 mono_metadata_decode_value (sig, &sig);
10162                 /* FIELD signature == 0x06 */
10163                 g_assert (*sig == 0x06);
10164                 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10165                 if (!field->type)
10166                         mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10167         }
10168 }
10169
10170 static guint32
10171 mono_field_resolve_flags (MonoClassField *field)
10172 {
10173         MonoClass *class = field->parent;
10174         MonoImage *image = class->image;
10175         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10176         int field_idx = field - class->fields;
10177
10178
10179         if (gtd) {
10180                 MonoClassField *gfield = &gtd->fields [field_idx];
10181                 return mono_field_get_flags (gfield);
10182         } else {
10183                 int idx = class->field.first + field_idx;
10184
10185                 /*FIXME, in theory we do not lazy load SRE fields*/
10186                 g_assert (!image->dynamic);
10187
10188                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10189         }
10190 }
10191
10192 /**
10193  * mono_class_setup_basic_field_info:
10194  * @class: The class to initialize
10195  *
10196  * Initializes the class->fields array of fields.
10197  * Aquires the loader lock.
10198  */
10199 static void
10200 mono_class_setup_basic_field_info_locking (MonoClass *class)
10201 {
10202         mono_loader_lock ();
10203         mono_class_setup_basic_field_info (class);
10204         mono_loader_unlock ();
10205 }
10206
10207 /**
10208  * mono_class_get_fields_lazy:
10209  * @klass: the MonoClass to act on
10210  *
10211  * This routine is an iterator routine for retrieving the fields in a class.
10212  * Only minimal information about fields are loaded. Accessors must be used
10213  * for all MonoClassField returned.
10214  *
10215  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10216  * iterate over all of the elements.  When no more values are
10217  * available, the return value is NULL.
10218  *
10219  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10220  */
10221 MonoClassField*
10222 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10223 {
10224         MonoClassField* field;
10225         if (!iter)
10226                 return NULL;
10227         if (!*iter) {
10228                 mono_class_setup_basic_field_info_locking (klass);
10229                 if (!klass->fields)
10230                         return NULL;
10231                 /* start from the first */
10232                 if (klass->field.count) {
10233                         return *iter = &klass->fields [0];
10234                 } else {
10235                         /* no fields */
10236                         return NULL;
10237                 }
10238         }
10239         field = *iter;
10240         field++;
10241         if (field < &klass->fields [klass->field.count]) {
10242                 return *iter = field;
10243         }
10244         return NULL;
10245 }
10246
10247 char*
10248 mono_class_full_name (MonoClass *klass)
10249 {
10250         return mono_type_full_name (&klass->byval_arg);
10251 }
10252