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