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