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