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