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