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