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