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