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