Merge pull request #1659 from alexanderkyte/stringbuilder-referencesource
[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 (ic >= 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                 klass->inited = 1;
6055
6056                 mono_class_setup_supertypes (klass);
6057
6058                 if (klass->enumtype) {
6059                         /*
6060                          * For enums, gklass->fields might not been set, but instance_size etc. is 
6061                          * already set in mono_reflection_create_internal_class (). For non-enums,
6062                          * these will be computed normally in mono_class_layout_fields ().
6063                          */
6064                         klass->instance_size = gklass->instance_size;
6065                         klass->sizes.class_size = gklass->sizes.class_size;
6066                         mono_memory_barrier ();
6067                         klass->size_inited = 1;
6068                 }
6069         }
6070
6071         mono_memory_barrier ();
6072         gclass->cached_class = klass;
6073
6074         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6075
6076         inflated_classes ++;
6077         inflated_classes_size += sizeof (MonoClass);
6078         
6079         mono_loader_unlock ();
6080
6081         return klass;
6082 }
6083
6084 static MonoClass*
6085 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6086 {
6087         MonoClass *klass, **ptr;
6088         int count, pos, i;
6089         MonoGenericContainer *container = mono_generic_param_owner (param);
6090
6091         if (!image)
6092                 /* FIXME: */
6093                 image = mono_defaults.corlib;
6094
6095         klass = mono_image_alloc0 (image, sizeof (MonoClass));
6096         classes_size += sizeof (MonoClass);
6097
6098         if (pinfo) {
6099                 klass->name = pinfo->name;
6100         } else {
6101                 int n = mono_generic_param_num (param);
6102                 klass->name = mono_image_alloc0 (image, 16);
6103                 sprintf ((char*)klass->name, "%d", n);
6104         }
6105
6106         if (container) {
6107                 if (is_mvar) {
6108                         MonoMethod *omethod = container->owner.method;
6109                         klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6110                 } else {
6111                         MonoClass *oklass = container->owner.klass;
6112                         klass->name_space = oklass ? oklass->name_space : "";
6113                 }
6114         } else {
6115                 klass->name_space = "";
6116         }
6117
6118         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6119
6120         count = 0;
6121         if (pinfo)
6122                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6123                         ;
6124
6125         pos = 0;
6126         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6127                 klass->parent = pinfo->constraints [0];
6128                 pos++;
6129         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6130                 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6131         else
6132                 klass->parent = mono_defaults.object_class;
6133
6134
6135         if (count - pos > 0) {
6136                 klass->interface_count = count - pos;
6137                 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6138                 klass->interfaces_inited = TRUE;
6139                 for (i = pos; i < count; i++)
6140                         klass->interfaces [i - pos] = pinfo->constraints [i];
6141         }
6142
6143         klass->image = image;
6144
6145         klass->inited = TRUE;
6146         klass->cast_class = klass->element_class = klass;
6147         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6148
6149         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6150         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6151         klass->this_arg.byref = TRUE;
6152
6153         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6154         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6155
6156         /*Init these fields to sane values*/
6157         klass->min_align = 1;
6158         /*
6159          * This makes sure the the value size of this class is equal to the size of the types the gparam is
6160          * constrained to, the JIT depends on this.
6161          */
6162         klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6163         mono_memory_barrier ();
6164         klass->size_inited = 1;
6165         klass->setup_fields_called = 1;
6166
6167         mono_class_setup_supertypes (klass);
6168
6169         if (count - pos > 0) {
6170                 mono_class_setup_vtable (klass->parent);
6171                 if (klass->parent->exception_type)
6172                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6173                 else
6174                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6175         }
6176
6177         return klass;
6178 }
6179
6180 #define FAST_CACHE_SIZE 16
6181
6182 /*
6183  * LOCKING: Takes the image lock depending on @take_lock.
6184  */
6185 static MonoClass *
6186 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6187 {
6188         int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6189         MonoImage *image = param->image;
6190         GHashTable *ht;
6191
6192         g_assert (image);
6193
6194         if (n < FAST_CACHE_SIZE) {
6195                 if (is_mvar)
6196                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6197                 else
6198                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6199         } else {
6200                 MonoClass *klass = NULL;
6201                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6202                 if (ht) {
6203                         if (take_lock)
6204                                 mono_image_lock (image);
6205                         klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6206                         if (take_lock)
6207                                 mono_image_unlock (image);
6208                 }
6209                 return klass;
6210         }
6211 }
6212
6213 /*
6214  * LOCKING: Image lock (param->image) must be held
6215  */
6216 static void
6217 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6218 {
6219         int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6220         MonoImage *image = param->image;
6221
6222         g_assert (image);
6223
6224         if (n < FAST_CACHE_SIZE) {
6225                 if (is_mvar) {
6226                         /* Requires locking to avoid droping an already published class */
6227                         if (!image->mvar_cache_fast)
6228                                 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6229                         image->mvar_cache_fast [n] = klass;
6230                 } else {
6231                         if (!image->var_cache_fast)
6232                                 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6233                         image->var_cache_fast [n] = klass;
6234                 }
6235         } else {
6236                 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6237                 if (!ht) {
6238                         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6239                         if (!ht) {
6240                                 ht = g_hash_table_new (NULL, NULL);
6241                                 mono_memory_barrier ();
6242                                 if (is_mvar)
6243                                         image->mvar_cache_slow = ht;
6244                                 else
6245                                         image->var_cache_slow = ht;
6246                         }
6247                 }
6248                 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6249         }
6250 }
6251
6252 /*
6253  * LOCKING: Acquires the image lock (@image).
6254  */
6255 MonoClass *
6256 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6257 {
6258         MonoGenericContainer *container = mono_generic_param_owner (param);
6259         MonoGenericParamInfo *pinfo = NULL;
6260         MonoClass *klass, *klass2;
6261
6262         if (container) {
6263                 pinfo = mono_generic_param_info (param);
6264                 klass = pinfo->pklass;
6265         } else {
6266                 image = NULL;
6267                 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6268         }
6269         if (klass)
6270                 return klass;
6271
6272         if (!image && container) {
6273                 if (is_mvar) {
6274                         MonoMethod *method = container->owner.method;
6275                         image = (method && method->klass) ? method->klass->image : NULL;
6276                 } else {
6277                         MonoClass *klass = container->owner.klass;
6278                         // FIXME: 'klass' should not be null
6279                         //        But, monodis creates GenericContainers without associating a owner to it
6280                         image = klass ? klass->image : NULL;
6281                 }
6282         }
6283
6284         klass = make_generic_param_class (param, image, is_mvar, pinfo);
6285
6286         mono_memory_barrier ();
6287
6288         if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6289                 image = mono_defaults.corlib;
6290
6291         mono_image_lock (image);
6292         if (container)
6293                 klass2 = pinfo->pklass;
6294         else
6295                 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6296
6297         if (klass2) {
6298                 klass = klass2;
6299         } else {
6300                 if (container)
6301                         pinfo->pklass = klass;
6302                 else
6303                         set_anon_gparam_class (param, is_mvar, klass);
6304         }
6305         mono_image_unlock (image);
6306
6307         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6308         if (klass2)
6309                 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6310         else
6311                 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6312
6313         return klass;
6314 }
6315
6316 MonoClass *
6317 mono_ptr_class_get (MonoType *type)
6318 {
6319         MonoClass *result;
6320         MonoClass *el_class;
6321         MonoImage *image;
6322         char *name;
6323
6324         el_class = mono_class_from_mono_type (type);
6325         image = el_class->image;
6326
6327         mono_image_lock (image);
6328         if (image->ptr_cache) {
6329                 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6330                         mono_image_unlock (image);
6331                         return result;
6332                 }
6333         }
6334         mono_image_unlock (image);
6335         
6336         result = mono_image_alloc0 (image, sizeof (MonoClass));
6337
6338         classes_size += sizeof (MonoClass);
6339
6340         result->parent = NULL; /* no parent for PTR types */
6341         result->name_space = el_class->name_space;
6342         name = g_strdup_printf ("%s*", el_class->name);
6343         result->name = mono_image_strdup (image, name);
6344         g_free (name);
6345
6346         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6347
6348         result->image = el_class->image;
6349         result->inited = TRUE;
6350         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6351         /* Can pointers get boxed? */
6352         result->instance_size = sizeof (gpointer);
6353         result->cast_class = result->element_class = el_class;
6354         result->blittable = TRUE;
6355
6356         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6357         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6358         result->this_arg.byref = TRUE;
6359
6360         mono_class_setup_supertypes (result);
6361
6362         mono_image_lock (image);
6363         if (image->ptr_cache) {
6364                 MonoClass *result2;
6365                 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6366                         mono_image_unlock (image);
6367                         mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6368                         return result2;
6369                 }
6370         } else {
6371                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6372         }
6373         g_hash_table_insert (image->ptr_cache, el_class, result);
6374         mono_image_unlock (image);
6375
6376         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6377
6378         return result;
6379 }
6380
6381 static MonoClass *
6382 mono_fnptr_class_get (MonoMethodSignature *sig)
6383 {
6384         MonoClass *result;
6385         static GHashTable *ptr_hash = NULL;
6386
6387         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6388
6389         mono_loader_lock ();
6390
6391         if (!ptr_hash)
6392                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6393         
6394         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6395                 mono_loader_unlock ();
6396                 return result;
6397         }
6398         result = g_new0 (MonoClass, 1);
6399
6400         result->parent = NULL; /* no parent for PTR types */
6401         result->name_space = "System";
6402         result->name = "MonoFNPtrFakeClass";
6403
6404         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6405
6406         result->image = mono_defaults.corlib; /* need to fix... */
6407         result->inited = TRUE;
6408         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6409         /* Can pointers get boxed? */
6410         result->instance_size = sizeof (gpointer);
6411         result->cast_class = result->element_class = result;
6412         result->blittable = TRUE;
6413
6414         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6415         result->this_arg.data.method = result->byval_arg.data.method = sig;
6416         result->this_arg.byref = TRUE;
6417         result->blittable = TRUE;
6418
6419         mono_class_setup_supertypes (result);
6420
6421         g_hash_table_insert (ptr_hash, sig, result);
6422
6423         mono_loader_unlock ();
6424
6425         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6426
6427         return result;
6428 }
6429
6430 MonoClass *
6431 mono_class_from_mono_type (MonoType *type)
6432 {
6433         switch (type->type) {
6434         case MONO_TYPE_OBJECT:
6435                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6436         case MONO_TYPE_VOID:
6437                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6438         case MONO_TYPE_BOOLEAN:
6439                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6440         case MONO_TYPE_CHAR:
6441                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6442         case MONO_TYPE_I1:
6443                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6444         case MONO_TYPE_U1:
6445                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6446         case MONO_TYPE_I2:
6447                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6448         case MONO_TYPE_U2:
6449                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6450         case MONO_TYPE_I4:
6451                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6452         case MONO_TYPE_U4:
6453                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6454         case MONO_TYPE_I:
6455                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6456         case MONO_TYPE_U:
6457                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6458         case MONO_TYPE_I8:
6459                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6460         case MONO_TYPE_U8:
6461                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6462         case MONO_TYPE_R4:
6463                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6464         case MONO_TYPE_R8:
6465                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6466         case MONO_TYPE_STRING:
6467                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6468         case MONO_TYPE_TYPEDBYREF:
6469                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6470         case MONO_TYPE_ARRAY:
6471                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6472         case MONO_TYPE_PTR:
6473                 return mono_ptr_class_get (type->data.type);
6474         case MONO_TYPE_FNPTR:
6475                 return mono_fnptr_class_get (type->data.method);
6476         case MONO_TYPE_SZARRAY:
6477                 return mono_array_class_get (type->data.klass, 1);
6478         case MONO_TYPE_CLASS:
6479         case MONO_TYPE_VALUETYPE:
6480                 return type->data.klass;
6481         case MONO_TYPE_GENERICINST:
6482                 return mono_generic_class_get_class (type->data.generic_class);
6483         case MONO_TYPE_VAR:
6484                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6485         case MONO_TYPE_MVAR:
6486                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6487         default:
6488                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6489                 g_assert_not_reached ();
6490         }
6491         
6492         return NULL;
6493 }
6494
6495 /**
6496  * mono_type_retrieve_from_typespec
6497  * @image: context where the image is created
6498  * @type_spec:  typespec token
6499  * @context: the generic context used to evaluate generic instantiations in
6500  */
6501 static MonoType *
6502 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6503 {
6504         MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6505
6506         *did_inflate = FALSE;
6507
6508         if (!t)
6509                 return NULL;
6510
6511         if (context && (context->class_inst || context->method_inst)) {
6512                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6513
6514                 if (!mono_error_ok (error)) {
6515                         g_assert (!mono_loader_get_last_error ());
6516                         return NULL;
6517                 }
6518
6519                 if (inflated) {
6520                         t = inflated;
6521                         *did_inflate = TRUE;
6522                 }
6523         }
6524         return t;
6525 }
6526
6527 /**
6528  * mono_class_create_from_typespec
6529  * @image: context where the image is created
6530  * @type_spec:  typespec token
6531  * @context: the generic context used to evaluate generic instantiations in
6532  */
6533 static MonoClass *
6534 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6535 {
6536         MonoClass *ret;
6537         gboolean inflated = FALSE;
6538         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6539         if (!mono_error_ok (error))
6540                 return NULL;
6541         ret = mono_class_from_mono_type (t);
6542         if (inflated)
6543                 mono_metadata_free_type (t);
6544         return ret;
6545 }
6546
6547 /**
6548  * mono_bounded_array_class_get:
6549  * @element_class: element class 
6550  * @rank: the dimension of the array class
6551  * @bounded: whenever the array has non-zero bounds
6552  *
6553  * Returns: a class object describing the array with element type @element_type and 
6554  * dimension @rank. 
6555  */
6556 MonoClass *
6557 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6558 {
6559         MonoImage *image;
6560         MonoClass *class;
6561         MonoClass *parent = NULL;
6562         GSList *list, *rootlist = NULL;
6563         int nsize;
6564         char *name;
6565         gboolean corlib_type = FALSE;
6566
6567         g_assert (rank <= 255);
6568
6569         if (rank > 1)
6570                 /* bounded only matters for one-dimensional arrays */
6571                 bounded = FALSE;
6572
6573         image = eclass->image;
6574
6575         if (rank == 1 && !bounded) {
6576                 /* 
6577                  * This case is very frequent not just during compilation because of calls 
6578                  * from mono_class_from_mono_type (), mono_array_new (), 
6579                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6580                  */
6581                 mono_mutex_lock (&image->szarray_cache_lock);
6582                 if (!image->szarray_cache)
6583                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6584                 class = g_hash_table_lookup (image->szarray_cache, eclass);
6585                 mono_mutex_unlock (&image->szarray_cache_lock);
6586                 if (class)
6587                         return class;
6588
6589                 mono_loader_lock ();
6590         } else {
6591                 mono_loader_lock ();
6592
6593                 if (!image->array_cache)
6594                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6595
6596                 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6597                         for (; list; list = list->next) {
6598                                 class = list->data;
6599                                 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6600                                         mono_loader_unlock ();
6601                                         return class;
6602                                 }
6603                         }
6604                 }
6605         }
6606
6607         /* for the building corlib use System.Array from it */
6608         if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6609                 parent = mono_class_from_name (image, "System", "Array");
6610                 corlib_type = TRUE;
6611         } else {
6612                 parent = mono_defaults.array_class;
6613                 if (!parent->inited)
6614                         mono_class_init (parent);
6615         }
6616
6617         class = mono_image_alloc0 (image, sizeof (MonoClass));
6618
6619         class->image = image;
6620         class->name_space = eclass->name_space;
6621         nsize = strlen (eclass->name);
6622         name = g_malloc (nsize + 2 + rank + 1);
6623         memcpy (name, eclass->name, nsize);
6624         name [nsize] = '[';
6625         if (rank > 1)
6626                 memset (name + nsize + 1, ',', rank - 1);
6627         if (bounded)
6628                 name [nsize + rank] = '*';
6629         name [nsize + rank + bounded] = ']';
6630         name [nsize + rank + bounded + 1] = 0;
6631         class->name = mono_image_strdup (image, name);
6632         g_free (name);
6633
6634         mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6635
6636         classes_size += sizeof (MonoClass);
6637
6638         class->type_token = 0;
6639         /* all arrays are marked serializable and sealed, bug #42779 */
6640         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6641         class->parent = parent;
6642         class->instance_size = mono_class_instance_size (class->parent);
6643
6644         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6645                 /*Arrays of those two types are invalid.*/
6646                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6647         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6648                 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6649                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6650                         g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6651                 }
6652                 /* element_size -1 is ok as this is not an instantitable type*/
6653                 class->sizes.element_size = -1;
6654         } else
6655                 class->sizes.element_size = mono_class_array_element_size (eclass);
6656
6657         mono_class_setup_supertypes (class);
6658
6659         if (eclass->generic_class)
6660                 mono_class_init (eclass);
6661         if (!eclass->size_inited)
6662                 mono_class_setup_fields (eclass);
6663         if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6664                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6665
6666         class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6667
6668         class->rank = rank;
6669         
6670         if (eclass->enumtype)
6671                 class->cast_class = eclass->element_class;
6672         else
6673                 class->cast_class = eclass;
6674
6675         switch (class->cast_class->byval_arg.type) {
6676         case MONO_TYPE_I1:
6677                 class->cast_class = mono_defaults.byte_class;
6678                 break;
6679         case MONO_TYPE_U2:
6680                 class->cast_class = mono_defaults.int16_class;
6681                 break;
6682         case MONO_TYPE_U4:
6683 #if SIZEOF_VOID_P == 4
6684         case MONO_TYPE_I:
6685         case MONO_TYPE_U:
6686 #endif
6687                 class->cast_class = mono_defaults.int32_class;
6688                 break;
6689         case MONO_TYPE_U8:
6690 #if SIZEOF_VOID_P == 8
6691         case MONO_TYPE_I:
6692         case MONO_TYPE_U:
6693 #endif
6694                 class->cast_class = mono_defaults.int64_class;
6695                 break;
6696         default:
6697                 break;
6698         }
6699
6700         class->element_class = eclass;
6701
6702         if ((rank > 1) || bounded) {
6703                 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6704                 class->byval_arg.type = MONO_TYPE_ARRAY;
6705                 class->byval_arg.data.array = at;
6706                 at->eklass = eclass;
6707                 at->rank = rank;
6708                 /* FIXME: complete.... */
6709         } else {
6710                 class->byval_arg.type = MONO_TYPE_SZARRAY;
6711                 class->byval_arg.data.klass = eclass;
6712         }
6713         class->this_arg = class->byval_arg;
6714         class->this_arg.byref = 1;
6715         if (corlib_type) {
6716                 class->inited = 1;
6717         }
6718
6719         class->generic_container = eclass->generic_container;
6720
6721         if (rank == 1 && !bounded) {
6722                 MonoClass *prev_class;
6723
6724                 mono_mutex_lock (&image->szarray_cache_lock);
6725                 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6726                 if (prev_class)
6727                         /* Someone got in before us */
6728                         class = prev_class;
6729                 else
6730                         g_hash_table_insert (image->szarray_cache, eclass, class);
6731                 mono_mutex_unlock (&image->szarray_cache_lock);
6732         } else {
6733                 list = g_slist_append (rootlist, class);
6734                 g_hash_table_insert (image->array_cache, eclass, list);
6735         }
6736
6737         mono_loader_unlock ();
6738
6739         mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6740
6741         return class;
6742 }
6743
6744 /**
6745  * mono_array_class_get:
6746  * @element_class: element class 
6747  * @rank: the dimension of the array class
6748  *
6749  * Returns: a class object describing the array with element type @element_type and 
6750  * dimension @rank. 
6751  */
6752 MonoClass *
6753 mono_array_class_get (MonoClass *eclass, guint32 rank)
6754 {
6755         return mono_bounded_array_class_get (eclass, rank, FALSE);
6756 }
6757
6758 /**
6759  * mono_class_instance_size:
6760  * @klass: a class 
6761  * 
6762  * Returns: the size of an object instance
6763  */
6764 gint32
6765 mono_class_instance_size (MonoClass *klass)
6766 {       
6767         if (!klass->size_inited)
6768                 mono_class_init (klass);
6769
6770         return klass->instance_size;
6771 }
6772
6773 /**
6774  * mono_class_min_align:
6775  * @klass: a class 
6776  * 
6777  * Returns: minimm alignment requirements 
6778  */
6779 gint32
6780 mono_class_min_align (MonoClass *klass)
6781 {       
6782         if (!klass->size_inited)
6783                 mono_class_init (klass);
6784
6785         return klass->min_align;
6786 }
6787
6788 /**
6789  * mono_class_value_size:
6790  * @klass: a class 
6791  *
6792  * This function is used for value types, and return the
6793  * space and the alignment to store that kind of value object.
6794  *
6795  * Returns: the size of a value of kind @klass
6796  */
6797 gint32
6798 mono_class_value_size      (MonoClass *klass, guint32 *align)
6799 {
6800         gint32 size;
6801
6802         /* fixme: check disable, because we still have external revereces to
6803          * mscorlib and Dummy Objects 
6804          */
6805         /*g_assert (klass->valuetype);*/
6806
6807         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6808
6809         if (align)
6810                 *align = klass->min_align;
6811
6812         return size;
6813 }
6814
6815 /**
6816  * mono_class_data_size:
6817  * @klass: a class 
6818  * 
6819  * Returns: the size of the static class data
6820  */
6821 gint32
6822 mono_class_data_size (MonoClass *klass)
6823 {       
6824         if (!klass->inited)
6825                 mono_class_init (klass);
6826         /* This can happen with dynamically created types */
6827         if (!klass->fields_inited)
6828                 mono_class_setup_fields_locking (klass);
6829
6830         /* in arrays, sizes.class_size is unioned with element_size
6831          * and arrays have no static fields
6832          */
6833         if (klass->rank)
6834                 return 0;
6835         return klass->sizes.class_size;
6836 }
6837
6838 /*
6839  * Auxiliary routine to mono_class_get_field
6840  *
6841  * Takes a field index instead of a field token.
6842  */
6843 static MonoClassField *
6844 mono_class_get_field_idx (MonoClass *class, int idx)
6845 {
6846         mono_class_setup_fields_locking (class);
6847         if (class->exception_type)
6848                 return NULL;
6849
6850         while (class) {
6851                 if (class->image->uncompressed_metadata) {
6852                         /* 
6853                          * class->field.first points to the FieldPtr table, while idx points into the
6854                          * Field table, so we have to do a search.
6855                          */
6856                         /*FIXME this is broken for types with multiple fields with the same name.*/
6857                         const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6858                         int i;
6859
6860                         for (i = 0; i < class->field.count; ++i)
6861                                 if (mono_field_get_name (&class->fields [i]) == name)
6862                                         return &class->fields [i];
6863                         g_assert_not_reached ();
6864                 } else {                        
6865                         if (class->field.count) {
6866                                 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6867                                         return &class->fields [idx - class->field.first];
6868                                 }
6869                         }
6870                 }
6871                 class = class->parent;
6872         }
6873         return NULL;
6874 }
6875
6876 /**
6877  * mono_class_get_field:
6878  * @class: the class to lookup the field.
6879  * @field_token: the field token
6880  *
6881  * Returns: A MonoClassField representing the type and offset of
6882  * the field, or a NULL value if the field does not belong to this
6883  * class.
6884  */
6885 MonoClassField *
6886 mono_class_get_field (MonoClass *class, guint32 field_token)
6887 {
6888         int idx = mono_metadata_token_index (field_token);
6889
6890         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6891
6892         return mono_class_get_field_idx (class, idx - 1);
6893 }
6894
6895 /**
6896  * mono_class_get_field_from_name:
6897  * @klass: the class to lookup the field.
6898  * @name: the field name
6899  *
6900  * Search the class @klass and it's parents for a field with the name @name.
6901  * 
6902  * Returns: the MonoClassField pointer of the named field or NULL
6903  */
6904 MonoClassField *
6905 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6906 {
6907         return mono_class_get_field_from_name_full (klass, name, NULL);
6908 }
6909
6910 /**
6911  * mono_class_get_field_from_name_full:
6912  * @klass: the class to lookup the field.
6913  * @name: the field name
6914  * @type: the type of the fields. This optional.
6915  *
6916  * Search the class @klass and it's parents for a field with the name @name and type @type.
6917  *
6918  * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6919  * of its generic type definition.
6920  *
6921  * Returns: the MonoClassField pointer of the named field or NULL
6922  */
6923 MonoClassField *
6924 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6925 {
6926         int i;
6927
6928         mono_class_setup_fields_locking (klass);
6929         if (klass->exception_type)
6930                 return NULL;
6931
6932         while (klass) {
6933                 for (i = 0; i < klass->field.count; ++i) {
6934                         MonoClassField *field = &klass->fields [i];
6935
6936                         if (strcmp (name, mono_field_get_name (field)) != 0)
6937                                 continue;
6938
6939                         if (type) {
6940                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6941                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6942                                         continue;
6943                         }
6944                         return field;
6945                 }
6946                 klass = klass->parent;
6947         }
6948         return NULL;
6949 }
6950
6951 /**
6952  * mono_class_get_field_token:
6953  * @field: the field we need the token of
6954  *
6955  * Get the token of a field. Note that the tokesn is only valid for the image
6956  * the field was loaded from. Don't use this function for fields in dynamic types.
6957  * 
6958  * Returns: the token representing the field in the image it was loaded from.
6959  */
6960 guint32
6961 mono_class_get_field_token (MonoClassField *field)
6962 {
6963         MonoClass *klass = field->parent;
6964         int i;
6965
6966         mono_class_setup_fields_locking (klass);
6967
6968         while (klass) {
6969                 if (!klass->fields)
6970                         return 0;
6971                 for (i = 0; i < klass->field.count; ++i) {
6972                         if (&klass->fields [i] == field) {
6973                                 int idx = klass->field.first + i + 1;
6974
6975                                 if (klass->image->uncompressed_metadata)
6976                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6977                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6978                         }
6979                 }
6980                 klass = klass->parent;
6981         }
6982
6983         g_assert_not_reached ();
6984         return 0;
6985 }
6986
6987 static int
6988 mono_field_get_index (MonoClassField *field)
6989 {
6990         int index = field - field->parent->fields;
6991
6992         g_assert (index >= 0 && index < field->parent->field.count);
6993
6994         return index;
6995 }
6996
6997 /*
6998  * mono_class_get_field_default_value:
6999  *
7000  * Return the default value of the field as a pointer into the metadata blob.
7001  */
7002 const char*
7003 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7004 {
7005         guint32 cindex;
7006         guint32 constant_cols [MONO_CONSTANT_SIZE];
7007         int field_index;
7008         MonoClass *klass = field->parent;
7009
7010         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7011
7012         if (!klass->ext || !klass->ext->field_def_values) {
7013                 MonoFieldDefaultValue *def_values;
7014
7015                 mono_class_alloc_ext (klass);
7016
7017                 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7018
7019                 mono_image_lock (klass->image);
7020                 mono_memory_barrier ();
7021                 if (!klass->ext->field_def_values)
7022                         klass->ext->field_def_values = def_values;
7023                 mono_image_unlock (klass->image);
7024         }
7025
7026         field_index = mono_field_get_index (field);
7027                 
7028         if (!klass->ext->field_def_values [field_index].data) {
7029                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7030                 if (!cindex)
7031                         return NULL;
7032
7033                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7034
7035                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7036                 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7037                 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7038         }
7039
7040         *def_type = klass->ext->field_def_values [field_index].def_type;
7041         return klass->ext->field_def_values [field_index].data;
7042 }
7043
7044 static int
7045 mono_property_get_index (MonoProperty *prop)
7046 {
7047         int index = prop - prop->parent->ext->properties;
7048
7049         g_assert (index >= 0 && index < prop->parent->ext->property.count);
7050
7051         return index;
7052 }
7053
7054 /*
7055  * mono_class_get_property_default_value:
7056  *
7057  * Return the default value of the field as a pointer into the metadata blob.
7058  */
7059 const char*
7060 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7061 {
7062         guint32 cindex;
7063         guint32 constant_cols [MONO_CONSTANT_SIZE];
7064         MonoClass *klass = property->parent;
7065
7066         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7067         /*
7068          * We don't cache here because it is not used by C# so it's quite rare, but
7069          * we still do the lookup in klass->ext because that is where the data
7070          * is stored for dynamic assemblies.
7071          */
7072
7073         if (image_is_dynamic (klass->image)) {
7074                 int prop_index = mono_property_get_index (property);
7075                 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7076                         *def_type = klass->ext->prop_def_values [prop_index].def_type;
7077                         return klass->ext->prop_def_values [prop_index].data;
7078                 }
7079                 return NULL;
7080         }
7081         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7082         if (!cindex)
7083                 return NULL;
7084
7085         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7086         *def_type = constant_cols [MONO_CONSTANT_TYPE];
7087         return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7088 }
7089
7090 guint32
7091 mono_class_get_event_token (MonoEvent *event)
7092 {
7093         MonoClass *klass = event->parent;
7094         int i;
7095
7096         while (klass) {
7097                 if (klass->ext) {
7098                         for (i = 0; i < klass->ext->event.count; ++i) {
7099                                 if (&klass->ext->events [i] == event)
7100                                         return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7101                         }
7102                 }
7103                 klass = klass->parent;
7104         }
7105
7106         g_assert_not_reached ();
7107         return 0;
7108 }
7109
7110 MonoProperty*
7111 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7112 {
7113         while (klass) {
7114                 MonoProperty* p;
7115                 gpointer iter = NULL;
7116                 while ((p = mono_class_get_properties (klass, &iter))) {
7117                         if (! strcmp (name, p->name))
7118                                 return p;
7119                 }
7120                 klass = klass->parent;
7121         }
7122         return NULL;
7123 }
7124
7125 guint32
7126 mono_class_get_property_token (MonoProperty *prop)
7127 {
7128         MonoClass *klass = prop->parent;
7129         while (klass) {
7130                 MonoProperty* p;
7131                 int i = 0;
7132                 gpointer iter = NULL;
7133                 while ((p = mono_class_get_properties (klass, &iter))) {
7134                         if (&klass->ext->properties [i] == prop)
7135                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7136                         
7137                         i ++;
7138                 }
7139                 klass = klass->parent;
7140         }
7141
7142         g_assert_not_reached ();
7143         return 0;
7144 }
7145
7146 char *
7147 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7148 {
7149         const char *name, *nspace;
7150         if (image_is_dynamic (image))
7151                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7152         
7153         switch (type_token & 0xff000000){
7154         case MONO_TOKEN_TYPE_DEF: {
7155                 guint32 cols [MONO_TYPEDEF_SIZE];
7156                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7157                 guint tidx = mono_metadata_token_index (type_token);
7158
7159                 if (tidx > tt->rows)
7160                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7161
7162                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7163                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7164                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7165                 if (strlen (nspace) == 0)
7166                         return g_strdup_printf ("%s", name);
7167                 else
7168                         return g_strdup_printf ("%s.%s", nspace, name);
7169         }
7170
7171         case MONO_TOKEN_TYPE_REF: {
7172                 MonoError error;
7173                 guint32 cols [MONO_TYPEREF_SIZE];
7174                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7175                 guint tidx = mono_metadata_token_index (type_token);
7176
7177                 if (tidx > t->rows)
7178                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7179
7180                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7181                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7182                         mono_error_cleanup (&error);
7183                         return msg;
7184                 }
7185
7186                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7187                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7188                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7189                 if (strlen (nspace) == 0)
7190                         return g_strdup_printf ("%s", name);
7191                 else
7192                         return g_strdup_printf ("%s.%s", nspace, name);
7193         }
7194                 
7195         case MONO_TOKEN_TYPE_SPEC:
7196                 return g_strdup_printf ("Typespec 0x%08x", type_token);
7197         default:
7198                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7199         }
7200 }
7201
7202 static char *
7203 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7204 {
7205         if (image_is_dynamic (image))
7206                 return g_strdup_printf ("DynamicAssembly %s", image->name);
7207         
7208         switch (type_token & 0xff000000){
7209         case MONO_TOKEN_TYPE_DEF:
7210                 if (image->assembly)
7211                         return mono_stringify_assembly_name (&image->assembly->aname);
7212                 else if (image->assembly_name)
7213                         return g_strdup (image->assembly_name);
7214                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7215         case MONO_TOKEN_TYPE_REF: {
7216                 MonoError error;
7217                 MonoAssemblyName aname;
7218                 guint32 cols [MONO_TYPEREF_SIZE];
7219                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7220                 guint32 idx = mono_metadata_token_index (type_token);
7221
7222                 if (idx > t->rows)
7223                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7224         
7225                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7226                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7227                         mono_error_cleanup (&error);
7228                         return msg;
7229                 }
7230                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7231
7232                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7233                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7234                 case MONO_RESOLUTION_SCOPE_MODULE:
7235                         /* FIXME: */
7236                         return g_strdup ("");
7237                 case MONO_RESOLUTION_SCOPE_MODULEREF:
7238                         /* FIXME: */
7239                         return g_strdup ("");
7240                 case MONO_RESOLUTION_SCOPE_TYPEREF:
7241                         /* FIXME: */
7242                         return g_strdup ("");
7243                 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7244                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7245                         return mono_stringify_assembly_name (&aname);
7246                 default:
7247                         g_assert_not_reached ();
7248                 }
7249                 break;
7250         }
7251         case MONO_TOKEN_TYPE_SPEC:
7252                 /* FIXME: */
7253                 return g_strdup ("");
7254         default:
7255                 g_assert_not_reached ();
7256         }
7257
7258         return NULL;
7259 }
7260
7261 /**
7262  * mono_class_get_full:
7263  * @image: the image where the class resides
7264  * @type_token: the token for the class
7265  * @context: the generic context used to evaluate generic instantiations in
7266  * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7267  *
7268  * Returns: the MonoClass that represents @type_token in @image
7269  */
7270 MonoClass *
7271 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7272 {
7273         MonoError error;
7274         MonoClass *class;
7275         class = mono_class_get_checked (image, type_token, &error);
7276
7277         if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7278                 class = mono_class_inflate_generic_class_checked (class, context, &error);
7279
7280         g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7281         return class;
7282 }
7283
7284
7285 MonoClass *
7286 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7287 {
7288         MonoClass *class;
7289
7290         mono_error_init (error);
7291         class = mono_class_get_checked (image, type_token, error);
7292
7293         if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7294                 class = mono_class_inflate_generic_class_checked (class, context, error);
7295
7296         return class;
7297 }
7298 /**
7299  * mono_class_get_checked:
7300  * @image: the image where the class resides
7301  * @type_token: the token for the class
7302  * @error: error object to return any error
7303  *
7304  * Returns: the MonoClass that represents @type_token in @image
7305  */
7306 MonoClass *
7307 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7308 {
7309         MonoClass *class = NULL;
7310
7311         mono_error_init (error);
7312
7313         if (image_is_dynamic (image)) {
7314                 int table = mono_metadata_token_table (type_token);
7315
7316                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7317                         mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7318                         return NULL;
7319                 }
7320                 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7321                 goto done;
7322         }
7323
7324         switch (type_token & 0xff000000){
7325         case MONO_TOKEN_TYPE_DEF:
7326                 class = mono_class_create_from_typedef (image, type_token, error);
7327                 break;          
7328         case MONO_TOKEN_TYPE_REF:
7329                 class = mono_class_from_typeref_checked (image, type_token, error);
7330                 break;
7331         case MONO_TOKEN_TYPE_SPEC:
7332                 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7333                 break;
7334         default:
7335                 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7336         }
7337
7338 done:
7339         /* Generic case, should be avoided for when a better error is possible. */
7340         if (!class && mono_error_ok (error)) {
7341                 char *name = mono_class_name_from_token (image, type_token);
7342                 char *assembly = mono_assembly_name_from_token (image, type_token);
7343                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7344         }
7345
7346         return class;
7347 }
7348
7349
7350 /**
7351  * mono_type_get_checked:
7352  * @image: the image where the type resides
7353  * @type_token: the token for the type
7354  * @context: the generic context used to evaluate generic instantiations in
7355  * @error: Error handling context
7356  *
7357  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7358  * 
7359  * Returns: the MonoType that represents @type_token in @image
7360  */
7361 MonoType *
7362 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7363 {
7364         MonoType *type = NULL;
7365         gboolean inflated = FALSE;
7366
7367         mono_error_init (error);
7368
7369         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7370         if (image_is_dynamic (image))
7371                 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7372
7373         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7374                 MonoClass *class = mono_class_get_checked (image, type_token, error);
7375
7376                 if (!class) {
7377                         g_assert (!mono_loader_get_last_error ());
7378                         return NULL;
7379                 }
7380
7381                 g_assert (class);
7382                 return mono_class_get_type (class);
7383         }
7384
7385         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7386
7387         if (!type) {
7388                 g_assert (!mono_loader_get_last_error ());
7389                 return NULL;
7390         }
7391
7392         if (inflated) {
7393                 MonoType *tmp = type;
7394                 type = mono_class_get_type (mono_class_from_mono_type (type));
7395                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7396                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7397                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7398                  *
7399                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7400                  * */
7401                 if (type->type != tmp->type)
7402                         type = tmp;
7403                 else
7404                         mono_metadata_free_type (tmp);
7405         }
7406         return type;
7407 }
7408
7409
7410 MonoClass *
7411 mono_class_get (MonoImage *image, guint32 type_token)
7412 {
7413         return mono_class_get_full (image, type_token, NULL);
7414 }
7415
7416 /**
7417  * mono_image_init_name_cache:
7418  *
7419  *  Initializes the class name cache stored in image->name_cache.
7420  *
7421  * LOCKING: Acquires the corresponding image lock.
7422  */
7423 void
7424 mono_image_init_name_cache (MonoImage *image)
7425 {
7426         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7427         guint32 cols [MONO_TYPEDEF_SIZE];
7428         const char *name;
7429         const char *nspace;
7430         guint32 i, visib, nspace_index;
7431         GHashTable *name_cache2, *nspace_table;
7432
7433         mono_image_lock (image);
7434
7435         if (image->name_cache) {
7436                 mono_image_unlock (image);
7437                 return;
7438         }
7439
7440         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7441
7442         if (image_is_dynamic (image)) {
7443                 mono_image_unlock (image);
7444                 return;
7445         }
7446
7447         /* Temporary hash table to avoid lookups in the nspace_table */
7448         name_cache2 = g_hash_table_new (NULL, NULL);
7449
7450         for (i = 1; i <= t->rows; ++i) {
7451                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7452                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7453                 /*
7454                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7455                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7456                  */
7457                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7458                         continue;
7459                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7460                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7461
7462                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7463                 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7464                 if (!nspace_table) {
7465                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7466                         g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7467                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7468                                                                  nspace_table);
7469                 }
7470                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7471         }
7472
7473         /* Load type names from EXPORTEDTYPES table */
7474         {
7475                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7476                 guint32 cols [MONO_EXP_TYPE_SIZE];
7477                 int i;
7478
7479                 for (i = 0; i < t->rows; ++i) {
7480                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7481                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7482                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7483
7484                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7485                         nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7486                         if (!nspace_table) {
7487                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7488                                 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7489                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7490                                                                          nspace_table);
7491                         }
7492                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7493                 }
7494         }
7495
7496         g_hash_table_destroy (name_cache2);
7497         mono_image_unlock (image);
7498 }
7499
7500 /*FIXME Only dynamic assemblies should allow this operation.*/
7501 void
7502 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7503                                                           const char *name, guint32 index)
7504 {
7505         GHashTable *nspace_table;
7506         GHashTable *name_cache;
7507         guint32 old_index;
7508
7509         mono_image_lock (image);
7510
7511         if (!image->name_cache)
7512                 mono_image_init_name_cache (image);
7513
7514         name_cache = image->name_cache;
7515         if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7516                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7517                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7518         }
7519
7520         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7521                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7522
7523         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7524
7525         mono_image_unlock (image);
7526 }
7527
7528 typedef struct {
7529         gconstpointer key;
7530         gpointer value;
7531 } FindUserData;
7532
7533 static void
7534 find_nocase (gpointer key, gpointer value, gpointer user_data)
7535 {
7536         char *name = (char*)key;
7537         FindUserData *data = (FindUserData*)user_data;
7538
7539         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7540                 data->value = value;
7541 }
7542
7543 /**
7544  * mono_class_from_name_case:
7545  * @image: The MonoImage where the type is looked up in
7546  * @name_space: the type namespace
7547  * @name: the type short name.
7548  * @deprecated: use the _checked variant
7549  *
7550  * Obtains a MonoClass with a given namespace and a given name which
7551  * is located in the given MonoImage.   The namespace and name
7552  * lookups are case insensitive.
7553  */
7554 MonoClass *
7555 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7556 {
7557         MonoError error;
7558         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7559         g_assert (!mono_error_ok (&error));
7560         return res;
7561 }
7562
7563 MonoClass *
7564 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7565 {
7566         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7567         guint32 cols [MONO_TYPEDEF_SIZE];
7568         const char *n;
7569         const char *nspace;
7570         guint32 i, visib;
7571
7572         mono_error_init (error);
7573
7574         if (image_is_dynamic (image)) {
7575                 guint32 token = 0;
7576                 FindUserData user_data;
7577
7578                 mono_image_lock (image);
7579
7580                 if (!image->name_cache)
7581                         mono_image_init_name_cache (image);
7582
7583                 user_data.key = name_space;
7584                 user_data.value = NULL;
7585                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7586
7587                 if (user_data.value) {
7588                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7589
7590                         user_data.key = name;
7591                         user_data.value = NULL;
7592
7593                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7594                         
7595                         if (user_data.value)
7596                                 token = GPOINTER_TO_UINT (user_data.value);
7597                 }
7598
7599                 mono_image_unlock (image);
7600                 
7601                 if (token)
7602                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7603                 else
7604                         return NULL;
7605
7606         }
7607
7608         /* add a cache if needed */
7609         for (i = 1; i <= t->rows; ++i) {
7610                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7611                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7612                 /*
7613                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7614                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7615                  */
7616                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7617                         continue;
7618                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7619                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7620                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7621                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7622         }
7623         return NULL;
7624 }
7625
7626 static MonoClass*
7627 return_nested_in (MonoClass *class, char *nested)
7628 {
7629         MonoClass *found;
7630         char *s = strchr (nested, '/');
7631         gpointer iter = NULL;
7632
7633         if (s) {
7634                 *s = 0;
7635                 s++;
7636         }
7637
7638         while ((found = mono_class_get_nested_types (class, &iter))) {
7639                 if (strcmp (found->name, nested) == 0) {
7640                         if (s)
7641                                 return return_nested_in (found, s);
7642                         return found;
7643                 }
7644         }
7645         return NULL;
7646 }
7647
7648 static MonoClass*
7649 search_modules (MonoImage *image, const char *name_space, const char *name)
7650 {
7651         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7652         MonoImage *file_image;
7653         MonoClass *class;
7654         int i;
7655
7656         /* 
7657          * The EXPORTEDTYPES table only contains public types, so have to search the
7658          * modules as well.
7659          * Note: image->modules contains the contents of the MODULEREF table, while
7660          * the real module list is in the FILE table.
7661          */
7662         for (i = 0; i < file_table->rows; i++) {
7663                 guint32 cols [MONO_FILE_SIZE];
7664                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7665                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7666                         continue;
7667
7668                 file_image = mono_image_load_file_for_image (image, i + 1);
7669                 if (file_image) {
7670                         class = mono_class_from_name (file_image, name_space, name);
7671                         if (class)
7672                                 return class;
7673                 }
7674         }
7675
7676         return NULL;
7677 }
7678
7679 /**
7680  * mono_class_from_name:
7681  * @image: The MonoImage where the type is looked up in
7682  * @name_space: the type namespace
7683  * @name: the type short name.
7684  *
7685  * Obtains a MonoClass with a given namespace and a given name which
7686  * is located in the given MonoImage.
7687  *
7688  * To reference nested classes, use the "/" character as a separator.
7689  * For example use "Foo/Bar" to reference the class Bar that is nested
7690  * inside Foo, like this: "class Foo { class Bar {} }".
7691  */
7692 MonoClass *
7693 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7694 {
7695         MonoError error;
7696         GHashTable *nspace_table;
7697         MonoImage *loaded_image;
7698         guint32 token = 0;
7699         int i;
7700         MonoClass *class;
7701         char *nested;
7702         char buf [1024];
7703
7704         if ((nested = strchr (name, '/'))) {
7705                 int pos = nested - name;
7706                 int len = strlen (name);
7707                 if (len > 1023)
7708                         return NULL;
7709                 memcpy (buf, name, len + 1);
7710                 buf [pos] = 0;
7711                 nested = buf + pos + 1;
7712                 name = buf;
7713         }
7714
7715         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7716         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7717                 gboolean res = get_class_from_name (image, name_space, name, &class);
7718                 if (res) {
7719                         if (!class)
7720                                 class = search_modules (image, name_space, name);
7721                         if (nested)
7722                                 return class ? return_nested_in (class, nested) : NULL;
7723                         else
7724                                 return class;
7725                 }
7726         }
7727
7728         mono_image_lock (image);
7729
7730         if (!image->name_cache)
7731                 mono_image_init_name_cache (image);
7732
7733         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7734
7735         if (nspace_table)
7736                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7737
7738         mono_image_unlock (image);
7739
7740         if (!token && image_is_dynamic (image) && image->modules) {
7741                 /* Search modules as well */
7742                 for (i = 0; i < image->module_count; ++i) {
7743                         MonoImage *module = image->modules [i];
7744
7745                         class = mono_class_from_name (module, name_space, name);
7746                         if (class)
7747                                 return class;
7748                 }
7749         }
7750
7751         if (!token) {
7752                 class = search_modules (image, name_space, name);
7753                 if (class)
7754                         return class;
7755         }
7756
7757         if (!token)
7758                 return NULL;
7759
7760         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7761                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7762                 guint32 cols [MONO_EXP_TYPE_SIZE];
7763                 guint32 idx, impl;
7764
7765                 idx = mono_metadata_token_index (token);
7766
7767                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7768
7769                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7770                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7771                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7772                         if (!loaded_image)
7773                                 return NULL;
7774                         class = mono_class_from_name (loaded_image, name_space, name);
7775                         if (nested)
7776                                 return return_nested_in (class, nested);
7777                         return class;
7778                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7779                         guint32 assembly_idx;
7780
7781                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7782
7783                         mono_assembly_load_reference (image, assembly_idx - 1);
7784                         g_assert (image->references [assembly_idx - 1]);
7785                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7786                                 return NULL;                    
7787                         else
7788                                 /* FIXME: Cycle detection */
7789                                 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7790                 } else {
7791                         g_error ("not yet implemented");
7792                 }
7793         }
7794
7795         token = MONO_TOKEN_TYPE_DEF | token;
7796
7797         class = mono_class_get_checked (image, token, &error);
7798         if (!mono_error_ok (&error)) {
7799                 mono_loader_set_error_from_mono_error (&error);
7800                 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7801         }
7802         if (nested)
7803                 return return_nested_in (class, nested);
7804         return class;
7805 }
7806
7807 /**
7808  * mono_class_is_subclass_of:
7809  * @klass: class to probe if it is a subclass of another one
7810  * @klassc: the class we suspect is the base class
7811  * @check_interfaces: whether we should perform interface checks
7812  *
7813  * This method determines whether @klass is a subclass of @klassc.
7814  *
7815  * If the @check_interfaces flag is set, then if @klassc is an interface
7816  * this method return true if the @klass implements the interface or
7817  * if @klass is an interface, if one of its base classes is @klass.
7818  *
7819  * If @check_interfaces is false then, then if @klass is not an interface
7820  * then it returns true if the @klass is a subclass of @klassc.
7821  *
7822  * if @klass is an interface and @klassc is System.Object, then this function
7823  * return true.
7824  *
7825  */
7826 gboolean
7827 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
7828                            gboolean check_interfaces)
7829 {
7830 /*FIXME test for interfaces with variant generic arguments*/
7831         
7832         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7833                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7834                         return TRUE;
7835         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7836                 int i;
7837
7838                 for (i = 0; i < klass->interface_count; i ++) {
7839                         MonoClass *ic =  klass->interfaces [i];
7840                         if (ic == klassc)
7841                                 return TRUE;
7842                 }
7843         } else {
7844                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7845                         return TRUE;
7846         }
7847
7848         /* 
7849          * MS.NET thinks interfaces are a subclass of Object, so we think it as
7850          * well.
7851          */
7852         if (klassc == mono_defaults.object_class)
7853                 return TRUE;
7854
7855         return FALSE;
7856 }
7857
7858 static gboolean
7859 mono_type_is_generic_argument (MonoType *type)
7860 {
7861         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7862 }
7863
7864 gboolean
7865 mono_class_has_variant_generic_params (MonoClass *klass)
7866 {
7867         int i;
7868         MonoGenericContainer *container;
7869
7870         if (!klass->generic_class)
7871                 return FALSE;
7872
7873         container = klass->generic_class->container_class->generic_container;
7874
7875         for (i = 0; i < container->type_argc; ++i)
7876                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7877                         return TRUE;
7878
7879         return FALSE;
7880 }
7881
7882 static gboolean
7883 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7884 {
7885         if (target == candidate)
7886                 return TRUE;
7887
7888         if (check_for_reference_conv &&
7889                 mono_type_is_generic_argument (&target->byval_arg) &&
7890                 mono_type_is_generic_argument (&candidate->byval_arg)) {
7891                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7892                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7893
7894                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7895                         return FALSE;
7896         }
7897         if (!mono_class_is_assignable_from (target, candidate))
7898                 return FALSE;
7899         return TRUE;
7900 }
7901
7902 /**
7903  * @container the generic container from the GTD
7904  * @klass: the class to be assigned to
7905  * @oklass: the source class
7906  * 
7907  * Both klass and oklass must be instances of the same generic interface.
7908  * Return true if @klass can be assigned to a @klass variable
7909  */
7910 gboolean
7911 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7912 {
7913         int j;
7914         MonoType **klass_argv, **oklass_argv;
7915         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7916         MonoGenericContainer *container = klass_gtd->generic_container;
7917
7918         if (klass == oklass)
7919                 return TRUE;
7920
7921         /*Viable candidates are instances of the same generic interface*/
7922         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7923                 return FALSE;
7924
7925         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7926         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7927
7928         for (j = 0; j < container->type_argc; ++j) {
7929                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7930                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7931
7932                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7933                         return FALSE;
7934
7935                 /*
7936                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7937                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7938                  */
7939                 if (param1_class != param2_class) {
7940                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7941                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7942                                         return FALSE;
7943                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7944                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7945                                         return FALSE;
7946                         } else
7947                                 return FALSE;
7948                 }
7949         }
7950         return TRUE;
7951 }
7952
7953 static gboolean
7954 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7955 {
7956         MonoGenericParam *gparam, *ogparam;
7957         MonoGenericParamInfo *tinfo, *cinfo;
7958         MonoClass **candidate_class;
7959         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7960         int tmask, cmask;
7961
7962         if (target == candidate)
7963                 return TRUE;
7964         if (target->byval_arg.type != candidate->byval_arg.type)
7965                 return FALSE;
7966
7967         gparam = target->byval_arg.data.generic_param;
7968         ogparam = candidate->byval_arg.data.generic_param;
7969         tinfo = mono_generic_param_info (gparam);
7970         cinfo = mono_generic_param_info (ogparam);
7971
7972         class_constraint_satisfied = FALSE;
7973         valuetype_constraint_satisfied = FALSE;
7974
7975         /*candidate must have a super set of target's special constraints*/
7976         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7977         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7978
7979         if (cinfo->constraints) {
7980                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7981                         MonoClass *cc = *candidate_class;
7982
7983                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7984                                 class_constraint_satisfied = TRUE;
7985                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7986                                 valuetype_constraint_satisfied = TRUE;
7987                 }
7988         }
7989         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7990         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7991
7992         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7993                 return FALSE;
7994         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7995                 return FALSE;
7996         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7997                 valuetype_constraint_satisfied)) {
7998                 return FALSE;
7999         }
8000
8001
8002         /*candidate type constraints must be a superset of target's*/
8003         if (tinfo->constraints) {
8004                 MonoClass **target_class;
8005                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8006                         MonoClass *tc = *target_class;
8007
8008                         /*
8009                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8010                          * check it's constraints since it satisfy the constraint by itself.
8011                          */
8012                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8013                                 continue;
8014
8015                         if (!cinfo->constraints)
8016                                 return FALSE;
8017
8018                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8019                                 MonoClass *cc = *candidate_class;
8020
8021                                 if (mono_class_is_assignable_from (tc, cc))
8022                                         break;
8023
8024                                 /*
8025                                  * This happens when we have the following:
8026                                  *
8027                                  * Bar<K> where K : IFace
8028                                  * Foo<T, U> where T : U where U : IFace
8029                                  *      ...
8030                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8031                                  *
8032                                  */
8033                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8034                                         if (mono_gparam_is_assignable_from (target, cc))
8035                                                 break;
8036                                 }
8037                         }
8038                         if (!*candidate_class)
8039                                 return FALSE;
8040                 }
8041         }
8042
8043         /*candidate itself must have a constraint that satisfy target*/
8044         if (cinfo->constraints) {
8045                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8046                         MonoClass *cc = *candidate_class;
8047                         if (mono_class_is_assignable_from (target, cc))
8048                                 return TRUE;
8049                 }
8050         }
8051         return FALSE;
8052 }
8053
8054 /**
8055  * mono_class_is_assignable_from:
8056  * @klass: the class to be assigned to
8057  * @oklass: the source class
8058  *
8059  * Return: true if an instance of object oklass can be assigned to an
8060  * instance of object @klass
8061  */
8062 gboolean
8063 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8064 {
8065         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8066         if (!klass->inited)
8067                 mono_class_init (klass);
8068
8069         if (!oklass->inited)
8070                 mono_class_init (oklass);
8071
8072         if (klass->exception_type || oklass->exception_type)
8073                 return FALSE;
8074
8075         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8076                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8077                         return FALSE;
8078                 return mono_gparam_is_assignable_from (klass, oklass);
8079         }
8080
8081         if (MONO_CLASS_IS_INTERFACE (klass)) {
8082                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8083                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8084                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8085                         int i;
8086
8087                         if (constraints) {
8088                                 for (i = 0; constraints [i]; ++i) {
8089                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8090                                                 return TRUE;
8091                                 }
8092                         }
8093
8094                         return FALSE;
8095                 }
8096
8097                 /* interface_offsets might not be set for dynamic classes */
8098                 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8099                         /* 
8100                          * oklass might be a generic type parameter but they have 
8101                          * interface_offsets set.
8102                          */
8103                         return mono_reflection_call_is_assignable_to (oklass, klass);
8104                 if (!oklass->interface_bitmap)
8105                         /* Happens with generic instances of not-yet created dynamic types */
8106                         return FALSE;
8107                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8108                         return TRUE;
8109
8110                 if (mono_class_has_variant_generic_params (klass)) {
8111                         MonoError error;
8112                         int i;
8113                         mono_class_setup_interfaces (oklass, &error);
8114                         if (!mono_error_ok (&error)) {
8115                                 mono_error_cleanup (&error);
8116                                 return FALSE;
8117                         }
8118
8119                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8120                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8121                                 MonoClass *iface = oklass->interfaces_packed [i];
8122
8123                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8124                                         return TRUE;
8125                         }
8126                 }
8127                 return FALSE;
8128         } else if (klass->delegate) {
8129                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8130                         return TRUE;
8131         }else if (klass->rank) {
8132                 MonoClass *eclass, *eoclass;
8133
8134                 if (oklass->rank != klass->rank)
8135                         return FALSE;
8136
8137                 /* vectors vs. one dimensional arrays */
8138                 if (oklass->byval_arg.type != klass->byval_arg.type)
8139                         return FALSE;
8140
8141                 eclass = klass->cast_class;
8142                 eoclass = oklass->cast_class;
8143
8144                 /* 
8145                  * a is b does not imply a[] is b[] when a is a valuetype, and
8146                  * b is a reference type.
8147                  */
8148
8149                 if (eoclass->valuetype) {
8150                         if ((eclass == mono_defaults.enum_class) || 
8151                                 (eclass == mono_defaults.enum_class->parent) ||
8152                                 (eclass == mono_defaults.object_class))
8153                                 return FALSE;
8154                 }
8155
8156                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8157         } else if (mono_class_is_nullable (klass)) {
8158                 if (mono_class_is_nullable (oklass))
8159                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8160                 else
8161                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8162         } else if (klass == mono_defaults.object_class)
8163                 return TRUE;
8164
8165         return mono_class_has_parent (oklass, klass);
8166 }       
8167
8168 /*Check if @oklass is variant compatible with @klass.*/
8169 static gboolean
8170 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8171 {
8172         int j;
8173         MonoType **klass_argv, **oklass_argv;
8174         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8175         MonoGenericContainer *container = klass_gtd->generic_container;
8176
8177         /*Viable candidates are instances of the same generic interface*/
8178         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8179                 return FALSE;
8180
8181         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8182         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8183
8184         for (j = 0; j < container->type_argc; ++j) {
8185                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8186                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8187
8188                 if (param1_class->valuetype != param2_class->valuetype)
8189                         return FALSE;
8190
8191                 /*
8192                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8193                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8194                  */
8195                 if (param1_class != param2_class) {
8196                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8197                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8198                                         return FALSE;
8199                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8200                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8201                                         return FALSE;
8202                         } else
8203                                 return FALSE;
8204                 }
8205         }
8206         return TRUE;
8207 }
8208 /*Check if @candidate implements the interface @target*/
8209 static gboolean
8210 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8211 {
8212         MonoError error;
8213         int i;
8214         gboolean is_variant = mono_class_has_variant_generic_params (target);
8215
8216         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8217                 if (mono_class_is_variant_compatible_slow (target, candidate))
8218                         return TRUE;
8219         }
8220
8221         do {
8222                 if (candidate == target)
8223                         return TRUE;
8224
8225                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8226                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8227                         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8228                         int j;
8229                         if (tb && tb->interfaces) {
8230                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8231                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8232                                         MonoClass *iface_class;
8233
8234                                         /* we can't realize the type here since it can do pretty much anything. */
8235                                         if (!iface->type)
8236                                                 continue;
8237                                         iface_class = mono_class_from_mono_type (iface->type);
8238                                         if (iface_class == target)
8239                                                 return TRUE;
8240                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8241                                                 return TRUE;
8242                                         if (mono_class_implement_interface_slow (target, iface_class))
8243                                                 return TRUE;
8244                                 }
8245                         }
8246                 } else {
8247                         /*setup_interfaces don't mono_class_init anything*/
8248                         /*FIXME this doesn't handle primitive type arrays.
8249                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8250                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8251                         */
8252                         mono_class_setup_interfaces (candidate, &error);
8253                         if (!mono_error_ok (&error)) {
8254                                 mono_error_cleanup (&error);
8255                                 return FALSE;
8256                         }
8257
8258                         for (i = 0; i < candidate->interface_count; ++i) {
8259                                 if (candidate->interfaces [i] == target)
8260                                         return TRUE;
8261                                 
8262                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8263                                         return TRUE;
8264
8265                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8266                                         return TRUE;
8267                         }
8268                 }
8269                 candidate = candidate->parent;
8270         } while (candidate);
8271
8272         return FALSE;
8273 }
8274
8275 /*
8276  * Check if @oklass can be assigned to @klass.
8277  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8278  */
8279 gboolean
8280 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8281 {
8282         if (candidate == target)
8283                 return TRUE;
8284         if (target == mono_defaults.object_class)
8285                 return TRUE;
8286
8287         if (mono_class_has_parent (candidate, target))
8288                 return TRUE;
8289
8290         /*If target is not an interface there is no need to check them.*/
8291         if (MONO_CLASS_IS_INTERFACE (target))
8292                 return mono_class_implement_interface_slow (target, candidate);
8293
8294         if (target->delegate && mono_class_has_variant_generic_params (target))
8295                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8296
8297         if (target->rank) {
8298                 MonoClass *eclass, *eoclass;
8299
8300                 if (target->rank != candidate->rank)
8301                         return FALSE;
8302
8303                 /* vectors vs. one dimensional arrays */
8304                 if (target->byval_arg.type != candidate->byval_arg.type)
8305                         return FALSE;
8306
8307                 eclass = target->cast_class;
8308                 eoclass = candidate->cast_class;
8309
8310                 /*
8311                  * a is b does not imply a[] is b[] when a is a valuetype, and
8312                  * b is a reference type.
8313                  */
8314
8315                 if (eoclass->valuetype) {
8316                         if ((eclass == mono_defaults.enum_class) ||
8317                                 (eclass == mono_defaults.enum_class->parent) ||
8318                                 (eclass == mono_defaults.object_class))
8319                                 return FALSE;
8320                 }
8321
8322                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8323         }
8324         /*FIXME properly handle nullables */
8325         /*FIXME properly handle (M)VAR */
8326         return FALSE;
8327 }
8328
8329 /**
8330  * mono_class_get_cctor:
8331  * @klass: A MonoClass pointer
8332  *
8333  * Returns: the static constructor of @klass if it exists, NULL otherwise.
8334  */
8335 MonoMethod*
8336 mono_class_get_cctor (MonoClass *klass)
8337 {
8338         MonoCachedClassInfo cached_info;
8339
8340         if (image_is_dynamic (klass->image)) {
8341                 /* 
8342                  * has_cctor is not set for these classes because mono_class_init () is
8343                  * not run for them.
8344                  */
8345                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8346         }
8347
8348         if (!klass->has_cctor)
8349                 return NULL;
8350
8351         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8352                 MonoError error;
8353                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8354                 if (!mono_error_ok (&error))
8355                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8356                 return result;
8357         }
8358
8359         if (klass->generic_class && !klass->methods)
8360                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8361
8362         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8363 }
8364
8365 /**
8366  * mono_class_get_finalizer:
8367  * @klass: The MonoClass pointer
8368  *
8369  * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8370  */
8371 MonoMethod*
8372 mono_class_get_finalizer (MonoClass *klass)
8373 {
8374         MonoCachedClassInfo cached_info;
8375
8376         if (!klass->inited)
8377                 mono_class_init (klass);
8378         if (!mono_class_has_finalizer (klass))
8379                 return NULL;
8380
8381         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8382                 MonoError error;
8383                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8384                 if (!mono_error_ok (&error))
8385                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8386                 return result;
8387         }else {
8388                 mono_class_setup_vtable (klass);
8389                 return klass->vtable [finalize_slot];
8390         }
8391 }
8392
8393 /**
8394  * mono_class_needs_cctor_run:
8395  * @klass: the MonoClass pointer
8396  * @caller: a MonoMethod describing the caller
8397  *
8398  * Determines whenever the class has a static constructor and whenever it
8399  * needs to be called when executing CALLER.
8400  */
8401 gboolean
8402 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8403 {
8404         MonoMethod *method;
8405
8406         method = mono_class_get_cctor (klass);
8407         if (method)
8408                 return (method == caller) ? FALSE : TRUE;
8409         else
8410                 return FALSE;
8411 }
8412
8413 /**
8414  * mono_class_array_element_size:
8415  * @klass: 
8416  *
8417  * Returns: the number of bytes an element of type @klass
8418  * uses when stored into an array.
8419  */
8420 gint32
8421 mono_class_array_element_size (MonoClass *klass)
8422 {
8423         MonoType *type = &klass->byval_arg;
8424         
8425 handle_enum:
8426         switch (type->type) {
8427         case MONO_TYPE_I1:
8428         case MONO_TYPE_U1:
8429         case MONO_TYPE_BOOLEAN:
8430                 return 1;
8431         case MONO_TYPE_I2:
8432         case MONO_TYPE_U2:
8433         case MONO_TYPE_CHAR:
8434                 return 2;
8435         case MONO_TYPE_I4:
8436         case MONO_TYPE_U4:
8437         case MONO_TYPE_R4:
8438                 return 4;
8439         case MONO_TYPE_I:
8440         case MONO_TYPE_U:
8441         case MONO_TYPE_PTR:
8442         case MONO_TYPE_CLASS:
8443         case MONO_TYPE_STRING:
8444         case MONO_TYPE_OBJECT:
8445         case MONO_TYPE_SZARRAY:
8446         case MONO_TYPE_ARRAY: 
8447                 return sizeof (gpointer);
8448         case MONO_TYPE_I8:
8449         case MONO_TYPE_U8:
8450         case MONO_TYPE_R8:
8451                 return 8;
8452         case MONO_TYPE_VALUETYPE:
8453                 if (type->data.klass->enumtype) {
8454                         type = mono_class_enum_basetype (type->data.klass);
8455                         klass = klass->element_class;
8456                         goto handle_enum;
8457                 }
8458                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8459         case MONO_TYPE_GENERICINST:
8460                 type = &type->data.generic_class->container_class->byval_arg;
8461                 goto handle_enum;
8462         case MONO_TYPE_VAR:
8463         case MONO_TYPE_MVAR: {
8464                 int align;
8465
8466                 return mono_type_size (type, &align);
8467         }
8468         case MONO_TYPE_VOID:
8469                 return 0;
8470                 
8471         default:
8472                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8473         }
8474         return -1;
8475 }
8476
8477 /**
8478  * mono_array_element_size:
8479  * @ac: pointer to a #MonoArrayClass
8480  *
8481  * Returns: the size of single array element.
8482  */
8483 gint32
8484 mono_array_element_size (MonoClass *ac)
8485 {
8486         g_assert (ac->rank);
8487         return ac->sizes.element_size;
8488 }
8489
8490 gpointer
8491 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8492               MonoGenericContext *context)
8493 {
8494         MonoError error;
8495         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8496         g_assert (mono_error_ok (&error));
8497         return res;
8498 }
8499
8500 gpointer
8501 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8502               MonoGenericContext *context, MonoError *error)
8503 {
8504         mono_error_init (error);
8505
8506         if (image_is_dynamic (image)) {
8507                 MonoClass *tmp_handle_class;
8508                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8509
8510                 g_assert (tmp_handle_class);
8511                 if (handle_class)
8512                         *handle_class = tmp_handle_class;
8513
8514                 if (tmp_handle_class == mono_defaults.typehandle_class)
8515                         return &((MonoClass*)obj)->byval_arg;
8516                 else
8517                         return obj;
8518         }
8519
8520         switch (token & 0xff000000) {
8521         case MONO_TOKEN_TYPE_DEF:
8522         case MONO_TOKEN_TYPE_REF:
8523         case MONO_TOKEN_TYPE_SPEC: {
8524                 MonoType *type;
8525                 if (handle_class)
8526                         *handle_class = mono_defaults.typehandle_class;
8527                 type = mono_type_get_checked (image, token, context, error);
8528                 if (!type)
8529                         return NULL;
8530
8531                 mono_class_init (mono_class_from_mono_type (type));
8532                 /* We return a MonoType* as handle */
8533                 return type;
8534         }
8535         case MONO_TOKEN_FIELD_DEF: {
8536                 MonoClass *class;
8537                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8538                 if (!type) {
8539                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8540                         return NULL;
8541                 }
8542                 if (handle_class)
8543                         *handle_class = mono_defaults.fieldhandle_class;
8544                 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8545                 if (!class)
8546                         return NULL;
8547
8548                 mono_class_init (class);
8549                 return mono_class_get_field (class, token);
8550         }
8551         case MONO_TOKEN_METHOD_DEF:
8552         case MONO_TOKEN_METHOD_SPEC: {
8553                 MonoMethod *meth;
8554                 meth = mono_get_method_checked (image, token, NULL, context, error);
8555                 if (handle_class)
8556                         *handle_class = mono_defaults.methodhandle_class;
8557                 if (!meth)
8558                         return NULL;
8559
8560                 return meth;
8561         }
8562         case MONO_TOKEN_MEMBER_REF: {
8563                 guint32 cols [MONO_MEMBERREF_SIZE];
8564                 const char *sig;
8565                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8566                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8567                 mono_metadata_decode_blob_size (sig, &sig);
8568                 if (*sig == 0x6) { /* it's a field */
8569                         MonoClass *klass;
8570                         MonoClassField *field;
8571                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8572                         if (handle_class)
8573                                 *handle_class = mono_defaults.fieldhandle_class;
8574                         return field;
8575                 } else {
8576                         MonoMethod *meth;
8577                         meth = mono_get_method_checked (image, token, NULL, context, error);
8578                         if (handle_class)
8579                                 *handle_class = mono_defaults.methodhandle_class;
8580                         return meth;
8581                 }
8582         }
8583         default:
8584                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8585         }
8586         return NULL;
8587 }
8588
8589 /**
8590  * This function might need to call runtime functions so it can't be part
8591  * of the metadata library.
8592  */
8593 static MonoLookupDynamicToken lookup_dynamic = NULL;
8594
8595 void
8596 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8597 {
8598         lookup_dynamic = func;
8599 }
8600
8601 gpointer
8602 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8603 {
8604         MonoClass *handle_class;
8605
8606         return lookup_dynamic (image, token, TRUE, &handle_class, context);
8607 }
8608
8609 gpointer
8610 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8611 {
8612         return lookup_dynamic (image, token, valid_token, handle_class, context);
8613 }
8614
8615 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8616
8617 void
8618 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8619 {
8620         get_cached_class_info = func;
8621 }
8622
8623 static gboolean
8624 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8625 {
8626         if (!get_cached_class_info)
8627                 return FALSE;
8628         else
8629                 return get_cached_class_info (klass, res);
8630 }
8631
8632 void
8633 mono_install_get_class_from_name (MonoGetClassFromName func)
8634 {
8635         get_class_from_name = func;
8636 }
8637
8638 MonoImage*
8639 mono_class_get_image (MonoClass *klass)
8640 {
8641         return klass->image;
8642 }
8643
8644 /**
8645  * mono_class_get_element_class:
8646  * @klass: the MonoClass to act on
8647  *
8648  * Returns: the element class of an array or an enumeration.
8649  */
8650 MonoClass*
8651 mono_class_get_element_class (MonoClass *klass)
8652 {
8653         return klass->element_class;
8654 }
8655
8656 /**
8657  * mono_class_is_valuetype:
8658  * @klass: the MonoClass to act on
8659  *
8660  * Returns: true if the MonoClass represents a ValueType.
8661  */
8662 gboolean
8663 mono_class_is_valuetype (MonoClass *klass)
8664 {
8665         return klass->valuetype;
8666 }
8667
8668 /**
8669  * mono_class_is_enum:
8670  * @klass: the MonoClass to act on
8671  *
8672  * Returns: true if the MonoClass represents an enumeration.
8673  */
8674 gboolean
8675 mono_class_is_enum (MonoClass *klass)
8676 {
8677         return klass->enumtype;
8678 }
8679
8680 /**
8681  * mono_class_enum_basetype:
8682  * @klass: the MonoClass to act on
8683  *
8684  * Returns: the underlying type representation for an enumeration.
8685  */
8686 MonoType*
8687 mono_class_enum_basetype (MonoClass *klass)
8688 {
8689         if (klass->element_class == klass)
8690                 /* SRE or broken types */
8691                 return NULL;
8692         else
8693                 return &klass->element_class->byval_arg;
8694 }
8695
8696 /**
8697  * mono_class_get_parent
8698  * @klass: the MonoClass to act on
8699  *
8700  * Returns: the parent class for this class.
8701  */
8702 MonoClass*
8703 mono_class_get_parent (MonoClass *klass)
8704 {
8705         return klass->parent;
8706 }
8707
8708 /**
8709  * mono_class_get_nesting_type;
8710  * @klass: the MonoClass to act on
8711  *
8712  * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8713  */
8714 MonoClass*
8715 mono_class_get_nesting_type (MonoClass *klass)
8716 {
8717         return klass->nested_in;
8718 }
8719
8720 /**
8721  * mono_class_get_rank:
8722  * @klass: the MonoClass to act on
8723  *
8724  * Returns: the rank for the array (the number of dimensions).
8725  */
8726 int
8727 mono_class_get_rank (MonoClass *klass)
8728 {
8729         return klass->rank;
8730 }
8731
8732 /**
8733  * mono_class_get_flags:
8734  * @klass: the MonoClass to act on
8735  *
8736  * The type flags from the TypeDef table from the metadata.
8737  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8738  * different values.
8739  *
8740  * Returns: the flags from the TypeDef table.
8741  */
8742 guint32
8743 mono_class_get_flags (MonoClass *klass)
8744 {
8745         return klass->flags;
8746 }
8747
8748 /**
8749  * mono_class_get_name
8750  * @klass: the MonoClass to act on
8751  *
8752  * Returns: the name of the class.
8753  */
8754 const char*
8755 mono_class_get_name (MonoClass *klass)
8756 {
8757         return klass->name;
8758 }
8759
8760 /**
8761  * mono_class_get_namespace:
8762  * @klass: the MonoClass to act on
8763  *
8764  * Returns: the namespace of the class.
8765  */
8766 const char*
8767 mono_class_get_namespace (MonoClass *klass)
8768 {
8769         return klass->name_space;
8770 }
8771
8772 /**
8773  * mono_class_get_type:
8774  * @klass: the MonoClass to act on
8775  *
8776  * This method returns the internal Type representation for the class.
8777  *
8778  * Returns: the MonoType from the class.
8779  */
8780 MonoType*
8781 mono_class_get_type (MonoClass *klass)
8782 {
8783         return &klass->byval_arg;
8784 }
8785
8786 /**
8787  * mono_class_get_type_token
8788  * @klass: the MonoClass to act on
8789  *
8790  * This method returns type token for the class.
8791  *
8792  * Returns: the type token for the class.
8793  */
8794 guint32
8795 mono_class_get_type_token (MonoClass *klass)
8796 {
8797   return klass->type_token;
8798 }
8799
8800 /**
8801  * mono_class_get_byref_type:
8802  * @klass: the MonoClass to act on
8803  *
8804  * 
8805  */
8806 MonoType*
8807 mono_class_get_byref_type (MonoClass *klass)
8808 {
8809         return &klass->this_arg;
8810 }
8811
8812 /**
8813  * mono_class_num_fields:
8814  * @klass: the MonoClass to act on
8815  *
8816  * Returns: the number of static and instance fields in the class.
8817  */
8818 int
8819 mono_class_num_fields (MonoClass *klass)
8820 {
8821         return klass->field.count;
8822 }
8823
8824 /**
8825  * mono_class_num_methods:
8826  * @klass: the MonoClass to act on
8827  *
8828  * Returns: the number of methods in the class.
8829  */
8830 int
8831 mono_class_num_methods (MonoClass *klass)
8832 {
8833         return klass->method.count;
8834 }
8835
8836 /**
8837  * mono_class_num_properties
8838  * @klass: the MonoClass to act on
8839  *
8840  * Returns: the number of properties in the class.
8841  */
8842 int
8843 mono_class_num_properties (MonoClass *klass)
8844 {
8845         mono_class_setup_properties (klass);
8846
8847         return klass->ext->property.count;
8848 }
8849
8850 /**
8851  * mono_class_num_events:
8852  * @klass: the MonoClass to act on
8853  *
8854  * Returns: the number of events in the class.
8855  */
8856 int
8857 mono_class_num_events (MonoClass *klass)
8858 {
8859         mono_class_setup_events (klass);
8860
8861         return klass->ext->event.count;
8862 }
8863
8864 /**
8865  * mono_class_get_fields:
8866  * @klass: the MonoClass to act on
8867  *
8868  * This routine is an iterator routine for retrieving the fields in a class.
8869  *
8870  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8871  * iterate over all of the elements.  When no more values are
8872  * available, the return value is NULL.
8873  *
8874  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8875  */
8876 MonoClassField*
8877 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8878 {
8879         MonoClassField* field;
8880         if (!iter)
8881                 return NULL;
8882         if (!*iter) {
8883                 mono_class_setup_fields_locking (klass);
8884                 if (klass->exception_type)
8885                         return NULL;
8886                 /* start from the first */
8887                 if (klass->field.count) {
8888                         return *iter = &klass->fields [0];
8889                 } else {
8890                         /* no fields */
8891                         return NULL;
8892                 }
8893         }
8894         field = *iter;
8895         field++;
8896         if (field < &klass->fields [klass->field.count]) {
8897                 return *iter = field;
8898         }
8899         return NULL;
8900 }
8901
8902 /**
8903  * mono_class_get_methods
8904  * @klass: the MonoClass to act on
8905  *
8906  * This routine is an iterator routine for retrieving the fields in a class.
8907  *
8908  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8909  * iterate over all of the elements.  When no more values are
8910  * available, the return value is NULL.
8911  *
8912  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8913  */
8914 MonoMethod*
8915 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8916 {
8917         MonoMethod** method;
8918         if (!iter)
8919                 return NULL;
8920         if (!*iter) {
8921                 mono_class_setup_methods (klass);
8922
8923                 /*
8924                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8925                  * FIXME we should better report this error to the caller
8926                  */
8927                 if (!klass->methods)
8928                         return NULL;
8929                 /* start from the first */
8930                 if (klass->method.count) {
8931                         *iter = &klass->methods [0];
8932                         return klass->methods [0];
8933                 } else {
8934                         /* no method */
8935                         return NULL;
8936                 }
8937         }
8938         method = *iter;
8939         method++;
8940         if (method < &klass->methods [klass->method.count]) {
8941                 *iter = method;
8942                 return *method;
8943         }
8944         return NULL;
8945 }
8946
8947 /*
8948  * mono_class_get_virtual_methods:
8949  *
8950  *   Iterate over the virtual methods of KLASS.
8951  *
8952  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8953  */
8954 static MonoMethod*
8955 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8956 {
8957         MonoMethod** method;
8958         if (!iter)
8959                 return NULL;
8960         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8961                 if (!*iter) {
8962                         mono_class_setup_methods (klass);
8963                         /*
8964                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8965                          * FIXME we should better report this error to the caller
8966                          */
8967                         if (!klass->methods)
8968                                 return NULL;
8969                         /* start from the first */
8970                         method = &klass->methods [0];
8971                 } else {
8972                         method = *iter;
8973                         method++;
8974                 }
8975                 while (method < &klass->methods [klass->method.count]) {
8976                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8977                                 break;
8978                         method ++;
8979                 }
8980                 if (method < &klass->methods [klass->method.count]) {
8981                         *iter = method;
8982                         return *method;
8983                 } else {
8984                         return NULL;
8985                 }
8986         } else {
8987                 /* Search directly in metadata to avoid calling setup_methods () */
8988                 MonoMethod *res = NULL;
8989                 int i, start_index;
8990
8991                 if (!*iter) {
8992                         start_index = 0;
8993                 } else {
8994                         start_index = GPOINTER_TO_UINT (*iter);
8995                 }
8996
8997                 for (i = start_index; i < klass->method.count; ++i) {
8998                         guint32 flags;
8999
9000                         /* class->method.first points into the methodptr table */
9001                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9002
9003                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9004                                 break;
9005                 }
9006
9007                 if (i < klass->method.count) {
9008                         MonoError error;
9009                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9010                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9011
9012                         /* Add 1 here so the if (*iter) check fails */
9013                         *iter = GUINT_TO_POINTER (i + 1);
9014                         return res;
9015                 } else {
9016                         return NULL;
9017                 }
9018         }
9019 }
9020
9021 /**
9022  * mono_class_get_properties:
9023  * @klass: the MonoClass to act on
9024  *
9025  * This routine is an iterator routine for retrieving the properties in a class.
9026  *
9027  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9028  * iterate over all of the elements.  When no more values are
9029  * available, the return value is NULL.
9030  *
9031  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9032  */
9033 MonoProperty*
9034 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9035 {
9036         MonoProperty* property;
9037         if (!iter)
9038                 return NULL;
9039         if (!*iter) {
9040                 mono_class_setup_properties (klass);
9041                 /* start from the first */
9042                 if (klass->ext->property.count) {
9043                         return *iter = &klass->ext->properties [0];
9044                 } else {
9045                         /* no fields */
9046                         return NULL;
9047                 }
9048         }
9049         property = *iter;
9050         property++;
9051         if (property < &klass->ext->properties [klass->ext->property.count]) {
9052                 return *iter = property;
9053         }
9054         return NULL;
9055 }
9056
9057 /**
9058  * mono_class_get_events:
9059  * @klass: the MonoClass to act on
9060  *
9061  * This routine is an iterator routine for retrieving the properties in a class.
9062  *
9063  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9064  * iterate over all of the elements.  When no more values are
9065  * available, the return value is NULL.
9066  *
9067  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9068  */
9069 MonoEvent*
9070 mono_class_get_events (MonoClass* klass, gpointer *iter)
9071 {
9072         MonoEvent* event;
9073         if (!iter)
9074                 return NULL;
9075         if (!*iter) {
9076                 mono_class_setup_events (klass);
9077                 /* start from the first */
9078                 if (klass->ext->event.count) {
9079                         return *iter = &klass->ext->events [0];
9080                 } else {
9081                         /* no fields */
9082                         return NULL;
9083                 }
9084         }
9085         event = *iter;
9086         event++;
9087         if (event < &klass->ext->events [klass->ext->event.count]) {
9088                 return *iter = event;
9089         }
9090         return NULL;
9091 }
9092
9093 /**
9094  * mono_class_get_interfaces
9095  * @klass: the MonoClass to act on
9096  *
9097  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9098  *
9099  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9100  * iterate over all of the elements.  When no more values are
9101  * available, the return value is NULL.
9102  *
9103  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9104  */
9105 MonoClass*
9106 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9107 {
9108         MonoError error;
9109         MonoClass** iface;
9110         if (!iter)
9111                 return NULL;
9112         if (!*iter) {
9113                 if (!klass->inited)
9114                         mono_class_init (klass);
9115                 if (!klass->interfaces_inited) {
9116                         mono_class_setup_interfaces (klass, &error);
9117                         if (!mono_error_ok (&error)) {
9118                                 mono_error_cleanup (&error);
9119                                 return NULL;
9120                         }
9121                 }
9122                 /* start from the first */
9123                 if (klass->interface_count) {
9124                         *iter = &klass->interfaces [0];
9125                         return klass->interfaces [0];
9126                 } else {
9127                         /* no interface */
9128                         return NULL;
9129                 }
9130         }
9131         iface = *iter;
9132         iface++;
9133         if (iface < &klass->interfaces [klass->interface_count]) {
9134                 *iter = iface;
9135                 return *iface;
9136         }
9137         return NULL;
9138 }
9139
9140 static void
9141 setup_nested_types (MonoClass *klass)
9142 {
9143         MonoError error;
9144         GList *classes, *nested_classes, *l;
9145         int i;
9146
9147         if (klass->nested_classes_inited)
9148                 return;
9149
9150         if (!klass->type_token)
9151                 klass->nested_classes_inited = TRUE;
9152
9153         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9154         classes = NULL;
9155         while (i) {
9156                 MonoClass* nclass;
9157                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9158                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9159                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9160                 if (!mono_error_ok (&error)) {
9161                         /*FIXME don't swallow the error message*/
9162                         mono_error_cleanup (&error);
9163
9164                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9165                         continue;
9166                 }
9167
9168                 classes = g_list_prepend (classes, nclass);
9169
9170                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9171         }
9172
9173         mono_class_alloc_ext (klass);
9174
9175         nested_classes = NULL;
9176         for (l = classes; l; l = l->next)
9177                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9178         g_list_free (classes);
9179
9180         mono_image_lock (klass->image);
9181
9182         mono_memory_barrier ();
9183         if (!klass->nested_classes_inited) {
9184                 klass->ext->nested_classes = nested_classes;
9185                 mono_memory_barrier ();
9186                 klass->nested_classes_inited = TRUE;
9187         }
9188
9189         mono_image_unlock (klass->image);
9190 }
9191
9192 /**
9193  * mono_class_get_nested_types
9194  * @klass: the MonoClass to act on
9195  *
9196  * This routine is an iterator routine for retrieving the nested types of a class.
9197  * This works only if @klass is non-generic, or a generic type definition.
9198  *
9199  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9200  * iterate over all of the elements.  When no more values are
9201  * available, the return value is NULL.
9202  *
9203  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9204  */
9205 MonoClass*
9206 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9207 {
9208         GList *item;
9209
9210         if (!iter)
9211                 return NULL;
9212         if (!klass->nested_classes_inited)
9213                 setup_nested_types (klass);
9214
9215         if (!*iter) {
9216                 /* start from the first */
9217                 if (klass->ext && klass->ext->nested_classes) {
9218                         *iter = klass->ext->nested_classes;
9219                         return klass->ext->nested_classes->data;
9220                 } else {
9221                         /* no nested types */
9222                         return NULL;
9223                 }
9224         }
9225         item = *iter;
9226         item = item->next;
9227         if (item) {
9228                 *iter = item;
9229                 return item->data;
9230         }
9231         return NULL;
9232 }
9233
9234
9235 /**
9236  * mono_class_is_delegate
9237  * @klass: the MonoClass to act on
9238  *
9239  * Returns: true if the MonoClass represents a System.Delegate.
9240  */
9241 mono_bool
9242 mono_class_is_delegate (MonoClass *klass)
9243 {
9244         return klass->delegate;
9245 }
9246
9247 /**
9248  * mono_class_implements_interface
9249  * @klass: The MonoClass to act on
9250  * @interface: The interface to check if @klass implements.
9251  *
9252  * Returns: true if @klass implements @interface.
9253  */
9254 mono_bool
9255 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9256 {
9257         return mono_class_is_assignable_from (iface, klass);
9258 }
9259
9260 /**
9261  * mono_field_get_name:
9262  * @field: the MonoClassField to act on
9263  *
9264  * Returns: the name of the field.
9265  */
9266 const char*
9267 mono_field_get_name (MonoClassField *field)
9268 {
9269         return field->name;
9270 }
9271
9272 /**
9273  * mono_field_get_type:
9274  * @field: the MonoClassField to act on
9275  *
9276  * Returns: MonoType of the field.
9277  */
9278 MonoType*
9279 mono_field_get_type (MonoClassField *field)
9280 {
9281         MonoError error;
9282         MonoType *type = mono_field_get_type_checked (field, &error);
9283         if (!mono_error_ok (&error)) {
9284                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9285                 mono_error_cleanup (&error);
9286         }
9287         return type;
9288 }
9289
9290
9291 /**
9292  * mono_field_get_type_checked:
9293  * @field: the MonoClassField to act on
9294  * @error: used to return any erro found while retrieving @field type
9295  *
9296  * Returns: MonoType of the field.
9297  */
9298 MonoType*
9299 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9300 {
9301         mono_error_init (error);
9302         if (!field->type)
9303                 mono_field_resolve_type (field, error);
9304         return field->type;
9305 }
9306
9307 /**
9308  * mono_field_get_parent:
9309  * @field: the MonoClassField to act on
9310  *
9311  * Returns: MonoClass where the field was defined.
9312  */
9313 MonoClass*
9314 mono_field_get_parent (MonoClassField *field)
9315 {
9316         return field->parent;
9317 }
9318
9319 /**
9320  * mono_field_get_flags;
9321  * @field: the MonoClassField to act on
9322  *
9323  * The metadata flags for a field are encoded using the
9324  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9325  *
9326  * Returns: the flags for the field.
9327  */
9328 guint32
9329 mono_field_get_flags (MonoClassField *field)
9330 {
9331         if (!field->type)
9332                 return mono_field_resolve_flags (field);
9333         return field->type->attrs;
9334 }
9335
9336 /**
9337  * mono_field_get_offset;
9338  * @field: the MonoClassField to act on
9339  *
9340  * Returns: the field offset.
9341  */
9342 guint32
9343 mono_field_get_offset (MonoClassField *field)
9344 {
9345         return field->offset;
9346 }
9347
9348 static const char *
9349 mono_field_get_rva (MonoClassField *field)
9350 {
9351         guint32 rva;
9352         int field_index;
9353         MonoClass *klass = field->parent;
9354         MonoFieldDefaultValue *field_def_values;
9355
9356         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9357
9358         if (!klass->ext || !klass->ext->field_def_values) {
9359                 mono_class_alloc_ext (klass);
9360
9361                 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9362
9363                 mono_image_lock (klass->image);
9364                 if (!klass->ext->field_def_values)
9365                         klass->ext->field_def_values = field_def_values;
9366                 mono_image_unlock (klass->image);
9367         }
9368
9369         field_index = mono_field_get_index (field);
9370                 
9371         if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9372                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9373                 if (!rva)
9374                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9375                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9376         }
9377
9378         return klass->ext->field_def_values [field_index].data;
9379 }
9380
9381 /**
9382  * mono_field_get_data;
9383  * @field: the MonoClassField to act on
9384  *
9385  * Returns: pointer to the metadata constant value or to the field
9386  * data if it has an RVA flag.
9387  */
9388 const char *
9389 mono_field_get_data (MonoClassField *field)
9390 {
9391         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9392                 MonoTypeEnum def_type;
9393
9394                 return mono_class_get_field_default_value (field, &def_type);
9395         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9396                 return mono_field_get_rva (field);
9397         } else {
9398                 return NULL;
9399         }
9400 }
9401
9402 /**
9403  * mono_property_get_name: 
9404  * @prop: the MonoProperty to act on
9405  *
9406  * Returns: the name of the property
9407  */
9408 const char*
9409 mono_property_get_name (MonoProperty *prop)
9410 {
9411         return prop->name;
9412 }
9413
9414 /**
9415  * mono_property_get_set_method
9416  * @prop: the MonoProperty to act on.
9417  *
9418  * Returns: the setter method of the property (A MonoMethod)
9419  */
9420 MonoMethod*
9421 mono_property_get_set_method (MonoProperty *prop)
9422 {
9423         return prop->set;
9424 }
9425
9426 /**
9427  * mono_property_get_get_method
9428  * @prop: the MonoProperty to act on.
9429  *
9430  * Returns: the setter method of the property (A MonoMethod)
9431  */
9432 MonoMethod*
9433 mono_property_get_get_method (MonoProperty *prop)
9434 {
9435         return prop->get;
9436 }
9437
9438 /**
9439  * mono_property_get_parent:
9440  * @prop: the MonoProperty to act on.
9441  *
9442  * Returns: the MonoClass where the property was defined.
9443  */
9444 MonoClass*
9445 mono_property_get_parent (MonoProperty *prop)
9446 {
9447         return prop->parent;
9448 }
9449
9450 /**
9451  * mono_property_get_flags:
9452  * @prop: the MonoProperty to act on.
9453  *
9454  * The metadata flags for a property are encoded using the
9455  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9456  *
9457  * Returns: the flags for the property.
9458  */
9459 guint32
9460 mono_property_get_flags (MonoProperty *prop)
9461 {
9462         return prop->attrs;
9463 }
9464
9465 /**
9466  * mono_event_get_name:
9467  * @event: the MonoEvent to act on
9468  *
9469  * Returns: the name of the event.
9470  */
9471 const char*
9472 mono_event_get_name (MonoEvent *event)
9473 {
9474         return event->name;
9475 }
9476
9477 /**
9478  * mono_event_get_add_method:
9479  * @event: The MonoEvent to act on.
9480  *
9481  * Returns: the @add' method for the event (a MonoMethod).
9482  */
9483 MonoMethod*
9484 mono_event_get_add_method (MonoEvent *event)
9485 {
9486         return event->add;
9487 }
9488
9489 /**
9490  * mono_event_get_remove_method:
9491  * @event: The MonoEvent to act on.
9492  *
9493  * Returns: the @remove method for the event (a MonoMethod).
9494  */
9495 MonoMethod*
9496 mono_event_get_remove_method (MonoEvent *event)
9497 {
9498         return event->remove;
9499 }
9500
9501 /**
9502  * mono_event_get_raise_method:
9503  * @event: The MonoEvent to act on.
9504  *
9505  * Returns: the @raise method for the event (a MonoMethod).
9506  */
9507 MonoMethod*
9508 mono_event_get_raise_method (MonoEvent *event)
9509 {
9510         return event->raise;
9511 }
9512
9513 /**
9514  * mono_event_get_parent:
9515  * @event: the MonoEvent to act on.
9516  *
9517  * Returns: the MonoClass where the event is defined.
9518  */
9519 MonoClass*
9520 mono_event_get_parent (MonoEvent *event)
9521 {
9522         return event->parent;
9523 }
9524
9525 /**
9526  * mono_event_get_flags
9527  * @event: the MonoEvent to act on.
9528  *
9529  * The metadata flags for an event are encoded using the
9530  * EVENT_* constants.  See the tabledefs.h file for details.
9531  *
9532  * Returns: the flags for the event.
9533  */
9534 guint32
9535 mono_event_get_flags (MonoEvent *event)
9536 {
9537         return event->attrs;
9538 }
9539
9540 /**
9541  * mono_class_get_method_from_name:
9542  * @klass: where to look for the method
9543  * @name: name of the method
9544  * @param_count: number of parameters. -1 for any number.
9545  *
9546  * Obtains a MonoMethod with a given name and number of parameters.
9547  * It only works if there are no multiple signatures for any given method name.
9548  */
9549 MonoMethod *
9550 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9551 {
9552         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9553 }
9554
9555 static MonoMethod*
9556 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9557 {
9558         MonoMethod *res = NULL;
9559         int i;
9560
9561         /* Search directly in the metadata to avoid calling setup_methods () */
9562         for (i = 0; i < klass->method.count; ++i) {
9563                 MonoError error;
9564                 guint32 cols [MONO_METHOD_SIZE];
9565                 MonoMethod *method;
9566                 MonoMethodSignature *sig;
9567
9568                 /* class->method.first points into the methodptr table */
9569                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9570
9571                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9572                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9573                         if (!method) {
9574                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9575                                 continue;
9576                         }
9577                         if (param_count == -1) {
9578                                 res = method;
9579                                 break;
9580                         }
9581                         sig = mono_method_signature_checked (method, &error);
9582                         if (!sig) {
9583                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9584                                 continue;
9585                         }
9586                         if (sig->param_count == param_count) {
9587                                 res = method;
9588                                 break;
9589                         }
9590                 }
9591         }
9592
9593         return res;
9594 }
9595
9596 /**
9597  * mono_class_get_method_from_name_flags:
9598  * @klass: where to look for the method
9599  * @name_space: name of the method
9600  * @param_count: number of parameters. -1 for any number.
9601  * @flags: flags which must be set in the method
9602  *
9603  * Obtains a MonoMethod with a given name and number of parameters.
9604  * It only works if there are no multiple signatures for any given method name.
9605  */
9606 MonoMethod *
9607 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9608 {
9609         MonoMethod *res = NULL;
9610         int i;
9611
9612         mono_class_init (klass);
9613
9614         if (klass->generic_class && !klass->methods) {
9615                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9616                 if (res) {
9617                         MonoError error;
9618                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9619                         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9620                 }
9621                 return res;
9622         }
9623
9624         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9625                 mono_class_setup_methods (klass);
9626                 /*
9627                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9628                 See mono/tests/array_load_exception.il
9629                 FIXME we should better report this error to the caller
9630                  */
9631                 if (!klass->methods)
9632                         return NULL;
9633                 for (i = 0; i < klass->method.count; ++i) {
9634                         MonoMethod *method = klass->methods [i];
9635
9636                         if (method->name[0] == name [0] && 
9637                                 !strcmp (name, method->name) &&
9638                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9639                                 ((method->flags & flags) == flags)) {
9640                                 res = method;
9641                                 break;
9642                         }
9643                 }
9644         }
9645         else {
9646             res = find_method_in_metadata (klass, name, param_count, flags);
9647         }
9648
9649         return res;
9650 }
9651
9652 /**
9653  * mono_class_set_failure:
9654  * @klass: class in which the failure was detected
9655  * @ex_type: the kind of exception/error to be thrown (later)
9656  * @ex_data: exception data (specific to each type of exception/error)
9657  *
9658  * Keep a detected failure informations in the class for later processing.
9659  * Note that only the first failure is kept.
9660  *
9661  * LOCKING: Acquires the loader lock.
9662  */
9663 gboolean
9664 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9665 {
9666         if (klass->exception_type)
9667                 return FALSE;
9668
9669         mono_loader_lock ();
9670         klass->exception_type = ex_type;
9671         if (ex_data)
9672                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9673         mono_loader_unlock ();
9674
9675         return TRUE;
9676 }
9677
9678 /*
9679  * mono_class_get_exception_data:
9680  *
9681  *   Return the exception_data property of KLASS.
9682  *
9683  * LOCKING: Acquires the loader lock.
9684  */
9685 gpointer
9686 mono_class_get_exception_data (MonoClass *klass)
9687 {
9688         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9689 }
9690
9691 /**
9692  * mono_classes_init:
9693  *
9694  * Initialize the resources used by this module.
9695  */
9696 void
9697 mono_classes_init (void)
9698 {
9699         mono_mutex_init (&classes_mutex);
9700
9701         mono_counters_register ("Inflated methods size",
9702                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9703         mono_counters_register ("Inflated classes",
9704                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9705         mono_counters_register ("Inflated classes size",
9706                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9707         mono_counters_register ("MonoClass size",
9708                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9709         mono_counters_register ("MonoClassExt size",
9710                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9711 }
9712
9713 /**
9714  * mono_classes_cleanup:
9715  *
9716  * Free the resources used by this module.
9717  */
9718 void
9719 mono_classes_cleanup (void)
9720 {
9721         if (global_interface_bitset)
9722                 mono_bitset_free (global_interface_bitset);
9723         global_interface_bitset = NULL;
9724         mono_mutex_destroy (&classes_mutex);
9725 }
9726
9727 /**
9728  * mono_class_get_exception_for_failure:
9729  * @klass: class in which the failure was detected
9730  *
9731  * Return a constructed MonoException than the caller can then throw
9732  * using mono_raise_exception - or NULL if no failure is present (or
9733  * doesn't result in an exception).
9734  */
9735 MonoException*
9736 mono_class_get_exception_for_failure (MonoClass *klass)
9737 {
9738         gpointer exception_data = mono_class_get_exception_data (klass);
9739
9740         switch (klass->exception_type) {
9741 #ifndef DISABLE_SECURITY
9742         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9743                 MonoDomain *domain = mono_domain_get ();
9744                 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9745                 MonoMethod *method = exception_data;
9746                 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9747                 MonoObject *exc = NULL;
9748                 gpointer args [4];
9749
9750                 args [0] = &error;
9751                 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9752                 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9753                 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9754
9755                 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9756                 return (MonoException*) exc;
9757         }
9758 #endif
9759         case MONO_EXCEPTION_TYPE_LOAD: {
9760                 MonoString *name;
9761                 MonoException *ex;
9762                 char *str = mono_type_get_full_name (klass);
9763                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9764                 name = mono_string_new (mono_domain_get (), str);
9765                 g_free (str);
9766                 ex = mono_get_exception_type_load (name, astr);
9767                 g_free (astr);
9768                 return ex;
9769         }
9770         case MONO_EXCEPTION_MISSING_METHOD: {
9771                 char *class_name = exception_data;
9772                 char *assembly_name = class_name + strlen (class_name) + 1;
9773
9774                 return mono_get_exception_missing_method (class_name, assembly_name);
9775         }
9776         case MONO_EXCEPTION_MISSING_FIELD: {
9777                 char *class_name = exception_data;
9778                 char *member_name = class_name + strlen (class_name) + 1;
9779
9780                 return mono_get_exception_missing_field (class_name, member_name);
9781         }
9782         case MONO_EXCEPTION_FILE_NOT_FOUND: {
9783                 char *msg_format = exception_data;
9784                 char *assembly_name = msg_format + strlen (msg_format) + 1;
9785                 char *msg = g_strdup_printf (msg_format, assembly_name);
9786                 MonoException *ex;
9787
9788                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9789
9790                 g_free (msg);
9791
9792                 return ex;
9793         }
9794         case MONO_EXCEPTION_BAD_IMAGE: {
9795                 return mono_get_exception_bad_image_format (exception_data);
9796         }
9797         default: {
9798                 MonoLoaderError *error;
9799                 MonoException *ex;
9800                 
9801                 error = mono_loader_get_last_error ();
9802                 if (error != NULL){
9803                         ex = mono_loader_error_prepare_exception (error);
9804                         return ex;
9805                 }
9806                 
9807                 /* TODO - handle other class related failures */
9808                 return NULL;
9809         }
9810         }
9811 }
9812
9813 static gboolean
9814 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9815  {
9816         outer_klass = mono_class_get_generic_type_definition (outer_klass);
9817         inner_klass = mono_class_get_generic_type_definition (inner_klass);
9818         do {
9819                 if (outer_klass == inner_klass)
9820                         return TRUE;
9821                 inner_klass = inner_klass->nested_in;
9822         } while (inner_klass);
9823         return FALSE;
9824 }
9825
9826 MonoClass *
9827 mono_class_get_generic_type_definition (MonoClass *klass)
9828 {
9829         return klass->generic_class ? klass->generic_class->container_class : klass;
9830 }
9831
9832 /*
9833  * Check if @klass is a subtype of @parent ignoring generic instantiations.
9834  * 
9835  * Generic instantiations are ignored for all super types of @klass.
9836  * 
9837  * Visibility checks ignoring generic instantiations.  
9838  */
9839 gboolean
9840 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9841 {
9842         int i;
9843         klass = mono_class_get_generic_type_definition (klass);
9844         parent = mono_class_get_generic_type_definition (parent);
9845         mono_class_setup_supertypes (klass);
9846
9847         for (i = 0; i < klass->idepth; ++i) {
9848                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9849                         return TRUE;
9850         }
9851         return FALSE;
9852 }
9853 /*
9854  * Subtype can only access parent members with family protection if the site object
9855  * is subclass of Subtype. For example:
9856  * class A { protected int x; }
9857  * class B : A {
9858  *      void valid_access () {
9859  *              B b;
9860  *              b.x = 0;
9861  *  }
9862  *  void invalid_access () {
9863  *              A a;
9864  *              a.x = 0;
9865  *  }
9866  * }
9867  * */
9868 static gboolean
9869 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9870 {
9871         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9872                 return FALSE;
9873
9874         if (context_klass == NULL)
9875                 return TRUE;
9876         /*if access_klass is not member_klass context_klass must be type compat*/
9877         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9878                 return FALSE;
9879         return TRUE;
9880 }
9881
9882 static gboolean
9883 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9884 {
9885         GSList *tmp;
9886         if (accessing == accessed)
9887                 return TRUE;
9888         if (!accessed || !accessing)
9889                 return FALSE;
9890
9891         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9892          * anywhere so untrusted friends are not safe to access platform's code internals */
9893         if (mono_security_core_clr_enabled ()) {
9894                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9895                         return FALSE;
9896         }
9897
9898         mono_assembly_load_friends (accessed);
9899         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9900                 MonoAssemblyName *friend = tmp->data;
9901                 /* Be conservative with checks */
9902                 if (!friend->name)
9903                         continue;
9904                 if (strcmp (accessing->aname.name, friend->name))
9905                         continue;
9906                 if (friend->public_key_token [0]) {
9907                         if (!accessing->aname.public_key_token [0])
9908                                 continue;
9909                         if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9910                                 continue;
9911                 }
9912                 return TRUE;
9913         }
9914         return FALSE;
9915 }
9916
9917 /*
9918  * If klass is a generic type or if it is derived from a generic type, return the
9919  * MonoClass of the generic definition
9920  * Returns NULL if not found
9921  */
9922 static MonoClass*
9923 get_generic_definition_class (MonoClass *klass)
9924 {
9925         while (klass) {
9926                 if (klass->generic_class && klass->generic_class->container_class)
9927                         return klass->generic_class->container_class;
9928                 klass = klass->parent;
9929         }
9930         return NULL;
9931 }
9932
9933 static gboolean
9934 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9935 {
9936         int i;
9937         for (i = 0; i < ginst->type_argc; ++i) {
9938                 MonoType *type = ginst->type_argv[i];
9939                 switch (type->type) {
9940                 case MONO_TYPE_SZARRAY:
9941                         if (!can_access_type (access_klass, type->data.klass))
9942                                 return FALSE;
9943                         break;
9944                 case MONO_TYPE_ARRAY:
9945                         if (!can_access_type (access_klass, type->data.array->eklass))
9946                                 return FALSE;
9947                         break;
9948                 case MONO_TYPE_PTR:
9949                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9950                                 return FALSE;
9951                         break;
9952                 case MONO_TYPE_CLASS:
9953                 case MONO_TYPE_VALUETYPE:
9954                 case MONO_TYPE_GENERICINST:
9955                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9956                                 return FALSE;
9957                 default:
9958                         break;
9959                 }
9960         }
9961         return TRUE;
9962 }
9963
9964 static gboolean
9965 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9966 {
9967         int access_level;
9968
9969         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9970                 return TRUE;
9971
9972         if (access_klass->element_class && !access_klass->enumtype)
9973                 access_klass = access_klass->element_class;
9974
9975         if (member_klass->element_class && !member_klass->enumtype)
9976                 member_klass = member_klass->element_class;
9977
9978         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9979
9980         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9981                 return TRUE;
9982
9983         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9984                 return FALSE;
9985
9986         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9987                 return TRUE;
9988
9989         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9990                 return FALSE;
9991
9992         /*Non nested type with nested visibility. We just fail it.*/
9993         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9994                 return FALSE;
9995
9996         switch (access_level) {
9997         case TYPE_ATTRIBUTE_NOT_PUBLIC:
9998                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9999
10000         case TYPE_ATTRIBUTE_PUBLIC:
10001                 return TRUE;
10002
10003         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10004                 return TRUE;
10005
10006         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10007                 return is_nesting_type (member_klass, access_klass);
10008
10009         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10010                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10011
10012         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10013                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10014
10015         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10016                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10017                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10018
10019         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10020                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10021                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10022         }
10023         return FALSE;
10024 }
10025
10026 /* FIXME: check visibility of type, too */
10027 static gboolean
10028 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10029 {
10030         MonoClass *member_generic_def;
10031         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10032                 return TRUE;
10033
10034         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10035                                         access_klass->generic_container) && 
10036                         (member_generic_def = get_generic_definition_class (member_klass))) {
10037                 MonoClass *access_container;
10038
10039                 if (access_klass->generic_container)
10040                         access_container = access_klass;
10041                 else
10042                         access_container = access_klass->generic_class->container_class;
10043
10044                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10045                         return TRUE;
10046         }
10047
10048         /* Partition I 8.5.3.2 */
10049         /* the access level values are the same for fields and methods */
10050         switch (access_level) {
10051         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10052                 /* same compilation unit */
10053                 return access_klass->image == member_klass->image;
10054         case FIELD_ATTRIBUTE_PRIVATE:
10055                 return access_klass == member_klass;
10056         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10057                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10058                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10059                         return TRUE;
10060                 return FALSE;
10061         case FIELD_ATTRIBUTE_ASSEMBLY:
10062                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10063         case FIELD_ATTRIBUTE_FAMILY:
10064                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10065                         return TRUE;
10066                 return FALSE;
10067         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10068                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10069                         return TRUE;
10070                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10071         case FIELD_ATTRIBUTE_PUBLIC:
10072                 return TRUE;
10073         }
10074         return FALSE;
10075 }
10076
10077 gboolean
10078 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10079 {
10080         /* FIXME: check all overlapping fields */
10081         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10082         if (!can) {
10083                 MonoClass *nested = method->klass->nested_in;
10084                 while (nested) {
10085                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10086                         if (can)
10087                                 return TRUE;
10088                         nested = nested->nested_in;
10089                 }
10090         }
10091         return can;
10092 }
10093
10094 gboolean
10095 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10096 {
10097         int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10098         if (!can) {
10099                 MonoClass *nested = method->klass->nested_in;
10100                 while (nested) {
10101                         can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10102                         if (can)
10103                                 return TRUE;
10104                         nested = nested->nested_in;
10105                 }
10106         }
10107         /* 
10108          * FIXME:
10109          * with generics calls to explicit interface implementations can be expressed
10110          * directly: the method is private, but we must allow it. This may be opening
10111          * a hole or the generics code should handle this differently.
10112          * Maybe just ensure the interface type is public.
10113          */
10114         if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10115                 return TRUE;
10116         return can;
10117 }
10118
10119 /*
10120  * mono_method_can_access_method_full:
10121  * @method: The caller method 
10122  * @called: The called method 
10123  * @context_klass: The static type on stack of the owner @called object used
10124  * 
10125  * This function must be used with instance calls, as they have more strict family accessibility.
10126  * It can be used with static methods, but context_klass should be NULL.
10127  * 
10128  * Returns: TRUE if caller have proper visibility and acessibility to @called
10129  */
10130 gboolean
10131 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10132 {
10133         MonoClass *access_class = method->klass;
10134         MonoClass *member_class = called->klass;
10135         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10136         if (!can) {
10137                 MonoClass *nested = access_class->nested_in;
10138                 while (nested) {
10139                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10140                         if (can)
10141                                 break;
10142                         nested = nested->nested_in;
10143                 }
10144         }
10145
10146         if (!can)
10147                 return FALSE;
10148
10149         can = can_access_type (access_class, member_class);
10150         if (!can) {
10151                 MonoClass *nested = access_class->nested_in;
10152                 while (nested) {
10153                         can = can_access_type (nested, member_class);
10154                         if (can)
10155                                 break;
10156                         nested = nested->nested_in;
10157                 }
10158         }
10159
10160         if (!can)
10161                 return FALSE;
10162
10163         if (called->is_inflated) {
10164                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10165                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10166                         return FALSE;
10167         }
10168                 
10169         return TRUE;
10170 }
10171
10172
10173 /*
10174  * mono_method_can_access_field_full:
10175  * @method: The caller method 
10176  * @field: The accessed field
10177  * @context_klass: The static type on stack of the owner @field object used
10178  * 
10179  * This function must be used with instance fields, as they have more strict family accessibility.
10180  * It can be used with static fields, but context_klass should be NULL.
10181  * 
10182  * Returns: TRUE if caller have proper visibility and acessibility to @field
10183  */
10184 gboolean
10185 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10186 {
10187         MonoClass *access_class = method->klass;
10188         MonoClass *member_class = field->parent;
10189         /* FIXME: check all overlapping fields */
10190         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10191         if (!can) {
10192                 MonoClass *nested = access_class->nested_in;
10193                 while (nested) {
10194                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10195                         if (can)
10196                                 break;
10197                         nested = nested->nested_in;
10198                 }
10199         }
10200
10201         if (!can)
10202                 return FALSE;
10203
10204         can = can_access_type (access_class, member_class);
10205         if (!can) {
10206                 MonoClass *nested = access_class->nested_in;
10207                 while (nested) {
10208                         can = can_access_type (nested, member_class);
10209                         if (can)
10210                                 break;
10211                         nested = nested->nested_in;
10212                 }
10213         }
10214
10215         if (!can)
10216                 return FALSE;
10217         return TRUE;
10218 }
10219
10220 /*
10221  * mono_class_can_access_class:
10222  * @source_class: The source class 
10223  * @target_class: The accessed class
10224  * 
10225  * This function returns is @target_class is visible to @source_class
10226  * 
10227  * Returns: TRUE if source have proper visibility and acessibility to target
10228  */
10229 gboolean
10230 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10231 {
10232         return can_access_type (source_class, target_class);
10233 }
10234
10235 /**
10236  * mono_type_is_valid_enum_basetype:
10237  * @type: The MonoType to check
10238  *
10239  * Returns: TRUE if the type can be used as the basetype of an enum
10240  */
10241 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10242         switch (type->type) {
10243         case MONO_TYPE_I1:
10244         case MONO_TYPE_U1:
10245         case MONO_TYPE_BOOLEAN:
10246         case MONO_TYPE_I2:
10247         case MONO_TYPE_U2:
10248         case MONO_TYPE_CHAR:
10249         case MONO_TYPE_I4:
10250         case MONO_TYPE_U4:
10251         case MONO_TYPE_I8:
10252         case MONO_TYPE_U8:
10253         case MONO_TYPE_I:
10254         case MONO_TYPE_U:
10255                 return TRUE;
10256         default:
10257                 return FALSE;
10258         }
10259 }
10260
10261 /**
10262  * mono_class_is_valid_enum:
10263  * @klass: An enum class to be validated
10264  *
10265  * This method verify the required properties an enum should have.
10266  *  
10267  * Returns: TRUE if the informed enum class is valid 
10268  *
10269  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10270  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10271  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10272  */
10273 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10274         MonoClassField * field;
10275         gpointer iter = NULL;
10276         gboolean found_base_field = FALSE;
10277
10278         g_assert (klass->enumtype);
10279         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10280         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10281                 return FALSE;
10282         }
10283
10284         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10285                 return FALSE;
10286
10287         while ((field = mono_class_get_fields (klass, &iter))) {
10288                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10289                         if (found_base_field)
10290                                 return FALSE;
10291                         found_base_field = TRUE;
10292                         if (!mono_type_is_valid_enum_basetype (field->type))
10293                                 return FALSE;
10294                 }
10295         }
10296
10297         if (!found_base_field)
10298                 return FALSE;
10299
10300         if (klass->method.count > 0) 
10301                 return FALSE;
10302
10303         return TRUE;
10304 }
10305
10306 gboolean
10307 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10308 {
10309         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10310 }
10311
10312 /*
10313  * mono_class_setup_interface_id:
10314  *
10315  * Initializes MonoClass::interface_id if required.
10316  *
10317  * LOCKING: Acquires the loader lock.
10318  */
10319 void
10320 mono_class_setup_interface_id (MonoClass *class)
10321 {
10322         mono_loader_lock ();
10323         if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10324                 class->interface_id = mono_get_unique_iid (class);
10325         mono_loader_unlock ();
10326 }
10327
10328 /*
10329  * mono_class_alloc_ext:
10330  *
10331  *   Allocate klass->ext if not already done.
10332  */
10333 void
10334 mono_class_alloc_ext (MonoClass *klass)
10335 {
10336         MonoClassExt *ext;
10337
10338         if (klass->ext)
10339                 return;
10340
10341         ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10342         mono_image_lock (klass->image);
10343         mono_memory_barrier ();
10344         if (!klass->ext)
10345                 klass->ext = ext;
10346         class_ext_size += sizeof (MonoClassExt);
10347         mono_image_unlock (klass->image);
10348 }
10349
10350 /*
10351  * mono_class_setup_interfaces:
10352  *
10353  *   Initialize class->interfaces/interfaces_count.
10354  * LOCKING: Acquires the loader lock.
10355  * This function can fail the type.
10356  */
10357 void
10358 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10359 {
10360         int i, interface_count;
10361         MonoClass **interfaces;
10362
10363         mono_error_init (error);
10364
10365         if (klass->interfaces_inited)
10366                 return;
10367
10368         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10369                 MonoType *args [1];
10370
10371                 /* generic IList, ICollection, IEnumerable */
10372                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10373                 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10374
10375                 args [0] = &klass->element_class->byval_arg;
10376                 interfaces [0] = mono_class_bind_generic_parameters (
10377                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10378                 if (interface_count > 1)
10379                         interfaces [1] = mono_class_bind_generic_parameters (
10380                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10381         } else if (klass->generic_class) {
10382                 MonoClass *gklass = klass->generic_class->container_class;
10383
10384                 mono_class_setup_interfaces (gklass, error);
10385                 if (!mono_error_ok (error)) {
10386                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10387                         return;
10388                 }
10389
10390                 interface_count = gklass->interface_count;
10391                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10392                 for (i = 0; i < interface_count; i++) {
10393                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10394                         if (!mono_error_ok (error)) {
10395                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10396                                 return;
10397                         }
10398                 }
10399         } else {
10400                 interface_count = 0;
10401                 interfaces = NULL;
10402         }
10403
10404         mono_image_lock (klass->image);
10405
10406         if (!klass->interfaces_inited) {
10407                 klass->interface_count = interface_count;
10408                 klass->interfaces = interfaces;
10409
10410                 mono_memory_barrier ();
10411
10412                 klass->interfaces_inited = TRUE;
10413         }
10414
10415         mono_image_unlock (klass->image);
10416 }
10417
10418 static void
10419 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10420 {
10421         MonoClass *class = field->parent;
10422         MonoImage *image = class->image;
10423         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10424         int field_idx = field - class->fields;
10425
10426         mono_error_init (error);
10427
10428         if (gtd) {
10429                 MonoClassField *gfield = &gtd->fields [field_idx];
10430                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10431                 if (!mono_error_ok (error)) {
10432                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10433                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10434                         g_free (err_msg);
10435                 }
10436
10437                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10438                 if (!mono_error_ok (error)) {
10439                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10440                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10441                         g_free (err_msg);
10442                 }
10443         } else {
10444                 const char *sig;
10445                 guint32 cols [MONO_FIELD_SIZE];
10446                 MonoGenericContainer *container = NULL;
10447                 int idx = class->field.first + field_idx;
10448
10449                 /*FIXME, in theory we do not lazy load SRE fields*/
10450                 g_assert (!image_is_dynamic (image));
10451
10452                 if (class->generic_container) {
10453                         container = class->generic_container;
10454                 } else if (gtd) {
10455                         container = gtd->generic_container;
10456                         g_assert (container);
10457                 }
10458
10459                 /* class->field.first and idx points into the fieldptr table */
10460                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10461
10462                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10463                         mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10464                         mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10465                         return;
10466                 }
10467
10468                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10469
10470                 mono_metadata_decode_value (sig, &sig);
10471                 /* FIELD signature == 0x06 */
10472                 g_assert (*sig == 0x06);
10473                 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10474                 if (!field->type)
10475                         mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10476         }
10477 }
10478
10479 static guint32
10480 mono_field_resolve_flags (MonoClassField *field)
10481 {
10482         MonoClass *class = field->parent;
10483         MonoImage *image = class->image;
10484         MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10485         int field_idx = field - class->fields;
10486
10487
10488         if (gtd) {
10489                 MonoClassField *gfield = &gtd->fields [field_idx];
10490                 return mono_field_get_flags (gfield);
10491         } else {
10492                 int idx = class->field.first + field_idx;
10493
10494                 /*FIXME, in theory we do not lazy load SRE fields*/
10495                 g_assert (!image_is_dynamic (image));
10496
10497                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10498         }
10499 }
10500
10501 /**
10502  * mono_class_setup_basic_field_info:
10503  * @class: The class to initialize
10504  *
10505  * Initializes the class->fields array of fields.
10506  * Aquires the loader lock.
10507  */
10508 static void
10509 mono_class_setup_basic_field_info_locking (MonoClass *class)
10510 {
10511         mono_loader_lock ();
10512         mono_class_setup_basic_field_info (class);
10513         mono_loader_unlock ();
10514 }
10515
10516 /**
10517  * mono_class_get_fields_lazy:
10518  * @klass: the MonoClass to act on
10519  *
10520  * This routine is an iterator routine for retrieving the fields in a class.
10521  * Only minimal information about fields are loaded. Accessors must be used
10522  * for all MonoClassField returned.
10523  *
10524  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10525  * iterate over all of the elements.  When no more values are
10526  * available, the return value is NULL.
10527  *
10528  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10529  */
10530 MonoClassField*
10531 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10532 {
10533         MonoClassField* field;
10534         if (!iter)
10535                 return NULL;
10536         if (!*iter) {
10537                 mono_class_setup_basic_field_info_locking (klass);
10538                 if (!klass->fields)
10539                         return NULL;
10540                 /* start from the first */
10541                 if (klass->field.count) {
10542                         return *iter = &klass->fields [0];
10543                 } else {
10544                         /* no fields */
10545                         return NULL;
10546                 }
10547         }
10548         field = *iter;
10549         field++;
10550         if (field < &klass->fields [klass->field.count]) {
10551                 return *iter = field;
10552         }
10553         return NULL;
10554 }
10555
10556 char*
10557 mono_class_full_name (MonoClass *klass)
10558 {
10559         return mono_type_full_name (&klass->byval_arg);
10560 }
10561