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