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