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