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