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