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