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