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