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