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