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