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