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