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