Merge pull request #3142 from henricm/fix-for-win-mono_string_to_utf8
[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         }
7899
7900         if (!token)
7901                 return NULL;
7902
7903         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7904                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7905                 guint32 cols [MONO_EXP_TYPE_SIZE];
7906                 guint32 idx, impl;
7907
7908                 idx = mono_metadata_token_index (token);
7909
7910                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7911
7912                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7913                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7914                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7915                         if (!loaded_image)
7916                                 return NULL;
7917                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7918                         if (nested)
7919                                 return klass ? return_nested_in (klass, nested) : NULL;
7920                         return klass;
7921                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7922                         guint32 assembly_idx;
7923
7924                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7925
7926                         mono_assembly_load_reference (image, assembly_idx - 1);
7927                         g_assert (image->references [assembly_idx - 1]);
7928                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7929                                 return NULL;                    
7930                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7931                         if (nested)
7932                                 return klass ? return_nested_in (klass, nested) : NULL;
7933                         return klass;
7934                 } else {
7935                         g_assert_not_reached ();
7936                 }
7937         }
7938
7939         token = MONO_TOKEN_TYPE_DEF | token;
7940
7941         klass = mono_class_get_checked (image, token, error);
7942         if (nested)
7943                 return return_nested_in (klass, nested);
7944         return klass;
7945 }
7946
7947 /**
7948  * mono_class_from_name_checked:
7949  * @image: The MonoImage where the type is looked up in
7950  * @name_space: the type namespace
7951  * @name: the type short name.
7952  *
7953  * Obtains a MonoClass with a given namespace and a given name which
7954  * is located in the given MonoImage.
7955  *
7956  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7957  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7958  */
7959 MonoClass *
7960 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7961 {
7962         MonoClass *klass;
7963         GHashTable *visited_images;
7964
7965         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7966
7967         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7968
7969         g_hash_table_destroy (visited_images);
7970
7971         return klass;
7972 }
7973
7974 /**
7975  * mono_class_from_name:
7976  * @image: The MonoImage where the type is looked up in
7977  * @name_space: the type namespace
7978  * @name: the type short name.
7979  *
7980  * Obtains a MonoClass with a given namespace and a given name which
7981  * is located in the given MonoImage.
7982  *
7983  * To reference nested classes, use the "/" character as a separator.
7984  * For example use "Foo/Bar" to reference the class Bar that is nested
7985  * inside Foo, like this: "class Foo { class Bar {} }".
7986  */
7987 MonoClass *
7988 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7989 {
7990         MonoError error;
7991         MonoClass *klass;
7992
7993         klass = mono_class_from_name_checked (image, name_space, name, &error);
7994         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7995
7996         return klass;
7997 }
7998
7999 /**
8000  * mono_class_load_from_name:
8001  * @image: The MonoImage where the type is looked up in
8002  * @name_space: the type namespace
8003  * @name: the type short name.
8004  *
8005  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8006  * This function should be used by the runtime for critical types to which there's no way to recover but crash
8007  * If they are missing. Thing of System.Object or System.String.
8008  */
8009 MonoClass *
8010 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8011 {
8012         MonoError error;
8013         MonoClass *klass;
8014
8015         klass = mono_class_from_name_checked (image, name_space, name, &error);
8016         if (!klass)
8017                 g_error ("Runtime critical type %s.%s not found", name_space, name);
8018         if (!mono_error_ok (&error))
8019                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8020         return klass;
8021 }
8022
8023 /**
8024  * mono_class_try_load_from_name:
8025  * @image: The MonoImage where the type is looked up in
8026  * @name_space: the type namespace
8027  * @name: the type short name.
8028  *
8029  * This function tries to load a type, returning the class was found or NULL otherwise.
8030  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8031  *
8032  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8033  * a type that we would otherwise assume to be available but was not due some error.
8034  *
8035  */
8036 MonoClass*
8037 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8038 {
8039         MonoError error;
8040         MonoClass *klass;
8041
8042         klass = mono_class_from_name_checked (image, name_space, name, &error);
8043         if (!mono_error_ok (&error))
8044                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8045         return klass;
8046 }
8047
8048
8049 /**
8050  * mono_class_is_subclass_of:
8051  * @klass: class to probe if it is a subclass of another one
8052  * @klassc: the class we suspect is the base class
8053  * @check_interfaces: whether we should perform interface checks
8054  *
8055  * This method determines whether @klass is a subclass of @klassc.
8056  *
8057  * If the @check_interfaces flag is set, then if @klassc is an interface
8058  * this method return TRUE if the @klass implements the interface or
8059  * if @klass is an interface, if one of its base classes is @klass.
8060  *
8061  * If @check_interfaces is false then, then if @klass is not an interface
8062  * then it returns TRUE if the @klass is a subclass of @klassc.
8063  *
8064  * if @klass is an interface and @klassc is System.Object, then this function
8065  * return true.
8066  *
8067  */
8068 gboolean
8069 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
8070                            gboolean check_interfaces)
8071 {
8072         /* FIXME test for interfaces with variant generic arguments */
8073         mono_class_init (klass);
8074         mono_class_init (klassc);
8075         
8076         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8077                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8078                         return TRUE;
8079         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8080                 int i;
8081
8082                 for (i = 0; i < klass->interface_count; i ++) {
8083                         MonoClass *ic =  klass->interfaces [i];
8084                         if (ic == klassc)
8085                                 return TRUE;
8086                 }
8087         } else {
8088                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8089                         return TRUE;
8090         }
8091
8092         /* 
8093          * MS.NET thinks interfaces are a subclass of Object, so we think it as
8094          * well.
8095          */
8096         if (klassc == mono_defaults.object_class)
8097                 return TRUE;
8098
8099         return FALSE;
8100 }
8101
8102 static gboolean
8103 mono_type_is_generic_argument (MonoType *type)
8104 {
8105         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8106 }
8107
8108 gboolean
8109 mono_class_has_variant_generic_params (MonoClass *klass)
8110 {
8111         int i;
8112         MonoGenericContainer *container;
8113
8114         if (!klass->generic_class)
8115                 return FALSE;
8116
8117         container = klass->generic_class->container_class->generic_container;
8118
8119         for (i = 0; i < container->type_argc; ++i)
8120                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8121                         return TRUE;
8122
8123         return FALSE;
8124 }
8125
8126 static gboolean
8127 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8128 {
8129         if (target == candidate)
8130                 return TRUE;
8131
8132         if (check_for_reference_conv &&
8133                 mono_type_is_generic_argument (&target->byval_arg) &&
8134                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8135                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8136                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8137
8138                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8139                         return FALSE;
8140         }
8141         if (!mono_class_is_assignable_from (target, candidate))
8142                 return FALSE;
8143         return TRUE;
8144 }
8145
8146 /**
8147  * @container the generic container from the GTD
8148  * @klass: the class to be assigned to
8149  * @oklass: the source class
8150  * 
8151  * Both @klass and @oklass must be instances of the same generic interface.
8152  *
8153  * Returns: TRUE if @klass can be assigned to a @klass variable
8154  */
8155 gboolean
8156 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8157 {
8158         int j;
8159         MonoType **klass_argv, **oklass_argv;
8160         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8161         MonoGenericContainer *container = klass_gtd->generic_container;
8162
8163         if (klass == oklass)
8164                 return TRUE;
8165
8166         /*Viable candidates are instances of the same generic interface*/
8167         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8168                 return FALSE;
8169
8170         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8171         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8172
8173         for (j = 0; j < container->type_argc; ++j) {
8174                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8175                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8176
8177                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8178                         return FALSE;
8179
8180                 /*
8181                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8182                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8183                  */
8184                 if (param1_class != param2_class) {
8185                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8186                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8187                                         return FALSE;
8188                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8189                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8190                                         return FALSE;
8191                         } else
8192                                 return FALSE;
8193                 }
8194         }
8195         return TRUE;
8196 }
8197
8198 static gboolean
8199 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8200 {
8201         MonoGenericParam *gparam, *ogparam;
8202         MonoGenericParamInfo *tinfo, *cinfo;
8203         MonoClass **candidate_class;
8204         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8205         int tmask, cmask;
8206
8207         if (target == candidate)
8208                 return TRUE;
8209         if (target->byval_arg.type != candidate->byval_arg.type)
8210                 return FALSE;
8211
8212         gparam = target->byval_arg.data.generic_param;
8213         ogparam = candidate->byval_arg.data.generic_param;
8214         tinfo = mono_generic_param_info (gparam);
8215         cinfo = mono_generic_param_info (ogparam);
8216
8217         class_constraint_satisfied = FALSE;
8218         valuetype_constraint_satisfied = FALSE;
8219
8220         /*candidate must have a super set of target's special constraints*/
8221         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8222         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8223
8224         if (cinfo->constraints) {
8225                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8226                         MonoClass *cc = *candidate_class;
8227
8228                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8229                                 class_constraint_satisfied = TRUE;
8230                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8231                                 valuetype_constraint_satisfied = TRUE;
8232                 }
8233         }
8234         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8235         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8236
8237         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8238                 return FALSE;
8239         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8240                 return FALSE;
8241         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8242                 valuetype_constraint_satisfied)) {
8243                 return FALSE;
8244         }
8245
8246
8247         /*candidate type constraints must be a superset of target's*/
8248         if (tinfo->constraints) {
8249                 MonoClass **target_class;
8250                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8251                         MonoClass *tc = *target_class;
8252
8253                         /*
8254                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8255                          * check it's constraints since it satisfy the constraint by itself.
8256                          */
8257                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8258                                 continue;
8259
8260                         if (!cinfo->constraints)
8261                                 return FALSE;
8262
8263                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8264                                 MonoClass *cc = *candidate_class;
8265
8266                                 if (mono_class_is_assignable_from (tc, cc))
8267                                         break;
8268
8269                                 /*
8270                                  * This happens when we have the following:
8271                                  *
8272                                  * Bar<K> where K : IFace
8273                                  * Foo<T, U> where T : U where U : IFace
8274                                  *      ...
8275                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8276                                  *
8277                                  */
8278                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8279                                         if (mono_gparam_is_assignable_from (target, cc))
8280                                                 break;
8281                                 }
8282                         }
8283                         if (!*candidate_class)
8284                                 return FALSE;
8285                 }
8286         }
8287
8288         /*candidate itself must have a constraint that satisfy target*/
8289         if (cinfo->constraints) {
8290                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8291                         MonoClass *cc = *candidate_class;
8292                         if (mono_class_is_assignable_from (target, cc))
8293                                 return TRUE;
8294                 }
8295         }
8296         return FALSE;
8297 }
8298
8299 /**
8300  * mono_class_is_assignable_from:
8301  * @klass: the class to be assigned to
8302  * @oklass: the source class
8303  *
8304  * Returns: TRUE if an instance of object oklass can be assigned to an
8305  * instance of object @klass
8306  */
8307 gboolean
8308 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8309 {
8310         MonoError error;
8311         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8312         if (!klass->inited)
8313                 mono_class_init (klass);
8314
8315         if (!oklass->inited)
8316                 mono_class_init (oklass);
8317
8318         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8319                 return FALSE;
8320
8321         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8322                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8323                         return FALSE;
8324                 return mono_gparam_is_assignable_from (klass, oklass);
8325         }
8326
8327         if (MONO_CLASS_IS_INTERFACE (klass)) {
8328                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8329                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8330                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8331                         int i;
8332
8333                         if (constraints) {
8334                                 for (i = 0; constraints [i]; ++i) {
8335                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8336                                                 return TRUE;
8337                                 }
8338                         }
8339
8340                         return FALSE;
8341                 }
8342
8343                 /* interface_offsets might not be set for dynamic classes */
8344                 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8345                         /* 
8346                          * oklass might be a generic type parameter but they have 
8347                          * interface_offsets set.
8348                          */
8349                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8350                         if (!is_ok (&error)) {
8351                                 mono_error_cleanup (&error);
8352                                 return FALSE;
8353                         }
8354                         return result;
8355                 }
8356                 if (!oklass->interface_bitmap)
8357                         /* Happens with generic instances of not-yet created dynamic types */
8358                         return FALSE;
8359                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8360                         return TRUE;
8361
8362                 if (mono_class_has_variant_generic_params (klass)) {
8363                         int i;
8364                         mono_class_setup_interfaces (oklass, &error);
8365                         if (!mono_error_ok (&error)) {
8366                                 mono_error_cleanup (&error);
8367                                 return FALSE;
8368                         }
8369
8370                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8371                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8372                                 MonoClass *iface = oklass->interfaces_packed [i];
8373
8374                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8375                                         return TRUE;
8376                         }
8377                 }
8378                 return FALSE;
8379         } else if (klass->delegate) {
8380                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8381                         return TRUE;
8382         }else if (klass->rank) {
8383                 MonoClass *eclass, *eoclass;
8384
8385                 if (oklass->rank != klass->rank)
8386                         return FALSE;
8387
8388                 /* vectors vs. one dimensional arrays */
8389                 if (oklass->byval_arg.type != klass->byval_arg.type)
8390                         return FALSE;
8391
8392                 eclass = klass->cast_class;
8393                 eoclass = oklass->cast_class;
8394
8395                 /* 
8396                  * a is b does not imply a[] is b[] when a is a valuetype, and
8397                  * b is a reference type.
8398                  */
8399
8400                 if (eoclass->valuetype) {
8401                         if ((eclass == mono_defaults.enum_class) || 
8402                                 (eclass == mono_defaults.enum_class->parent) ||
8403                                 (eclass == mono_defaults.object_class))
8404                                 return FALSE;
8405                 }
8406
8407                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8408         } else if (mono_class_is_nullable (klass)) {
8409                 if (mono_class_is_nullable (oklass))
8410                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8411                 else
8412                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8413         } else if (klass == mono_defaults.object_class)
8414                 return TRUE;
8415
8416         return mono_class_has_parent (oklass, klass);
8417 }       
8418
8419 /*Check if @oklass is variant compatible with @klass.*/
8420 static gboolean
8421 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8422 {
8423         int j;
8424         MonoType **klass_argv, **oklass_argv;
8425         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8426         MonoGenericContainer *container = klass_gtd->generic_container;
8427
8428         /*Viable candidates are instances of the same generic interface*/
8429         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8430                 return FALSE;
8431
8432         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8433         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8434
8435         for (j = 0; j < container->type_argc; ++j) {
8436                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8437                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8438
8439                 if (param1_class->valuetype != param2_class->valuetype)
8440                         return FALSE;
8441
8442                 /*
8443                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8444                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8445                  */
8446                 if (param1_class != param2_class) {
8447                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8448                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8449                                         return FALSE;
8450                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8451                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8452                                         return FALSE;
8453                         } else
8454                                 return FALSE;
8455                 }
8456         }
8457         return TRUE;
8458 }
8459 /*Check if @candidate implements the interface @target*/
8460 static gboolean
8461 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8462 {
8463         MonoError error;
8464         int i;
8465         gboolean is_variant = mono_class_has_variant_generic_params (target);
8466
8467         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8468                 if (mono_class_is_variant_compatible_slow (target, candidate))
8469                         return TRUE;
8470         }
8471
8472         do {
8473                 if (candidate == target)
8474                         return TRUE;
8475
8476                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8477                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8478                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8479                         int j;
8480                         if (tb && tb->interfaces) {
8481                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8482                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8483                                         MonoClass *iface_class;
8484
8485                                         /* we can't realize the type here since it can do pretty much anything. */
8486                                         if (!iface->type)
8487                                                 continue;
8488                                         iface_class = mono_class_from_mono_type (iface->type);
8489                                         if (iface_class == target)
8490                                                 return TRUE;
8491                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8492                                                 return TRUE;
8493                                         if (mono_class_implement_interface_slow (target, iface_class))
8494                                                 return TRUE;
8495                                 }
8496                         }
8497                 } else {
8498                         /*setup_interfaces don't mono_class_init anything*/
8499                         /*FIXME this doesn't handle primitive type arrays.
8500                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8501                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8502                         */
8503                         mono_class_setup_interfaces (candidate, &error);
8504                         if (!mono_error_ok (&error)) {
8505                                 mono_error_cleanup (&error);
8506                                 return FALSE;
8507                         }
8508
8509                         for (i = 0; i < candidate->interface_count; ++i) {
8510                                 if (candidate->interfaces [i] == target)
8511                                         return TRUE;
8512                                 
8513                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8514                                         return TRUE;
8515
8516                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8517                                         return TRUE;
8518                         }
8519                 }
8520                 candidate = candidate->parent;
8521         } while (candidate);
8522
8523         return FALSE;
8524 }
8525
8526 /*
8527  * Check if @oklass can be assigned to @klass.
8528  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8529  */
8530 gboolean
8531 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8532 {
8533         if (candidate == target)
8534                 return TRUE;
8535         if (target == mono_defaults.object_class)
8536                 return TRUE;
8537
8538         if (mono_class_has_parent (candidate, target))
8539                 return TRUE;
8540
8541         /*If target is not an interface there is no need to check them.*/
8542         if (MONO_CLASS_IS_INTERFACE (target))
8543                 return mono_class_implement_interface_slow (target, candidate);
8544
8545         if (target->delegate && mono_class_has_variant_generic_params (target))
8546                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8547
8548         if (target->rank) {
8549                 MonoClass *eclass, *eoclass;
8550
8551                 if (target->rank != candidate->rank)
8552                         return FALSE;
8553
8554                 /* vectors vs. one dimensional arrays */
8555                 if (target->byval_arg.type != candidate->byval_arg.type)
8556                         return FALSE;
8557
8558                 eclass = target->cast_class;
8559                 eoclass = candidate->cast_class;
8560
8561                 /*
8562                  * a is b does not imply a[] is b[] when a is a valuetype, and
8563                  * b is a reference type.
8564                  */
8565
8566                 if (eoclass->valuetype) {
8567                         if ((eclass == mono_defaults.enum_class) ||
8568                                 (eclass == mono_defaults.enum_class->parent) ||
8569                                 (eclass == mono_defaults.object_class))
8570                                 return FALSE;
8571                 }
8572
8573                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8574         }
8575         /*FIXME properly handle nullables */
8576         /*FIXME properly handle (M)VAR */
8577         return FALSE;
8578 }
8579
8580 /**
8581  * mono_class_get_cctor:
8582  * @klass: A MonoClass pointer
8583  *
8584  * Returns: The static constructor of @klass if it exists, NULL otherwise.
8585  */
8586 MonoMethod*
8587 mono_class_get_cctor (MonoClass *klass)
8588 {
8589         MonoCachedClassInfo cached_info;
8590
8591         if (image_is_dynamic (klass->image)) {
8592                 /* 
8593                  * has_cctor is not set for these classes because mono_class_init () is
8594                  * not run for them.
8595                  */
8596                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8597         }
8598
8599         if (!klass->has_cctor)
8600                 return NULL;
8601
8602         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8603                 MonoError error;
8604                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8605                 if (!mono_error_ok (&error))
8606                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8607                 return result;
8608         }
8609
8610         if (klass->generic_class && !klass->methods)
8611                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8612
8613         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8614 }
8615
8616 /**
8617  * mono_class_get_finalizer:
8618  * @klass: The MonoClass pointer
8619  *
8620  * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8621  */
8622 MonoMethod*
8623 mono_class_get_finalizer (MonoClass *klass)
8624 {
8625         MonoCachedClassInfo cached_info;
8626
8627         if (!klass->inited)
8628                 mono_class_init (klass);
8629         if (!mono_class_has_finalizer (klass))
8630                 return NULL;
8631
8632         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8633                 MonoError error;
8634                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8635                 if (!mono_error_ok (&error))
8636                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8637                 return result;
8638         }else {
8639                 mono_class_setup_vtable (klass);
8640                 return klass->vtable [finalize_slot];
8641         }
8642 }
8643
8644 /**
8645  * mono_class_needs_cctor_run:
8646  * @klass: the MonoClass pointer
8647  * @caller: a MonoMethod describing the caller
8648  *
8649  * Determines whenever the class has a static constructor and whenever it
8650  * needs to be called when executing CALLER.
8651  */
8652 gboolean
8653 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8654 {
8655         MonoMethod *method;
8656
8657         method = mono_class_get_cctor (klass);
8658         if (method)
8659                 return (method == caller) ? FALSE : TRUE;
8660         else
8661                 return FALSE;
8662 }
8663
8664 /**
8665  * mono_class_array_element_size:
8666  * @klass: 
8667  *
8668  * Returns: The number of bytes an element of type @klass
8669  * uses when stored into an array.
8670  */
8671 gint32
8672 mono_class_array_element_size (MonoClass *klass)
8673 {
8674         MonoType *type = &klass->byval_arg;
8675         
8676 handle_enum:
8677         switch (type->type) {
8678         case MONO_TYPE_I1:
8679         case MONO_TYPE_U1:
8680         case MONO_TYPE_BOOLEAN:
8681                 return 1;
8682         case MONO_TYPE_I2:
8683         case MONO_TYPE_U2:
8684         case MONO_TYPE_CHAR:
8685                 return 2;
8686         case MONO_TYPE_I4:
8687         case MONO_TYPE_U4:
8688         case MONO_TYPE_R4:
8689                 return 4;
8690         case MONO_TYPE_I:
8691         case MONO_TYPE_U:
8692         case MONO_TYPE_PTR:
8693         case MONO_TYPE_CLASS:
8694         case MONO_TYPE_STRING:
8695         case MONO_TYPE_OBJECT:
8696         case MONO_TYPE_SZARRAY:
8697         case MONO_TYPE_ARRAY: 
8698                 return sizeof (gpointer);
8699         case MONO_TYPE_I8:
8700         case MONO_TYPE_U8:
8701         case MONO_TYPE_R8:
8702                 return 8;
8703         case MONO_TYPE_VALUETYPE:
8704                 if (type->data.klass->enumtype) {
8705                         type = mono_class_enum_basetype (type->data.klass);
8706                         klass = klass->element_class;
8707                         goto handle_enum;
8708                 }
8709                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8710         case MONO_TYPE_GENERICINST:
8711                 type = &type->data.generic_class->container_class->byval_arg;
8712                 goto handle_enum;
8713         case MONO_TYPE_VAR:
8714         case MONO_TYPE_MVAR: {
8715                 int align;
8716
8717                 return mono_type_size (type, &align);
8718         }
8719         case MONO_TYPE_VOID:
8720                 return 0;
8721                 
8722         default:
8723                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8724         }
8725         return -1;
8726 }
8727
8728 /**
8729  * mono_array_element_size:
8730  * @ac: pointer to a #MonoArrayClass
8731  *
8732  * Returns: The size of single array element.
8733  */
8734 gint32
8735 mono_array_element_size (MonoClass *ac)
8736 {
8737         g_assert (ac->rank);
8738         return ac->sizes.element_size;
8739 }
8740
8741 gpointer
8742 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8743               MonoGenericContext *context)
8744 {
8745         MonoError error;
8746         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8747         g_assert (mono_error_ok (&error));
8748         return res;
8749 }
8750
8751 gpointer
8752 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8753               MonoGenericContext *context, MonoError *error)
8754 {
8755         mono_error_init (error);
8756
8757         if (image_is_dynamic (image)) {
8758                 MonoClass *tmp_handle_class;
8759                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8760
8761                 mono_error_assert_ok (error);
8762                 g_assert (tmp_handle_class);
8763                 if (handle_class)
8764                         *handle_class = tmp_handle_class;
8765
8766                 if (tmp_handle_class == mono_defaults.typehandle_class)
8767                         return &((MonoClass*)obj)->byval_arg;
8768                 else
8769                         return obj;
8770         }
8771
8772         switch (token & 0xff000000) {
8773         case MONO_TOKEN_TYPE_DEF:
8774         case MONO_TOKEN_TYPE_REF:
8775         case MONO_TOKEN_TYPE_SPEC: {
8776                 MonoType *type;
8777                 if (handle_class)
8778                         *handle_class = mono_defaults.typehandle_class;
8779                 type = mono_type_get_checked (image, token, context, error);
8780                 if (!type)
8781                         return NULL;
8782
8783                 mono_class_init (mono_class_from_mono_type (type));
8784                 /* We return a MonoType* as handle */
8785                 return type;
8786         }
8787         case MONO_TOKEN_FIELD_DEF: {
8788                 MonoClass *klass;
8789                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8790                 if (!type) {
8791                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8792                         return NULL;
8793                 }
8794                 if (handle_class)
8795                         *handle_class = mono_defaults.fieldhandle_class;
8796                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8797                 if (!klass)
8798                         return NULL;
8799
8800                 mono_class_init (klass);
8801                 return mono_class_get_field (klass, token);
8802         }
8803         case MONO_TOKEN_METHOD_DEF:
8804         case MONO_TOKEN_METHOD_SPEC: {
8805                 MonoMethod *meth;
8806                 meth = mono_get_method_checked (image, token, NULL, context, error);
8807                 if (handle_class)
8808                         *handle_class = mono_defaults.methodhandle_class;
8809                 if (!meth)
8810                         return NULL;
8811
8812                 return meth;
8813         }
8814         case MONO_TOKEN_MEMBER_REF: {
8815                 guint32 cols [MONO_MEMBERREF_SIZE];
8816                 const char *sig;
8817                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8818                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8819                 mono_metadata_decode_blob_size (sig, &sig);
8820                 if (*sig == 0x6) { /* it's a field */
8821                         MonoClass *klass;
8822                         MonoClassField *field;
8823                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8824                         if (handle_class)
8825                                 *handle_class = mono_defaults.fieldhandle_class;
8826                         return field;
8827                 } else {
8828                         MonoMethod *meth;
8829                         meth = mono_get_method_checked (image, token, NULL, context, error);
8830                         if (handle_class)
8831                                 *handle_class = mono_defaults.methodhandle_class;
8832                         return meth;
8833                 }
8834         }
8835         default:
8836                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8837         }
8838         return NULL;
8839 }
8840
8841 gpointer
8842 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8843 {
8844         MonoClass *handle_class;
8845         mono_error_init (error);
8846         return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8847 }
8848
8849 gpointer
8850 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8851 {
8852         return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8853 }
8854
8855 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8856
8857 void
8858 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8859 {
8860         get_cached_class_info = func;
8861 }
8862
8863 static gboolean
8864 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8865 {
8866         if (!get_cached_class_info)
8867                 return FALSE;
8868         else
8869                 return get_cached_class_info (klass, res);
8870 }
8871
8872 void
8873 mono_install_get_class_from_name (MonoGetClassFromName func)
8874 {
8875         get_class_from_name = func;
8876 }
8877
8878 /**
8879  * mono_class_get_image:
8880  *
8881  * Use this method to get the `MonoImage*` where this class came from.
8882  *
8883  * Returns: The image where this class is defined.
8884  */
8885 MonoImage*
8886 mono_class_get_image (MonoClass *klass)
8887 {
8888         return klass->image;
8889 }
8890
8891 /**
8892  * mono_class_get_element_class:
8893  * @klass: the MonoClass to act on
8894  *
8895  * Use this function to get the element class of an array.
8896  *
8897  * Returns: The element class of an array.
8898  */
8899 MonoClass*
8900 mono_class_get_element_class (MonoClass *klass)
8901 {
8902         return klass->element_class;
8903 }
8904
8905 /**
8906  * mono_class_is_valuetype:
8907  * @klass: the MonoClass to act on
8908  *
8909  * Use this method to determine if the provided `MonoClass*` represents a value type,
8910  * or a reference type.
8911  *
8912  * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8913  */
8914 gboolean
8915 mono_class_is_valuetype (MonoClass *klass)
8916 {
8917         return klass->valuetype;
8918 }
8919
8920 /**
8921  * mono_class_is_enum:
8922  * @klass: the MonoClass to act on
8923  *
8924  * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8925  *
8926  * Returns: TRUE if the MonoClass represents an enumeration.
8927  */
8928 gboolean
8929 mono_class_is_enum (MonoClass *klass)
8930 {
8931         return klass->enumtype;
8932 }
8933
8934 /**
8935  * mono_class_enum_basetype:
8936  * @klass: the MonoClass to act on
8937  *
8938  * Use this function to get the underlying type for an enumeration value.
8939  * 
8940  * Returns: The underlying type representation for an enumeration.
8941  */
8942 MonoType*
8943 mono_class_enum_basetype (MonoClass *klass)
8944 {
8945         if (klass->element_class == klass)
8946                 /* SRE or broken types */
8947                 return NULL;
8948         else
8949                 return &klass->element_class->byval_arg;
8950 }
8951
8952 /**
8953  * mono_class_get_parent
8954  * @klass: the MonoClass to act on
8955  *
8956  * Returns: The parent class for this class.
8957  */
8958 MonoClass*
8959 mono_class_get_parent (MonoClass *klass)
8960 {
8961         return klass->parent;
8962 }
8963
8964 /**
8965  * mono_class_get_nesting_type:
8966  * @klass: the MonoClass to act on
8967  *
8968  * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8969  *
8970  * If the return is NULL, this indicates that this class is not nested.
8971  *
8972  * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8973  */
8974 MonoClass*
8975 mono_class_get_nesting_type (MonoClass *klass)
8976 {
8977         return klass->nested_in;
8978 }
8979
8980 /**
8981  * mono_class_get_rank:
8982  * @klass: the MonoClass to act on
8983  *
8984  * Returns: The rank for the array (the number of dimensions).
8985  */
8986 int
8987 mono_class_get_rank (MonoClass *klass)
8988 {
8989         return klass->rank;
8990 }
8991
8992 /**
8993  * mono_class_get_flags:
8994  * @klass: the MonoClass to act on
8995  *
8996  * The type flags from the TypeDef table from the metadata.
8997  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8998  * different values.
8999  *
9000  * Returns: The flags from the TypeDef table.
9001  */
9002 guint32
9003 mono_class_get_flags (MonoClass *klass)
9004 {
9005         return klass->flags;
9006 }
9007
9008 /**
9009  * mono_class_get_name
9010  * @klass: the MonoClass to act on
9011  *
9012  * Returns: The name of the class.
9013  */
9014 const char*
9015 mono_class_get_name (MonoClass *klass)
9016 {
9017         return klass->name;
9018 }
9019
9020 /**
9021  * mono_class_get_namespace:
9022  * @klass: the MonoClass to act on
9023  *
9024  * Returns: The namespace of the class.
9025  */
9026 const char*
9027 mono_class_get_namespace (MonoClass *klass)
9028 {
9029         return klass->name_space;
9030 }
9031
9032 /**
9033  * mono_class_get_type:
9034  * @klass: the MonoClass to act on
9035  *
9036  * This method returns the internal Type representation for the class.
9037  *
9038  * Returns: The MonoType from the class.
9039  */
9040 MonoType*
9041 mono_class_get_type (MonoClass *klass)
9042 {
9043         return &klass->byval_arg;
9044 }
9045
9046 /**
9047  * mono_class_get_type_token:
9048  * @klass: the MonoClass to act on
9049  *
9050  * This method returns type token for the class.
9051  *
9052  * Returns: The type token for the class.
9053  */
9054 guint32
9055 mono_class_get_type_token (MonoClass *klass)
9056 {
9057   return klass->type_token;
9058 }
9059
9060 /**
9061  * mono_class_get_byref_type:
9062  * @klass: the MonoClass to act on
9063  *
9064  * 
9065  */
9066 MonoType*
9067 mono_class_get_byref_type (MonoClass *klass)
9068 {
9069         return &klass->this_arg;
9070 }
9071
9072 /**
9073  * mono_class_num_fields:
9074  * @klass: the MonoClass to act on
9075  *
9076  * Returns: The number of static and instance fields in the class.
9077  */
9078 int
9079 mono_class_num_fields (MonoClass *klass)
9080 {
9081         return klass->field.count;
9082 }
9083
9084 /**
9085  * mono_class_num_methods:
9086  * @klass: the MonoClass to act on
9087  *
9088  * Returns: The number of methods in the class.
9089  */
9090 int
9091 mono_class_num_methods (MonoClass *klass)
9092 {
9093         return klass->method.count;
9094 }
9095
9096 /**
9097  * mono_class_num_properties
9098  * @klass: the MonoClass to act on
9099  *
9100  * Returns: The number of properties in the class.
9101  */
9102 int
9103 mono_class_num_properties (MonoClass *klass)
9104 {
9105         mono_class_setup_properties (klass);
9106
9107         return klass->ext->property.count;
9108 }
9109
9110 /**
9111  * mono_class_num_events:
9112  * @klass: the MonoClass to act on
9113  *
9114  * Returns: The number of events in the class.
9115  */
9116 int
9117 mono_class_num_events (MonoClass *klass)
9118 {
9119         mono_class_setup_events (klass);
9120
9121         return klass->ext->event.count;
9122 }
9123
9124 /**
9125  * mono_class_get_fields:
9126  * @klass: the MonoClass to act on
9127  *
9128  * This routine is an iterator routine for retrieving the fields in a class.
9129  *
9130  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9131  * iterate over all of the elements.  When no more values are
9132  * available, the return value is NULL.
9133  *
9134  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9135  */
9136 MonoClassField*
9137 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9138 {
9139         MonoClassField* field;
9140         if (!iter)
9141                 return NULL;
9142         if (!*iter) {
9143                 mono_class_setup_fields_locking (klass);
9144                 if (mono_class_has_failure (klass))
9145                         return NULL;
9146                 /* start from the first */
9147                 if (klass->field.count) {
9148                         *iter = &klass->fields [0];
9149                         return &klass->fields [0];
9150                 } else {
9151                         /* no fields */
9152                         return NULL;
9153                 }
9154         }
9155         field = (MonoClassField *)*iter;
9156         field++;
9157         if (field < &klass->fields [klass->field.count]) {
9158                 *iter = field;
9159                 return field;
9160         }
9161         return NULL;
9162 }
9163
9164 /**
9165  * mono_class_get_methods
9166  * @klass: the MonoClass to act on
9167  *
9168  * This routine is an iterator routine for retrieving the fields in a class.
9169  *
9170  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9171  * iterate over all of the elements.  When no more values are
9172  * available, the return value is NULL.
9173  *
9174  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9175  */
9176 MonoMethod*
9177 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9178 {
9179         MonoMethod** method;
9180         if (!iter)
9181                 return NULL;
9182         if (!*iter) {
9183                 mono_class_setup_methods (klass);
9184
9185                 /*
9186                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9187                  * FIXME we should better report this error to the caller
9188                  */
9189                 if (!klass->methods)
9190                         return NULL;
9191                 /* start from the first */
9192                 if (klass->method.count) {
9193                         *iter = &klass->methods [0];
9194                         return klass->methods [0];
9195                 } else {
9196                         /* no method */
9197                         return NULL;
9198                 }
9199         }
9200         method = (MonoMethod **)*iter;
9201         method++;
9202         if (method < &klass->methods [klass->method.count]) {
9203                 *iter = method;
9204                 return *method;
9205         }
9206         return NULL;
9207 }
9208
9209 /*
9210  * mono_class_get_virtual_methods:
9211  *
9212  *   Iterate over the virtual methods of KLASS.
9213  *
9214  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9215  */
9216 static MonoMethod*
9217 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9218 {
9219         MonoMethod** method;
9220         if (!iter)
9221                 return NULL;
9222         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9223                 if (!*iter) {
9224                         mono_class_setup_methods (klass);
9225                         /*
9226                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9227                          * FIXME we should better report this error to the caller
9228                          */
9229                         if (!klass->methods)
9230                                 return NULL;
9231                         /* start from the first */
9232                         method = &klass->methods [0];
9233                 } else {
9234                         method = (MonoMethod **)*iter;
9235                         method++;
9236                 }
9237                 while (method < &klass->methods [klass->method.count]) {
9238                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9239                                 break;
9240                         method ++;
9241                 }
9242                 if (method < &klass->methods [klass->method.count]) {
9243                         *iter = method;
9244                         return *method;
9245                 } else {
9246                         return NULL;
9247                 }
9248         } else {
9249                 /* Search directly in metadata to avoid calling setup_methods () */
9250                 MonoMethod *res = NULL;
9251                 int i, start_index;
9252
9253                 if (!*iter) {
9254                         start_index = 0;
9255                 } else {
9256                         start_index = GPOINTER_TO_UINT (*iter);
9257                 }
9258
9259                 for (i = start_index; i < klass->method.count; ++i) {
9260                         guint32 flags;
9261
9262                         /* klass->method.first points into the methodptr table */
9263                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9264
9265                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9266                                 break;
9267                 }
9268
9269                 if (i < klass->method.count) {
9270                         MonoError error;
9271                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9272                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9273
9274                         /* Add 1 here so the if (*iter) check fails */
9275                         *iter = GUINT_TO_POINTER (i + 1);
9276                         return res;
9277                 } else {
9278                         return NULL;
9279                 }
9280         }
9281 }
9282
9283 /**
9284  * mono_class_get_properties:
9285  * @klass: the MonoClass to act on
9286  *
9287  * This routine is an iterator routine for retrieving the properties in a class.
9288  *
9289  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9290  * iterate over all of the elements.  When no more values are
9291  * available, the return value is NULL.
9292  *
9293  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9294  */
9295 MonoProperty*
9296 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9297 {
9298         MonoProperty* property;
9299         if (!iter)
9300                 return NULL;
9301         if (!*iter) {
9302                 mono_class_setup_properties (klass);
9303                 /* start from the first */
9304                 if (klass->ext->property.count) {
9305                         *iter = &klass->ext->properties [0];
9306                         return (MonoProperty *)*iter;
9307                 } else {
9308                         /* no fields */
9309                         return NULL;
9310                 }
9311         }
9312         property = (MonoProperty *)*iter;
9313         property++;
9314         if (property < &klass->ext->properties [klass->ext->property.count]) {
9315                 *iter = property;
9316                 return (MonoProperty *)*iter;
9317         }
9318         return NULL;
9319 }
9320
9321 /**
9322  * mono_class_get_events:
9323  * @klass: the MonoClass to act on
9324  *
9325  * This routine is an iterator routine for retrieving the properties in a class.
9326  *
9327  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9328  * iterate over all of the elements.  When no more values are
9329  * available, the return value is NULL.
9330  *
9331  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9332  */
9333 MonoEvent*
9334 mono_class_get_events (MonoClass* klass, gpointer *iter)
9335 {
9336         MonoEvent* event;
9337         if (!iter)
9338                 return NULL;
9339         if (!*iter) {
9340                 mono_class_setup_events (klass);
9341                 /* start from the first */
9342                 if (klass->ext->event.count) {
9343                         *iter = &klass->ext->events [0];
9344                         return (MonoEvent *)*iter;
9345                 } else {
9346                         /* no fields */
9347                         return NULL;
9348                 }
9349         }
9350         event = (MonoEvent *)*iter;
9351         event++;
9352         if (event < &klass->ext->events [klass->ext->event.count]) {
9353                 *iter = event;
9354                 return (MonoEvent *)*iter;
9355         }
9356         return NULL;
9357 }
9358
9359 /**
9360  * mono_class_get_interfaces
9361  * @klass: the MonoClass to act on
9362  *
9363  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9364  *
9365  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9366  * iterate over all of the elements.  When no more values are
9367  * available, the return value is NULL.
9368  *
9369  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9370  */
9371 MonoClass*
9372 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9373 {
9374         MonoError error;
9375         MonoClass** iface;
9376         if (!iter)
9377                 return NULL;
9378         if (!*iter) {
9379                 if (!klass->inited)
9380                         mono_class_init (klass);
9381                 if (!klass->interfaces_inited) {
9382                         mono_class_setup_interfaces (klass, &error);
9383                         if (!mono_error_ok (&error)) {
9384                                 mono_error_cleanup (&error);
9385                                 return NULL;
9386                         }
9387                 }
9388                 /* start from the first */
9389                 if (klass->interface_count) {
9390                         *iter = &klass->interfaces [0];
9391                         return klass->interfaces [0];
9392                 } else {
9393                         /* no interface */
9394                         return NULL;
9395                 }
9396         }
9397         iface = (MonoClass **)*iter;
9398         iface++;
9399         if (iface < &klass->interfaces [klass->interface_count]) {
9400                 *iter = iface;
9401                 return *iface;
9402         }
9403         return NULL;
9404 }
9405
9406 static void
9407 setup_nested_types (MonoClass *klass)
9408 {
9409         MonoError error;
9410         GList *classes, *nested_classes, *l;
9411         int i;
9412
9413         if (klass->nested_classes_inited)
9414                 return;
9415
9416         if (!klass->type_token)
9417                 klass->nested_classes_inited = TRUE;
9418
9419         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9420         classes = NULL;
9421         while (i) {
9422                 MonoClass* nclass;
9423                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9424                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9425                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9426                 if (!mono_error_ok (&error)) {
9427                         /*FIXME don't swallow the error message*/
9428                         mono_error_cleanup (&error);
9429
9430                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9431                         continue;
9432                 }
9433
9434                 classes = g_list_prepend (classes, nclass);
9435
9436                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9437         }
9438
9439         mono_class_alloc_ext (klass);
9440
9441         nested_classes = NULL;
9442         for (l = classes; l; l = l->next)
9443                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9444         g_list_free (classes);
9445
9446         mono_image_lock (klass->image);
9447
9448         mono_memory_barrier ();
9449         if (!klass->nested_classes_inited) {
9450                 klass->ext->nested_classes = nested_classes;
9451                 mono_memory_barrier ();
9452                 klass->nested_classes_inited = TRUE;
9453         }
9454
9455         mono_image_unlock (klass->image);
9456 }
9457
9458 /**
9459  * mono_class_get_nested_types
9460  * @klass: the MonoClass to act on
9461  *
9462  * This routine is an iterator routine for retrieving the nested types of a class.
9463  * This works only if @klass is non-generic, or a generic type definition.
9464  *
9465  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9466  * iterate over all of the elements.  When no more values are
9467  * available, the return value is NULL.
9468  *
9469  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9470  */
9471 MonoClass*
9472 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9473 {
9474         GList *item;
9475
9476         if (!iter)
9477                 return NULL;
9478         if (!klass->nested_classes_inited)
9479                 setup_nested_types (klass);
9480
9481         if (!*iter) {
9482                 /* start from the first */
9483                 if (klass->ext && klass->ext->nested_classes) {
9484                         *iter = klass->ext->nested_classes;
9485                         return (MonoClass *)klass->ext->nested_classes->data;
9486                 } else {
9487                         /* no nested types */
9488                         return NULL;
9489                 }
9490         }
9491         item = (GList *)*iter;
9492         item = item->next;
9493         if (item) {
9494                 *iter = item;
9495                 return (MonoClass *)item->data;
9496         }
9497         return NULL;
9498 }
9499
9500
9501 /**
9502  * mono_class_is_delegate
9503  * @klass: the MonoClass to act on
9504  *
9505  * Returns: TRUE if the MonoClass represents a System.Delegate.
9506  */
9507 mono_bool
9508 mono_class_is_delegate (MonoClass *klass)
9509 {
9510         return klass->delegate;
9511 }
9512
9513 /**
9514  * mono_class_implements_interface
9515  * @klass: The MonoClass to act on
9516  * @interface: The interface to check if @klass implements.
9517  *
9518  * Returns: TRUE if @klass implements @interface.
9519  */
9520 mono_bool
9521 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9522 {
9523         return mono_class_is_assignable_from (iface, klass);
9524 }
9525
9526 /**
9527  * mono_field_get_name:
9528  * @field: the MonoClassField to act on
9529  *
9530  * Returns: The name of the field.
9531  */
9532 const char*
9533 mono_field_get_name (MonoClassField *field)
9534 {
9535         return field->name;
9536 }
9537
9538 /**
9539  * mono_field_get_type:
9540  * @field: the MonoClassField to act on
9541  *
9542  * Returns: MonoType of the field.
9543  */
9544 MonoType*
9545 mono_field_get_type (MonoClassField *field)
9546 {
9547         MonoError error;
9548         MonoType *type = mono_field_get_type_checked (field, &error);
9549         if (!mono_error_ok (&error)) {
9550                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9551                 mono_error_cleanup (&error);
9552         }
9553         return type;
9554 }
9555
9556
9557 /**
9558  * mono_field_get_type_checked:
9559  * @field: the MonoClassField to act on
9560  * @error: used to return any erro found while retrieving @field type
9561  *
9562  * Returns: MonoType of the field.
9563  */
9564 MonoType*
9565 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9566 {
9567         mono_error_init (error);
9568         if (!field->type)
9569                 mono_field_resolve_type (field, error);
9570         return field->type;
9571 }
9572
9573 /**
9574  * mono_field_get_parent:
9575  * @field: the MonoClassField to act on
9576  *
9577  * Returns: MonoClass where the field was defined.
9578  */
9579 MonoClass*
9580 mono_field_get_parent (MonoClassField *field)
9581 {
9582         return field->parent;
9583 }
9584
9585 /**
9586  * mono_field_get_flags;
9587  * @field: the MonoClassField to act on
9588  *
9589  * The metadata flags for a field are encoded using the
9590  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9591  *
9592  * Returns: The flags for the field.
9593  */
9594 guint32
9595 mono_field_get_flags (MonoClassField *field)
9596 {
9597         if (!field->type)
9598                 return mono_field_resolve_flags (field);
9599         return field->type->attrs;
9600 }
9601
9602 /**
9603  * mono_field_get_offset:
9604  * @field: the MonoClassField to act on
9605  *
9606  * Returns: The field offset.
9607  */
9608 guint32
9609 mono_field_get_offset (MonoClassField *field)
9610 {
9611         return field->offset;
9612 }
9613
9614 static const char *
9615 mono_field_get_rva (MonoClassField *field)
9616 {
9617         guint32 rva;
9618         int field_index;
9619         MonoClass *klass = field->parent;
9620         MonoFieldDefaultValue *field_def_values;
9621
9622         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9623
9624         if (!klass->ext || !klass->ext->field_def_values) {
9625                 mono_class_alloc_ext (klass);
9626
9627                 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9628
9629                 mono_image_lock (klass->image);
9630                 if (!klass->ext->field_def_values)
9631                         klass->ext->field_def_values = field_def_values;
9632                 mono_image_unlock (klass->image);
9633         }
9634
9635         field_index = mono_field_get_index (field);
9636                 
9637         if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9638                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9639                 if (!rva)
9640                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9641                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9642         }
9643
9644         return klass->ext->field_def_values [field_index].data;
9645 }
9646
9647 /**
9648  * mono_field_get_data:
9649  * @field: the MonoClassField to act on
9650  *
9651  * Returns: A pointer to the metadata constant value or to the field
9652  * data if it has an RVA flag.
9653  */
9654 const char *
9655 mono_field_get_data (MonoClassField *field)
9656 {
9657         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9658                 MonoTypeEnum def_type;
9659
9660                 return mono_class_get_field_default_value (field, &def_type);
9661         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9662                 return mono_field_get_rva (field);
9663         } else {
9664                 return NULL;
9665         }
9666 }
9667
9668 /**
9669  * mono_property_get_name: 
9670  * @prop: the MonoProperty to act on
9671  *
9672  * Returns: The name of the property
9673  */
9674 const char*
9675 mono_property_get_name (MonoProperty *prop)
9676 {
9677         return prop->name;
9678 }
9679
9680 /**
9681  * mono_property_get_set_method
9682  * @prop: the MonoProperty to act on.
9683  *
9684  * Returns: The setter method of the property (A MonoMethod)
9685  */
9686 MonoMethod*
9687 mono_property_get_set_method (MonoProperty *prop)
9688 {
9689         return prop->set;
9690 }
9691
9692 /**
9693  * mono_property_get_get_method
9694  * @prop: the MonoProperty to act on.
9695  *
9696  * Returns: The setter method of the property (A MonoMethod)
9697  */
9698 MonoMethod*
9699 mono_property_get_get_method (MonoProperty *prop)
9700 {
9701         return prop->get;
9702 }
9703
9704 /**
9705  * mono_property_get_parent:
9706  * @prop: the MonoProperty to act on.
9707  *
9708  * Returns: The MonoClass where the property was defined.
9709  */
9710 MonoClass*
9711 mono_property_get_parent (MonoProperty *prop)
9712 {
9713         return prop->parent;
9714 }
9715
9716 /**
9717  * mono_property_get_flags:
9718  * @prop: the MonoProperty to act on.
9719  *
9720  * The metadata flags for a property are encoded using the
9721  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9722  *
9723  * Returns: The flags for the property.
9724  */
9725 guint32
9726 mono_property_get_flags (MonoProperty *prop)
9727 {
9728         return prop->attrs;
9729 }
9730
9731 /**
9732  * mono_event_get_name:
9733  * @event: the MonoEvent to act on
9734  *
9735  * Returns: The name of the event.
9736  */
9737 const char*
9738 mono_event_get_name (MonoEvent *event)
9739 {
9740         return event->name;
9741 }
9742
9743 /**
9744  * mono_event_get_add_method:
9745  * @event: The MonoEvent to act on.
9746  *
9747  * Returns: The @add' method for the event (a MonoMethod).
9748  */
9749 MonoMethod*
9750 mono_event_get_add_method (MonoEvent *event)
9751 {
9752         return event->add;
9753 }
9754
9755 /**
9756  * mono_event_get_remove_method:
9757  * @event: The MonoEvent to act on.
9758  *
9759  * Returns: The @remove method for the event (a MonoMethod).
9760  */
9761 MonoMethod*
9762 mono_event_get_remove_method (MonoEvent *event)
9763 {
9764         return event->remove;
9765 }
9766
9767 /**
9768  * mono_event_get_raise_method:
9769  * @event: The MonoEvent to act on.
9770  *
9771  * Returns: The @raise method for the event (a MonoMethod).
9772  */
9773 MonoMethod*
9774 mono_event_get_raise_method (MonoEvent *event)
9775 {
9776         return event->raise;
9777 }
9778
9779 /**
9780  * mono_event_get_parent:
9781  * @event: the MonoEvent to act on.
9782  *
9783  * Returns: The MonoClass where the event is defined.
9784  */
9785 MonoClass*
9786 mono_event_get_parent (MonoEvent *event)
9787 {
9788         return event->parent;
9789 }
9790
9791 /**
9792  * mono_event_get_flags
9793  * @event: the MonoEvent to act on.
9794  *
9795  * The metadata flags for an event are encoded using the
9796  * EVENT_* constants.  See the tabledefs.h file for details.
9797  *
9798  * Returns: The flags for the event.
9799  */
9800 guint32
9801 mono_event_get_flags (MonoEvent *event)
9802 {
9803         return event->attrs;
9804 }
9805
9806 /**
9807  * mono_class_get_method_from_name:
9808  * @klass: where to look for the method
9809  * @name: name of the method
9810  * @param_count: number of parameters. -1 for any number.
9811  *
9812  * Obtains a MonoMethod with a given name and number of parameters.
9813  * It only works if there are no multiple signatures for any given method name.
9814  */
9815 MonoMethod *
9816 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9817 {
9818         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9819 }
9820
9821 static MonoMethod*
9822 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9823 {
9824         MonoMethod *res = NULL;
9825         int i;
9826
9827         /* Search directly in the metadata to avoid calling setup_methods () */
9828         for (i = 0; i < klass->method.count; ++i) {
9829                 MonoError error;
9830                 guint32 cols [MONO_METHOD_SIZE];
9831                 MonoMethod *method;
9832                 MonoMethodSignature *sig;
9833
9834                 /* klass->method.first points into the methodptr table */
9835                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9836
9837                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9838                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9839                         if (!method) {
9840                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9841                                 continue;
9842                         }
9843                         if (param_count == -1) {
9844                                 res = method;
9845                                 break;
9846                         }
9847                         sig = mono_method_signature_checked (method, &error);
9848                         if (!sig) {
9849                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9850                                 continue;
9851                         }
9852                         if (sig->param_count == param_count) {
9853                                 res = method;
9854                                 break;
9855                         }
9856                 }
9857         }
9858
9859         return res;
9860 }
9861
9862 /**
9863  * mono_class_get_method_from_name_flags:
9864  * @klass: where to look for the method
9865  * @name_space: name of the method
9866  * @param_count: number of parameters. -1 for any number.
9867  * @flags: flags which must be set in the method
9868  *
9869  * Obtains a MonoMethod with a given name and number of parameters.
9870  * It only works if there are no multiple signatures for any given method name.
9871  */
9872 MonoMethod *
9873 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9874 {
9875         MonoMethod *res = NULL;
9876         int i;
9877
9878         mono_class_init (klass);
9879
9880         if (klass->generic_class && !klass->methods) {
9881                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9882                 if (res) {
9883                         MonoError error;
9884                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9885                         if (!mono_error_ok (&error))
9886                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9887                 }
9888                 return res;
9889         }
9890
9891         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9892                 mono_class_setup_methods (klass);
9893                 /*
9894                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9895                 See mono/tests/array_load_exception.il
9896                 FIXME we should better report this error to the caller
9897                  */
9898                 if (!klass->methods)
9899                         return NULL;
9900                 for (i = 0; i < klass->method.count; ++i) {
9901                         MonoMethod *method = klass->methods [i];
9902
9903                         if (method->name[0] == name [0] && 
9904                                 !strcmp (name, method->name) &&
9905                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9906                                 ((method->flags & flags) == flags)) {
9907                                 res = method;
9908                                 break;
9909                         }
9910                 }
9911         }
9912         else {
9913             res = find_method_in_metadata (klass, name, param_count, flags);
9914         }
9915
9916         return res;
9917 }
9918
9919 /**
9920  * mono_class_set_failure:
9921  * @klass: class in which the failure was detected
9922  * @ex_type: the kind of exception/error to be thrown (later)
9923  * @ex_data: exception data (specific to each type of exception/error)
9924  *
9925  * Keep a detected failure informations in the class for later processing.
9926  * Note that only the first failure is kept.
9927  *
9928  * LOCKING: Acquires the loader lock.
9929  */
9930 gboolean
9931 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9932 {
9933         if (mono_class_has_failure (klass))
9934                 return FALSE;
9935
9936         mono_loader_lock ();
9937         klass->exception_type = ex_type;
9938         if (ex_data)
9939                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9940         mono_loader_unlock ();
9941
9942         return TRUE;
9943 }
9944
9945 /*
9946  * mono_class_get_exception_data:
9947  *
9948  *   Return the exception_data property of KLASS.
9949  *
9950  * LOCKING: Acquires the loader lock.
9951  */
9952 gpointer
9953 mono_class_get_exception_data (MonoClass *klass)
9954 {
9955         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9956 }
9957
9958 /**
9959  * mono_classes_init:
9960  *
9961  * Initialize the resources used by this module.
9962  */
9963 void
9964 mono_classes_init (void)
9965 {
9966         mono_os_mutex_init (&classes_mutex);
9967
9968         mono_counters_register ("Inflated methods size",
9969                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9970         mono_counters_register ("Inflated classes",
9971                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9972         mono_counters_register ("Inflated classes size",
9973                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9974         mono_counters_register ("MonoClass size",
9975                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9976         mono_counters_register ("MonoClassExt size",
9977                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9978 }
9979
9980 /**
9981  * mono_classes_cleanup:
9982  *
9983  * Free the resources used by this module.
9984  */
9985 void
9986 mono_classes_cleanup (void)
9987 {
9988         if (global_interface_bitset)
9989                 mono_bitset_free (global_interface_bitset);
9990         global_interface_bitset = NULL;
9991         mono_os_mutex_destroy (&classes_mutex);
9992 }
9993
9994 /**
9995  * mono_class_get_exception_for_failure:
9996  * @klass: class in which the failure was detected
9997  *
9998  * Return a constructed MonoException than the caller can then throw
9999  * using mono_raise_exception - or NULL if no failure is present (or
10000  * doesn't result in an exception).
10001  */
10002 MonoException*
10003 mono_class_get_exception_for_failure (MonoClass *klass)
10004 {
10005         gpointer exception_data = mono_class_get_exception_data (klass);
10006
10007         switch (mono_class_get_failure(klass)) {
10008         case MONO_EXCEPTION_TYPE_LOAD: {
10009                 MonoString *name;
10010                 MonoException *ex;
10011                 char *str = mono_type_get_full_name (klass);
10012                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10013                 name = mono_string_new (mono_domain_get (), str);
10014                 g_free (str);
10015                 ex = mono_get_exception_type_load (name, astr);
10016                 g_free (astr);
10017                 return ex;
10018         }
10019         case MONO_EXCEPTION_MISSING_METHOD: {
10020                 char *class_name = (char *)exception_data;
10021                 char *assembly_name = class_name + strlen (class_name) + 1;
10022
10023                 return mono_get_exception_missing_method (class_name, assembly_name);
10024         }
10025         case MONO_EXCEPTION_MISSING_FIELD: {
10026                 char *class_name = (char *)exception_data;
10027                 char *member_name = class_name + strlen (class_name) + 1;
10028
10029                 return mono_get_exception_missing_field (class_name, member_name);
10030         }
10031         case MONO_EXCEPTION_FILE_NOT_FOUND: {
10032                 char *msg_format = (char *)exception_data;
10033                 char *assembly_name = msg_format + strlen (msg_format) + 1;
10034                 char *msg = g_strdup_printf (msg_format, assembly_name);
10035                 MonoException *ex;
10036
10037                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10038
10039                 g_free (msg);
10040
10041                 return ex;
10042         }
10043         case MONO_EXCEPTION_BAD_IMAGE: {
10044                 return mono_get_exception_bad_image_format ((const char *)exception_data);
10045         }
10046         case MONO_EXCEPTION_INVALID_PROGRAM: {
10047                 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10048         }
10049         default: {
10050                 /* TODO - handle other class related failures */
10051                 return mono_get_exception_execution_engine ("Unknown class failure");
10052         }
10053         }
10054 }
10055
10056 static gboolean
10057 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10058  {
10059         outer_klass = mono_class_get_generic_type_definition (outer_klass);
10060         inner_klass = mono_class_get_generic_type_definition (inner_klass);
10061         do {
10062                 if (outer_klass == inner_klass)
10063                         return TRUE;
10064                 inner_klass = inner_klass->nested_in;
10065         } while (inner_klass);
10066         return FALSE;
10067 }
10068
10069 MonoClass *
10070 mono_class_get_generic_type_definition (MonoClass *klass)
10071 {
10072         return klass->generic_class ? klass->generic_class->container_class : klass;
10073 }
10074
10075 /*
10076  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10077  * 
10078  * Generic instantiations are ignored for all super types of @klass.
10079  * 
10080  * Visibility checks ignoring generic instantiations.  
10081  */
10082 gboolean
10083 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10084 {
10085         int i;
10086         klass = mono_class_get_generic_type_definition (klass);
10087         parent = mono_class_get_generic_type_definition (parent);
10088         mono_class_setup_supertypes (klass);
10089
10090         for (i = 0; i < klass->idepth; ++i) {
10091                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10092                         return TRUE;
10093         }
10094         return FALSE;
10095 }
10096 /*
10097  * Subtype can only access parent members with family protection if the site object
10098  * is subclass of Subtype. For example:
10099  * class A { protected int x; }
10100  * class B : A {
10101  *      void valid_access () {
10102  *              B b;
10103  *              b.x = 0;
10104  *  }
10105  *  void invalid_access () {
10106  *              A a;
10107  *              a.x = 0;
10108  *  }
10109  * }
10110  * */
10111 static gboolean
10112 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10113 {
10114         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10115                 return FALSE;
10116
10117         if (context_klass == NULL)
10118                 return TRUE;
10119         /*if access_klass is not member_klass context_klass must be type compat*/
10120         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10121                 return FALSE;
10122         return TRUE;
10123 }
10124
10125 static gboolean
10126 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10127 {
10128         GSList *tmp;
10129         if (accessing == accessed)
10130                 return TRUE;
10131         if (!accessed || !accessing)
10132                 return FALSE;
10133
10134         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10135          * anywhere so untrusted friends are not safe to access platform's code internals */
10136         if (mono_security_core_clr_enabled ()) {
10137                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10138                         return FALSE;
10139         }
10140
10141         mono_assembly_load_friends (accessed);
10142         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10143                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10144                 /* Be conservative with checks */
10145                 if (!friend_->name)
10146                         continue;
10147                 if (strcmp (accessing->aname.name, friend_->name))
10148                         continue;
10149                 if (friend_->public_key_token [0]) {
10150                         if (!accessing->aname.public_key_token [0])
10151                                 continue;
10152                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10153                                 continue;
10154                 }
10155                 return TRUE;
10156         }
10157         return FALSE;
10158 }
10159
10160 /*
10161  * If klass is a generic type or if it is derived from a generic type, return the
10162  * MonoClass of the generic definition
10163  * Returns NULL if not found
10164  */
10165 static MonoClass*
10166 get_generic_definition_class (MonoClass *klass)
10167 {
10168         while (klass) {
10169                 if (klass->generic_class && klass->generic_class->container_class)
10170                         return klass->generic_class->container_class;
10171                 klass = klass->parent;
10172         }
10173         return NULL;
10174 }
10175
10176 static gboolean
10177 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10178 {
10179         int i;
10180         for (i = 0; i < ginst->type_argc; ++i) {
10181                 MonoType *type = ginst->type_argv[i];
10182                 switch (type->type) {
10183                 case MONO_TYPE_SZARRAY:
10184                         if (!can_access_type (access_klass, type->data.klass))
10185                                 return FALSE;
10186                         break;
10187                 case MONO_TYPE_ARRAY:
10188                         if (!can_access_type (access_klass, type->data.array->eklass))
10189                                 return FALSE;
10190                         break;
10191                 case MONO_TYPE_PTR:
10192                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10193                                 return FALSE;
10194                         break;
10195                 case MONO_TYPE_CLASS:
10196                 case MONO_TYPE_VALUETYPE:
10197                 case MONO_TYPE_GENERICINST:
10198                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10199                                 return FALSE;
10200                 default:
10201                         break;
10202                 }
10203         }
10204         return TRUE;
10205 }
10206
10207 static gboolean
10208 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10209 {
10210         int access_level;
10211
10212         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10213                 return TRUE;
10214
10215         if (access_klass->element_class && !access_klass->enumtype)
10216                 access_klass = access_klass->element_class;
10217
10218         if (member_klass->element_class && !member_klass->enumtype)
10219                 member_klass = member_klass->element_class;
10220
10221         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10222
10223         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10224                 return TRUE;
10225
10226         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10227                 return FALSE;
10228
10229         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10230                 return TRUE;
10231
10232         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10233                 return FALSE;
10234
10235         /*Non nested type with nested visibility. We just fail it.*/
10236         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10237                 return FALSE;
10238
10239         switch (access_level) {
10240         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10241                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10242
10243         case TYPE_ATTRIBUTE_PUBLIC:
10244                 return TRUE;
10245
10246         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10247                 return TRUE;
10248
10249         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10250                 return is_nesting_type (member_klass, access_klass);
10251
10252         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10253                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10254
10255         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10256                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10257
10258         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10259                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10260                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10261
10262         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10263                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10264                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10265         }
10266         return FALSE;
10267 }
10268
10269 /* FIXME: check visibility of type, too */
10270 static gboolean
10271 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10272 {
10273         MonoClass *member_generic_def;
10274         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10275                 return TRUE;
10276
10277         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10278                                         access_klass->generic_container) && 
10279                         (member_generic_def = get_generic_definition_class (member_klass))) {
10280                 MonoClass *access_container;
10281
10282                 if (access_klass->generic_container)
10283                         access_container = access_klass;
10284                 else
10285                         access_container = access_klass->generic_class->container_class;
10286
10287                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10288                         return TRUE;
10289         }
10290
10291         /* Partition I 8.5.3.2 */
10292         /* the access level values are the same for fields and methods */
10293         switch (access_level) {
10294         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10295                 /* same compilation unit */
10296                 return access_klass->image == member_klass->image;
10297         case FIELD_ATTRIBUTE_PRIVATE:
10298                 return access_klass == member_klass;
10299         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10300                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10301                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10302                         return TRUE;
10303                 return FALSE;
10304         case FIELD_ATTRIBUTE_ASSEMBLY:
10305                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10306         case FIELD_ATTRIBUTE_FAMILY:
10307                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10308                         return TRUE;
10309                 return FALSE;
10310         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10311                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10312                         return TRUE;
10313                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10314         case FIELD_ATTRIBUTE_PUBLIC:
10315                 return TRUE;
10316         }
10317         return FALSE;
10318 }
10319
10320 /**
10321  * mono_method_can_access_field:
10322  * @method: Method that will attempt to access the field
10323  * @field: the field to access
10324  *
10325  * Used to determine if a method is allowed to access the specified field.
10326  *
10327  * Returns: TRUE if the given @method is allowed to access the @field while following
10328  * the accessibility rules of the CLI.
10329  */
10330 gboolean
10331 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10332 {
10333         /* FIXME: check all overlapping fields */
10334         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10335         if (!can) {
10336                 MonoClass *nested = method->klass->nested_in;
10337                 while (nested) {
10338                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10339                         if (can)
10340                                 return TRUE;
10341                         nested = nested->nested_in;
10342                 }
10343         }
10344         return can;
10345 }
10346
10347 /**
10348  * mono_method_can_access_method:
10349  * @method: Method that will attempt to access the other method
10350  * @called: the method that we want to probe for accessibility.
10351  *
10352  * Used to determine if the @method is allowed to access the specified @called method.
10353  *
10354  * Returns: TRUE if the given @method is allowed to invoke the @called while following
10355  * the accessibility rules of the CLI.
10356  */
10357 gboolean
10358 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10359 {
10360         int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10361         if (!can) {
10362                 MonoClass *nested = method->klass->nested_in;
10363                 while (nested) {
10364                         can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10365                         if (can)
10366                                 return TRUE;
10367                         nested = nested->nested_in;
10368                 }
10369         }
10370         /* 
10371          * FIXME:
10372          * with generics calls to explicit interface implementations can be expressed
10373          * directly: the method is private, but we must allow it. This may be opening
10374          * a hole or the generics code should handle this differently.
10375          * Maybe just ensure the interface type is public.
10376          */
10377         if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10378                 return TRUE;
10379         return can;
10380 }
10381
10382 /*
10383  * mono_method_can_access_method_full:
10384  * @method: The caller method 
10385  * @called: The called method 
10386  * @context_klass: The static type on stack of the owner @called object used
10387  * 
10388  * This function must be used with instance calls, as they have more strict family accessibility.
10389  * It can be used with static methods, but context_klass should be NULL.
10390  * 
10391  * Returns: TRUE if caller have proper visibility and acessibility to @called
10392  */
10393 gboolean
10394 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10395 {
10396         MonoClass *access_class = method->klass;
10397         MonoClass *member_class = called->klass;
10398         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10399         if (!can) {
10400                 MonoClass *nested = access_class->nested_in;
10401                 while (nested) {
10402                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10403                         if (can)
10404                                 break;
10405                         nested = nested->nested_in;
10406                 }
10407         }
10408
10409         if (!can)
10410                 return FALSE;
10411
10412         can = can_access_type (access_class, member_class);
10413         if (!can) {
10414                 MonoClass *nested = access_class->nested_in;
10415                 while (nested) {
10416                         can = can_access_type (nested, member_class);
10417                         if (can)
10418                                 break;
10419                         nested = nested->nested_in;
10420                 }
10421         }
10422
10423         if (!can)
10424                 return FALSE;
10425
10426         if (called->is_inflated) {
10427                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10428                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10429                         return FALSE;
10430         }
10431                 
10432         return TRUE;
10433 }
10434
10435
10436 /*
10437  * mono_method_can_access_field_full:
10438  * @method: The caller method 
10439  * @field: The accessed field
10440  * @context_klass: The static type on stack of the owner @field object used
10441  * 
10442  * This function must be used with instance fields, as they have more strict family accessibility.
10443  * It can be used with static fields, but context_klass should be NULL.
10444  * 
10445  * Returns: TRUE if caller have proper visibility and acessibility to @field
10446  */
10447 gboolean
10448 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10449 {
10450         MonoClass *access_class = method->klass;
10451         MonoClass *member_class = field->parent;
10452         /* FIXME: check all overlapping fields */
10453         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10454         if (!can) {
10455                 MonoClass *nested = access_class->nested_in;
10456                 while (nested) {
10457                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10458                         if (can)
10459                                 break;
10460                         nested = nested->nested_in;
10461                 }
10462         }
10463
10464         if (!can)
10465                 return FALSE;
10466
10467         can = can_access_type (access_class, member_class);
10468         if (!can) {
10469                 MonoClass *nested = access_class->nested_in;
10470                 while (nested) {
10471                         can = can_access_type (nested, member_class);
10472                         if (can)
10473                                 break;
10474                         nested = nested->nested_in;
10475                 }
10476         }
10477
10478         if (!can)
10479                 return FALSE;
10480         return TRUE;
10481 }
10482
10483 /*
10484  * mono_class_can_access_class:
10485  * @source_class: The source class 
10486  * @target_class: The accessed class
10487  * 
10488  * This function returns is @target_class is visible to @source_class
10489  * 
10490  * Returns: TRUE if source have proper visibility and acessibility to target
10491  */
10492 gboolean
10493 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10494 {
10495         return can_access_type (source_class, target_class);
10496 }
10497
10498 /**
10499  * mono_type_is_valid_enum_basetype:
10500  * @type: The MonoType to check
10501  *
10502  * Returns: TRUE if the type can be used as the basetype of an enum
10503  */
10504 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10505         switch (type->type) {
10506         case MONO_TYPE_I1:
10507         case MONO_TYPE_U1:
10508         case MONO_TYPE_BOOLEAN:
10509         case MONO_TYPE_I2:
10510         case MONO_TYPE_U2:
10511         case MONO_TYPE_CHAR:
10512         case MONO_TYPE_I4:
10513         case MONO_TYPE_U4:
10514         case MONO_TYPE_I8:
10515         case MONO_TYPE_U8:
10516         case MONO_TYPE_I:
10517         case MONO_TYPE_U:
10518                 return TRUE;
10519         default:
10520                 return FALSE;
10521         }
10522 }
10523
10524 /**
10525  * mono_class_is_valid_enum:
10526  * @klass: An enum class to be validated
10527  *
10528  * This method verify the required properties an enum should have.
10529  *  
10530  * Returns: TRUE if the informed enum class is valid 
10531  *
10532  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10533  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10534  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10535  */
10536 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10537         MonoClassField * field;
10538         gpointer iter = NULL;
10539         gboolean found_base_field = FALSE;
10540
10541         g_assert (klass->enumtype);
10542         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10543         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10544                 return FALSE;
10545         }
10546
10547         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10548                 return FALSE;
10549
10550         while ((field = mono_class_get_fields (klass, &iter))) {
10551                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10552                         if (found_base_field)
10553                                 return FALSE;
10554                         found_base_field = TRUE;
10555                         if (!mono_type_is_valid_enum_basetype (field->type))
10556                                 return FALSE;
10557                 }
10558         }
10559
10560         if (!found_base_field)
10561                 return FALSE;
10562
10563         if (klass->method.count > 0) 
10564                 return FALSE;
10565
10566         return TRUE;
10567 }
10568
10569 gboolean
10570 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10571 {
10572         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10573 }
10574
10575 /*
10576  * mono_class_setup_interface_id:
10577  *
10578  * Initializes MonoClass::interface_id if required.
10579  *
10580  * LOCKING: Acquires the loader lock.
10581  */
10582 void
10583 mono_class_setup_interface_id (MonoClass *klass)
10584 {
10585         mono_loader_lock ();
10586         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10587                 klass->interface_id = mono_get_unique_iid (klass);
10588         mono_loader_unlock ();
10589 }
10590
10591 /*
10592  * mono_class_alloc_ext:
10593  *
10594  *   Allocate klass->ext if not already done.
10595  */
10596 void
10597 mono_class_alloc_ext (MonoClass *klass)
10598 {
10599         MonoClassExt *ext;
10600
10601         if (klass->ext)
10602                 return;
10603
10604         ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10605         mono_image_lock (klass->image);
10606         mono_memory_barrier ();
10607         if (!klass->ext)
10608                 klass->ext = ext;
10609         class_ext_size += sizeof (MonoClassExt);
10610         mono_image_unlock (klass->image);
10611 }
10612
10613 /*
10614  * mono_class_setup_interfaces:
10615  *
10616  *   Initialize klass->interfaces/interfaces_count.
10617  * LOCKING: Acquires the loader lock.
10618  * This function can fail the type.
10619  */
10620 void
10621 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10622 {
10623         int i, interface_count;
10624         MonoClass **interfaces;
10625
10626         mono_error_init (error);
10627
10628         if (klass->interfaces_inited)
10629                 return;
10630
10631         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10632                 MonoType *args [1];
10633
10634                 /* generic IList, ICollection, IEnumerable */
10635                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10636                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10637
10638                 args [0] = &klass->element_class->byval_arg;
10639                 interfaces [0] = mono_class_bind_generic_parameters (
10640                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10641                 if (interface_count > 1)
10642                         interfaces [1] = mono_class_bind_generic_parameters (
10643                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10644         } else if (klass->generic_class) {
10645                 MonoClass *gklass = klass->generic_class->container_class;
10646
10647                 mono_class_setup_interfaces (gklass, error);
10648                 if (!mono_error_ok (error)) {
10649                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10650                         return;
10651                 }
10652
10653                 interface_count = gklass->interface_count;
10654                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10655                 for (i = 0; i < interface_count; i++) {
10656                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10657                         if (!mono_error_ok (error)) {
10658                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10659                                 return;
10660                         }
10661                 }
10662         } else {
10663                 interface_count = 0;
10664                 interfaces = NULL;
10665         }
10666
10667         mono_image_lock (klass->image);
10668
10669         if (!klass->interfaces_inited) {
10670                 klass->interface_count = interface_count;
10671                 klass->interfaces = interfaces;
10672
10673                 mono_memory_barrier ();
10674
10675                 klass->interfaces_inited = TRUE;
10676         }
10677
10678         mono_image_unlock (klass->image);
10679 }
10680
10681 static void
10682 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10683 {
10684         MonoClass *klass = field->parent;
10685         MonoImage *image = klass->image;
10686         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10687         int field_idx = field - klass->fields;
10688
10689         mono_error_init (error);
10690
10691         if (gtd) {
10692                 MonoClassField *gfield = &gtd->fields [field_idx];
10693                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10694                 if (!mono_error_ok (error)) {
10695                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10696                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10697                 }
10698
10699                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10700                 if (!mono_error_ok (error)) {
10701                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10702                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10703                 }
10704         } else {
10705                 const char *sig;
10706                 guint32 cols [MONO_FIELD_SIZE];
10707                 MonoGenericContainer *container = NULL;
10708                 int idx = klass->field.first + field_idx;
10709
10710                 /*FIXME, in theory we do not lazy load SRE fields*/
10711                 g_assert (!image_is_dynamic (image));
10712
10713                 if (klass->generic_container) {
10714                         container = klass->generic_container;
10715                 } else if (gtd) {
10716                         container = gtd->generic_container;
10717                         g_assert (container);
10718                 }
10719
10720                 /* klass->field.first and idx points into the fieldptr table */
10721                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10722
10723                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10724                         mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10725                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10726                         return;
10727                 }
10728
10729                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10730
10731                 mono_metadata_decode_value (sig, &sig);
10732                 /* FIELD signature == 0x06 */
10733                 g_assert (*sig == 0x06);
10734
10735                 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10736                 if (!field->type) {
10737                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10738                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10739                 }
10740         }
10741 }
10742
10743 static guint32
10744 mono_field_resolve_flags (MonoClassField *field)
10745 {
10746         MonoClass *klass = field->parent;
10747         MonoImage *image = klass->image;
10748         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10749         int field_idx = field - klass->fields;
10750
10751
10752         if (gtd) {
10753                 MonoClassField *gfield = &gtd->fields [field_idx];
10754                 return mono_field_get_flags (gfield);
10755         } else {
10756                 int idx = klass->field.first + field_idx;
10757
10758                 /*FIXME, in theory we do not lazy load SRE fields*/
10759                 g_assert (!image_is_dynamic (image));
10760
10761                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10762         }
10763 }
10764
10765 /**
10766  * mono_class_setup_basic_field_info:
10767  * @class: The class to initialize
10768  *
10769  * Initializes the klass->fields array of fields.
10770  * Aquires the loader lock.
10771  */
10772 static void
10773 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10774 {
10775         mono_loader_lock ();
10776         mono_class_setup_basic_field_info (klass);
10777         mono_loader_unlock ();
10778 }
10779
10780 /**
10781  * mono_class_get_fields_lazy:
10782  * @klass: the MonoClass to act on
10783  *
10784  * This routine is an iterator routine for retrieving the fields in a class.
10785  * Only minimal information about fields are loaded. Accessors must be used
10786  * for all MonoClassField returned.
10787  *
10788  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10789  * iterate over all of the elements.  When no more values are
10790  * available, the return value is NULL.
10791  *
10792  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10793  */
10794 MonoClassField*
10795 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10796 {
10797         MonoClassField* field;
10798         if (!iter)
10799                 return NULL;
10800         if (!*iter) {
10801                 mono_class_setup_basic_field_info_locking (klass);
10802                 if (!klass->fields)
10803                         return NULL;
10804                 /* start from the first */
10805                 if (klass->field.count) {
10806                         *iter = &klass->fields [0];
10807                         return (MonoClassField *)*iter;
10808                 } else {
10809                         /* no fields */
10810                         return NULL;
10811                 }
10812         }
10813         field = (MonoClassField *)*iter;
10814         field++;
10815         if (field < &klass->fields [klass->field.count]) {
10816                 *iter = field;
10817                 return (MonoClassField *)*iter;
10818         }
10819         return NULL;
10820 }
10821
10822 char*
10823 mono_class_full_name (MonoClass *klass)
10824 {
10825         return mono_type_full_name (&klass->byval_arg);
10826 }
10827
10828 /* Declare all shared lazy type lookup functions */
10829 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)