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