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