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