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