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