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