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