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