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