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