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