* Makefile: Don't build make-map.exe.
[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  * (C) 2001-2006 Novell, Inc.
8  *
9  */
10 #include <config.h>
11 #include <glib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <signal.h>
16 #include <mono/metadata/image.h>
17 #include <mono/metadata/assembly.h>
18 #include <mono/metadata/cil-coff.h>
19 #include <mono/metadata/metadata.h>
20 #include <mono/metadata/metadata-internals.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/class-internals.h>
24 #include <mono/metadata/object.h>
25 #include <mono/metadata/appdomain.h>
26 #include <mono/metadata/mono-endian.h>
27 #include <mono/metadata/debug-helpers.h>
28 #include <mono/metadata/reflection.h>
29 #include <mono/metadata/exception.h>
30 #include <mono/metadata/security-manager.h>
31 #include <mono/os/gc_wrapper.h>
32 #include <mono/utils/mono-counters.h>
33
34 MonoStats mono_stats;
35
36 gboolean mono_print_vtable = FALSE;
37
38 /* Function supplied by the runtime to find classes by name using information from the AOT file */
39 static MonoGetClassFromName get_class_from_name = NULL;
40
41 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
42 static void mono_class_create_generic (MonoInflatedGenericClass *gclass);
43 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
44
45 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
46 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
47
48 /*
49  * mono_class_from_typeref:
50  * @image: a MonoImage
51  * @type_token: a TypeRef token
52  *
53  * Creates the MonoClass* structure representing the type defined by
54  * the typeref token valid inside @image.
55  * Returns: the MonoClass* representing the typeref token, NULL ifcould
56  * not be loaded.
57  */
58 MonoClass *
59 mono_class_from_typeref (MonoImage *image, guint32 type_token)
60 {
61         guint32 cols [MONO_TYPEREF_SIZE];
62         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
63         guint32 idx;
64         const char *name, *nspace;
65         MonoClass *res;
66         MonoAssembly **references;
67         
68         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
69
70         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
71         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
72
73         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
74         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
75         case MONO_RESOLTION_SCOPE_MODULE:
76                 if (!idx)
77                         g_error ("null ResolutionScope not yet handled");
78                 /* a typedef in disguise */
79                 return mono_class_from_name (image, nspace, name);
80         case MONO_RESOLTION_SCOPE_MODULEREF:
81                 if (image->modules [idx-1])
82                         return mono_class_from_name (image->modules [idx - 1], nspace, name);
83                 else {
84                         char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
85                         char *human_name;
86                         
87                         human_name = mono_stringify_assembly_name (&image->assembly->aname);
88                         mono_loader_set_error_type_load (msg, human_name);
89                         g_free (msg);
90                         g_free (human_name);
91                 
92                         return NULL;
93                 }
94         case MONO_RESOLTION_SCOPE_TYPEREF: {
95                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
96                 GList *tmp;
97
98                 if (enclosing->inited) {
99                         /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
100                         for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
101                                 res = tmp->data;
102                                 if (strcmp (res->name, name) == 0)
103                                         return res;
104                         }
105                 } else {
106                         /* Don't call mono_class_init as we might've been called by it recursively */
107                         int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
108                         while (i) {
109                                 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
110                                 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
111                                 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
112
113                                 if (strcmp (nname, name) == 0)
114                                         return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
115
116                                 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
117                         }
118                 }
119                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
120                 return NULL;
121         }
122         case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
123                 break;
124         }
125
126         references = image->references;
127         if (!references [idx - 1])
128                 mono_assembly_load_reference (image, idx - 1);
129         /* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
130         g_assert (references == image->references);
131         g_assert (references [idx - 1]);
132
133         /* If the assembly did not load, register this as a type load exception */
134         if (references [idx - 1] == REFERENCE_MISSING){
135                 MonoAssemblyName aname;
136                 char *human_name;
137                 
138                 mono_assembly_get_assemblyref (image, idx - 1, &aname);
139                 human_name = mono_stringify_assembly_name (&aname);
140                 mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
141                 g_free (human_name);
142                 
143                 return NULL;
144         }
145
146         return mono_class_from_name (references [idx - 1]->image, nspace, name);
147 }
148
149 static inline MonoType*
150 dup_type (MonoType* t, const MonoType *original)
151 {
152         MonoType *r = g_new0 (MonoType, 1);
153         *r = *t;
154         r->attrs = original->attrs;
155         r->byref = original->byref;
156         if (t->type == MONO_TYPE_PTR)
157                 t->data.type = dup_type (t->data.type, original->data.type);
158         else if (t->type == MONO_TYPE_ARRAY)
159                 t->data.array = mono_dup_array_type (t->data.array);
160         else if (t->type == MONO_TYPE_FNPTR)
161                 t->data.method = mono_metadata_signature_deep_dup (t->data.method);
162         mono_stats.generics_metadata_size += sizeof (MonoType);
163         return r;
164 }
165
166 /* Copy everything mono_metadata_free_array free. */
167 MonoArrayType *
168 mono_dup_array_type (MonoArrayType *a)
169 {
170         a = g_memdup (a, sizeof (MonoArrayType));
171         if (a->sizes)
172                 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
173         if (a->lobounds)
174                 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
175         return a;
176 }
177
178 /* Copy everything mono_metadata_free_method_signature free. */
179 MonoMethodSignature*
180 mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
181 {
182         int i;
183         
184         sig = mono_metadata_signature_dup (sig);
185         
186         sig->ret = dup_type (sig->ret, sig->ret);
187         for (i = 0; i < sig->param_count; ++i)
188                 sig->params [i] = dup_type (sig->params [i], sig->params [i]);
189         
190         return sig;
191 }
192
193 static void
194 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
195 {
196         MonoAssembly *ta = klass->image->assembly;
197
198         g_string_append_printf (
199                 str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
200                 ta->aname.name,
201                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
202                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
203                 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
204 }
205
206 static void
207 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
208                             MonoTypeNameFormat format)
209 {
210         MonoClass *klass;
211         
212         switch (type->type) {
213         case MONO_TYPE_ARRAY: {
214                 int i, rank = type->data.array->rank;
215                 MonoTypeNameFormat nested_format;
216
217                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
218                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
219
220                 mono_type_get_name_recurse (
221                         &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
222                 g_string_append_c (str, '[');
223                 if (rank == 1)
224                         g_string_append_c (str, '*');
225                 for (i = 1; i < rank; i++)
226                         g_string_append_c (str, ',');
227                 g_string_append_c (str, ']');
228                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
229                         _mono_type_get_assembly_name (type->data.array->eklass, str);
230                 break;
231         }
232         case MONO_TYPE_SZARRAY: {
233                 MonoTypeNameFormat nested_format;
234
235                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
236                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
237
238                 mono_type_get_name_recurse (
239                         &type->data.klass->byval_arg, str, FALSE, nested_format);
240                 g_string_append (str, "[]");
241                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
242                         _mono_type_get_assembly_name (type->data.klass, str);
243                 break;
244         }
245         case MONO_TYPE_PTR: {
246                 MonoTypeNameFormat nested_format;
247
248                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
249                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
250
251                 mono_type_get_name_recurse (
252                         type->data.type, str, FALSE, nested_format);
253                 g_string_append (str, "*");
254                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
255                         _mono_type_get_assembly_name (type->data.klass, str);
256                 break;
257         }
258         case MONO_TYPE_VAR:
259         case MONO_TYPE_MVAR:
260                 g_assert (type->data.generic_param->name);
261                 g_string_append (str, type->data.generic_param->name);
262                 break;
263         default:
264                 klass = mono_class_from_mono_type (type);
265                 if (klass->nested_in) {
266                         mono_type_get_name_recurse (
267                                 &klass->nested_in->byval_arg, str, TRUE, format);
268                         if (format == MONO_TYPE_NAME_FORMAT_IL)
269                                 g_string_append_c (str, '.');
270                         else
271                                 g_string_append_c (str, '+');
272                 } else if (*klass->name_space) {
273                         g_string_append (str, klass->name_space);
274                         g_string_append_c (str, '.');
275                 }
276                 if (format == MONO_TYPE_NAME_FORMAT_IL) {
277                         char *s = strchr (klass->name, '`');
278                         int len = s ? s - klass->name : strlen (klass->name);
279
280                         g_string_append_len (str, klass->name, len);
281                 } else
282                         g_string_append (str, klass->name);
283                 if (is_recursed)
284                         break;
285                 if (klass->generic_class) {
286                         MonoGenericClass *gclass = klass->generic_class;
287                         MonoTypeNameFormat nested_format;
288                         int i;
289
290                         nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
291                                 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
292
293                         if (format == MONO_TYPE_NAME_FORMAT_IL)
294                                 g_string_append_c (str, '<');
295                         else
296                                 g_string_append_c (str, '[');
297                         for (i = 0; i < gclass->inst->type_argc; i++) {
298                                 MonoType *t = gclass->inst->type_argv [i];
299
300                                 if (i)
301                                         g_string_append_c (str, ',');
302                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
303                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
304                                         g_string_append_c (str, '[');
305                                 mono_type_get_name_recurse (
306                                         gclass->inst->type_argv [i], str, FALSE, nested_format);
307                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
308                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
309                                         g_string_append_c (str, ']');
310                         }
311                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
312                                 g_string_append_c (str, '>');
313                         else
314                                 g_string_append_c (str, ']');
315                 } else if (klass->generic_container &&
316                            (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
317                            (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
318                         int i;
319
320                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
321                                 g_string_append_c (str, '<');
322                         else
323                                 g_string_append_c (str, '[');
324                         for (i = 0; i < klass->generic_container->type_argc; i++) {
325                                 if (i)
326                                         g_string_append_c (str, ',');
327                                 g_string_append (str, klass->generic_container->type_params [i].name);
328                         }
329                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
330                                 g_string_append_c (str, '>');
331                         else
332                                 g_string_append_c (str, ']');
333                 }
334                 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
335                     (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
336                         _mono_type_get_assembly_name (klass, str);
337                 break;
338         }
339 }
340
341 /**
342  * mono_type_get_name:
343  * @type: a type
344  * @format: the format for the return string.
345  *
346  * 
347  * Returns: the string representation in a number of formats:
348  *
349  * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
350  * returned in the formatrequired by System.Reflection, this is the
351  * inverse of mono_reflection_parse_type ().
352  *
353  * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
354  * be used by the IL assembler.
355  *
356  * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
357  *
358  * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
359  */
360 char*
361 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
362 {
363         GString* result;
364
365         result = g_string_new ("");
366
367         mono_type_get_name_recurse (type, result, FALSE, format);
368
369         if (type->byref)
370                 g_string_append_c (result, '&');
371
372         return g_string_free (result, FALSE);
373 }
374
375 /**
376  * mono_type_get_full_name:
377  * @class: a class
378  *
379  * Returns: the string representation for type as required by System.Reflection.
380  * The inverse of mono_reflection_parse_type ().
381  */
382 char *
383 mono_type_get_full_name (MonoClass *class)
384 {
385         return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
386 }
387
388 /**
389  * mono_type_get_name:
390  * @type: a type
391  *
392  * Returns: the string representation for type as it would be represented in IL code.
393  */
394 char*
395 mono_type_get_name (MonoType *type)
396 {
397         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
398 }
399
400 /*
401  * mono_type_get_underlying_type:
402  * @type: a type
403  *
404  * Returns: the MonoType for the underlying interger type if @type
405  * is an enum, otherwise the type itself.
406  */
407 MonoType*
408 mono_type_get_underlying_type (MonoType *type)
409 {
410         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
411                 return type->data.klass->enum_basetype;
412         return type;
413 }
414
415 /*
416  * mono_class_is_open_constructed_type:
417  * @type: a type
418  *
419  * Returns TRUE if type represents a generics open constructed type
420  * (not all the type parameters required for the instantiation have
421  * been provided).
422  */
423 gboolean
424 mono_class_is_open_constructed_type (MonoType *t)
425 {
426         switch (t->type) {
427         case MONO_TYPE_VAR:
428         case MONO_TYPE_MVAR:
429                 return TRUE;
430         case MONO_TYPE_SZARRAY:
431                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
432         case MONO_TYPE_ARRAY:
433                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
434         case MONO_TYPE_PTR:
435                 return mono_class_is_open_constructed_type (t->data.type);
436         case MONO_TYPE_GENERICINST: {
437                 MonoGenericClass *gclass = t->data.generic_class;
438                 int i;
439
440                 if (mono_class_is_open_constructed_type (&gclass->container_class->byval_arg))
441                         return TRUE;
442                 for (i = 0; i < gclass->inst->type_argc; i++)
443                         if (mono_class_is_open_constructed_type (gclass->inst->type_argv [i]))
444                                 return TRUE;
445                 return FALSE;
446         }
447         default:
448                 return FALSE;
449         }
450 }
451
452 static MonoGenericClass *
453 inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
454 {
455         MonoInflatedGenericClass *igclass;
456         MonoGenericClass *ngclass, *cached;
457         MonoGenericInst *ninst;
458
459         ninst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
460         if (ninst == ogclass->inst)
461                 return ogclass;
462
463         if (ogclass->is_dynamic) {
464                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
465                 igclass = &dgclass->generic_class;
466                 ngclass = &igclass->generic_class;
467                 ngclass->is_inflated = 1;
468                 ngclass->is_dynamic = 1;
469         } else {
470                 igclass = g_new0 (MonoInflatedGenericClass, 1);
471                 ngclass = &igclass->generic_class;
472                 ngclass->is_inflated = 1;
473         }
474
475         *ngclass = *ogclass;
476
477         ngclass->inst = ninst;
478
479         igclass->klass = NULL;
480
481         ngclass->context = g_new0 (MonoGenericContext, 1);
482         ngclass->context->container = ngclass->container_class->generic_container;
483         ngclass->context->gclass = ngclass;
484
485         mono_loader_lock ();
486         cached = mono_metadata_lookup_generic_class (ngclass);
487         mono_loader_unlock ();
488         if (cached) {
489                 g_free (ngclass->context);
490                 g_free (ngclass);
491                 return cached;
492         }
493
494         return ngclass;
495 }
496
497 static MonoType*
498 inflate_generic_type (MonoType *type, MonoGenericContext *context)
499 {
500         switch (type->type) {
501         case MONO_TYPE_MVAR: {
502                 int num = type->data.generic_param->num;
503                 MonoGenericInst *inst = context->gmethod ? context->gmethod->inst : NULL;
504                 if (!inst || !inst->type_argv)
505                         return NULL;
506                 if (num >= inst->type_argc)
507                         g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
508                 return dup_type (inst->type_argv [num], type);
509         }
510         case MONO_TYPE_VAR: {
511                 int num = type->data.generic_param->num;
512                 MonoGenericInst *inst = context->gclass ? context->gclass->inst : NULL;
513                 if (!inst)
514                         return NULL;
515                 if (num >= inst->type_argc)
516                         g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
517                 return dup_type (inst->type_argv [num], type);
518         }
519         case MONO_TYPE_SZARRAY: {
520                 MonoClass *eclass = type->data.klass;
521                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
522                 if (!inflated)
523                         return NULL;
524                 nt = dup_type (type, type);
525                 nt->data.klass = mono_class_from_mono_type (inflated);
526                 return nt;
527         }
528         case MONO_TYPE_ARRAY: {
529                 MonoClass *eclass = type->data.array->eklass;
530                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
531                 if (!inflated)
532                         return NULL;
533                 nt = dup_type (type, type);
534                 nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
535                 nt->data.array->eklass = mono_class_from_mono_type (inflated);
536                 return nt;
537         }
538         case MONO_TYPE_GENERICINST: {
539                 MonoGenericClass *gclass = type->data.generic_class;
540                 MonoType *nt;
541                 if (!gclass->inst->is_open)
542                         return NULL;
543                 gclass = inflate_generic_class (gclass, context);
544                 if (gclass == type->data.generic_class)
545                         return NULL;
546                 nt = dup_type (type, type);
547                 nt->data.generic_class = gclass;
548                 return nt;
549         }
550         case MONO_TYPE_CLASS:
551         case MONO_TYPE_VALUETYPE: {
552                 MonoClass *klass = type->data.klass;
553                 MonoGenericClass *gclass;
554                 MonoType *nt;
555
556                 if (!klass->generic_container)
557                         return NULL;
558                 gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
559                 if (gclass == klass->generic_container->context.gclass)
560                         return NULL;
561                 nt = dup_type (type, type);
562                 nt->type = MONO_TYPE_GENERICINST;
563                 nt->data.generic_class = gclass;
564                 return nt;
565         }
566         default:
567                 return NULL;
568         }
569         return NULL;
570 }
571
572 MonoInflatedGenericClass*
573 mono_get_inflated_generic_class (MonoGenericClass *gclass)
574 {
575         g_assert (gclass->is_inflated);
576         mono_class_create_generic ((MonoInflatedGenericClass *) gclass);
577         return (MonoInflatedGenericClass *) gclass;
578 }
579
580 /*
581  * mono_class_inflate_generic_type:
582  * @type: a type
583  * @context: a generics context
584  *
585  * Instantiate the generic type @type, using the generics context @context.
586  *
587  * Returns: the instantiated type
588  */
589 MonoType*
590 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
591 {
592         MonoType *inflated = inflate_generic_type (type, context);
593
594         if (!inflated)
595                 return dup_type (type, type);
596
597         mono_stats.inflated_type_count++;
598         return inflated;
599 }
600
601 static MonoGenericContext *
602 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
603 {
604         MonoGenericClass *gclass = NULL;
605         MonoGenericMethod *gmethod = NULL;
606         MonoGenericContext *res;
607
608         if (context->gclass)
609                 gclass = inflate_generic_class (context->gclass, inflate_with);
610
611         if (context->gmethod) {
612                 MonoGenericInst *ninst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
613                 if (gclass == context->gclass && ninst == context->gmethod->inst) {
614                         gmethod = context->gmethod;
615                 } else {
616                         gmethod = g_new0 (MonoGenericMethod, 1);
617                         gmethod->generic_class = gclass;
618                         gmethod->container = context->container;
619                         gmethod->inst = ninst;
620                 }
621         }
622
623         if (gclass == context->gclass && gmethod == context->gmethod)
624                 return context;
625
626         res = g_new0 (MonoGenericContext, 1);
627
628         res->container = gmethod ? gmethod->container : context->container;
629         res->gclass = gclass;
630         res->gmethod = gmethod;
631
632         return res;
633 }
634
635 /*
636  * mono_class_inflate_generic_method:
637  * @method: a generic method
638  * @context: a generics context
639  *
640  * Instantiate the generic method @method using the generics context @context.
641  *
642  * Returns: the new instantiated method
643  */
644 MonoMethod *
645 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
646 {
647         return mono_class_inflate_generic_method_full (method, NULL, context);
648 }
649
650 /**
651  * mono_class_inflate_generic_method:
652  *
653  * Instantiate method @method with the generic context @context.
654  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
655  *         Use mono_get_inflated_method (), mono_method_signature () and mono_method_get_header () to get the correct values.
656  */
657 MonoMethod*
658 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
659 {
660         MonoMethod *result;
661         MonoMethodInflated *iresult;
662         MonoMethodSignature *sig;
663
664         /* The `method' has already been instantiated before -> we need to create a new context. */
665         while (method->is_inflated) {
666                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
667                 context = inflate_generic_context (imethod->context, context);
668                 if (context == imethod->context)
669                         return method;
670                 method = imethod->declaring;
671         }
672
673         if (!method->generic_container && !method->klass->generic_container)
674                 return method;
675
676         mono_stats.inflated_method_count++;
677         iresult = g_new0 (MonoMethodInflated, 1);
678
679         sig = mono_method_signature (method);
680         if (sig->pinvoke) {
681                 iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
682         } else {
683                 iresult->method.normal = *(MonoMethodNormal*)method;
684                 iresult->method.normal.header = NULL;
685         }
686
687         result = (MonoMethod *) iresult;
688         result->is_inflated = 1;
689         result->signature = NULL;
690         iresult->context = context;
691         iresult->declaring = method;
692
693         if (!klass_hint || !klass_hint->generic_class ||
694             klass_hint->generic_class->container_class != method->klass ||
695             klass_hint->generic_class->inst != context->gclass->inst)
696                 klass_hint = NULL;
697
698         if (method->klass->generic_container)
699                 result->klass = klass_hint;
700
701         if (!result->klass) {
702                 MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
703                 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
704         }
705
706         if (method->generic_container && !context->gmethod) {
707                 MonoGenericMethod *gmethod = g_memdup (method->generic_container->context.gmethod, sizeof (*gmethod));
708                 gmethod->generic_class = result->klass->generic_class;
709
710                 context = g_new0 (MonoGenericContext, 1);
711                 context->container = method->generic_container;
712                 context->gclass = result->klass->generic_class;
713                 context->gmethod = gmethod;
714
715                 iresult->context = context;
716         }
717
718         return result;
719 }
720
721 /**
722  * mono_get_inflated_method:
723  *
724  * For performance reasons, mono_class_inflate_generic_method() does not actually instantiate the
725  * method, it just "prepares" it for that.  If you really need to fully instantiate the method
726  * (including its signature and header), call this method.
727  * FIXME: Martin? this description looks completely wrong.
728  */
729 MonoMethod *
730 mono_get_inflated_method (MonoMethod *method)
731 {
732         return method;
733 }
734
735 /** 
736  * mono_class_find_enum_basetype:
737  * @class: The enum class
738  *
739  *   Determine the basetype of an enum by iterating through its fields. We do this
740  * in a separate function since it is cheaper than calling mono_class_setup_fields.
741  */
742 static MonoType*
743 mono_class_find_enum_basetype (MonoClass *class)
744 {
745         MonoImage *m = class->image; 
746         const int top = class->field.count;
747         int i;
748
749         g_assert (class->enumtype);
750
751         /*
752          * Fetch all the field information.
753          */
754         for (i = 0; i < top; i++){
755                 const char *sig;
756                 guint32 cols [MONO_FIELD_SIZE];
757                 int idx = class->field.first + i;
758                 MonoGenericContainer *container = NULL;
759                 MonoType *ftype;
760
761                 /* class->field.first and idx points into the fieldptr table */
762                 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
763                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
764                 mono_metadata_decode_value (sig, &sig);
765                 /* FIELD signature == 0x06 */
766                 g_assert (*sig == 0x06);
767                 if (class->generic_container)
768                         container = class->generic_container;
769                 else if (class->generic_class) {
770                         MonoClass *gklass = class->generic_class->container_class;
771
772                         container = gklass->generic_container;
773                         g_assert (container);
774                 }
775                 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
776                 if (!ftype)
777                         return NULL;
778                 if (class->generic_class) {
779                         ftype = mono_class_inflate_generic_type (ftype, class->generic_class->context);
780                         ftype->attrs = cols [MONO_FIELD_FLAGS];
781                 }
782
783                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
784                         return ftype;
785         }
786
787         return NULL;
788 }
789
790 /** 
791  * mono_class_setup_fields:
792  * @class: The class to initialize
793  *
794  * Initializes the class->fields.
795  * LOCKING: Assumes the loader lock is held.
796  */
797 static void
798 mono_class_setup_fields (MonoClass *class)
799 {
800         MonoImage *m = class->image; 
801         int top = class->field.count;
802         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
803         int i, blittable = TRUE;
804         guint32 real_size = 0;
805         guint32 packing_size = 0;
806         gboolean explicit_size;
807         MonoClassField *field;
808         MonoGenericContainer *container = NULL;
809         MonoClass *gklass = NULL;
810
811         if (class->size_inited)
812                 return;
813
814         if (class->generic_class) {
815                 MonoClass *gklass = class->generic_class->container_class;
816                 mono_class_setup_fields (gklass);
817                 top = gklass->field.count;
818         }
819
820         class->instance_size = 0;
821         if (!class->rank)
822                 class->sizes.class_size = 0;
823
824         if (class->parent) {
825                 /* For generic instances, class->parent might not have been initialized */
826                 mono_class_init (class->parent);
827                 if (!class->parent->size_inited)
828                         mono_class_setup_fields (class->parent);
829                 class->instance_size += class->parent->instance_size;
830                 class->min_align = class->parent->min_align;
831                 /* we use |= since it may have been set already */
832                 class->has_references |= class->parent->has_references;
833                 blittable = class->parent->blittable;
834         } else {
835                 class->instance_size = sizeof (MonoObject);
836                 class->min_align = 1;
837         }
838
839         /* Get the real size */
840         explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
841
842         if (explicit_size) {
843                 g_assert ((packing_size & 0xfffffff0) == 0);
844                 class->packing_size = packing_size;
845                 real_size += class->instance_size;
846         }
847
848         if (!top) {
849                 if (explicit_size && real_size) {
850                         class->instance_size = MAX (real_size, class->instance_size);
851                 }
852                 class->size_inited = 1;
853                 class->blittable = blittable;
854                 return;
855         }
856
857         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
858                 blittable = FALSE;
859
860         /* Prevent infinite loops if the class references itself */
861         class->size_inited = 1;
862
863         class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
864
865         if (class->generic_container) {
866                 container = class->generic_container;
867         } else if (class->generic_class) {
868                 gklass = class->generic_class->container_class;
869                 container = gklass->generic_container;
870                 g_assert (container);
871
872                 mono_class_setup_fields (gklass);
873         }
874
875         /*
876          * Fetch all the field information.
877          */
878         for (i = 0; i < top; i++){
879                 int idx = class->field.first + i;
880                 field = &class->fields [i];
881
882                 field->parent = class;
883
884                 if (class->generic_class) {
885                         MonoClassField *gfield = &gklass->fields [i];
886                         MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
887
888                         ifield->generic_type = gfield->type;
889                         field->name = gfield->name;
890                         field->generic_info = ifield;
891                         field->type = mono_class_inflate_generic_type (gfield->type, class->generic_class->context);
892                         field->type->attrs = gfield->type->attrs;
893                         if (mono_field_is_deleted (field))
894                                 continue;
895                         field->offset = gfield->offset;
896                         field->data = gfield->data;
897                 } else {
898                         guint32 rva;
899                         const char *sig;
900                         guint32 cols [MONO_FIELD_SIZE];
901
902                         /* class->field.first and idx points into the fieldptr table */
903                         mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
904                         /* The name is needed for fieldrefs */
905                         field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
906                         sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
907                         mono_metadata_decode_value (sig, &sig);
908                         /* FIELD signature == 0x06 */
909                         g_assert (*sig == 0x06);
910                         field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
911                         if (!field->type) {
912                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
913                                 break;
914                         }
915                         if (mono_field_is_deleted (field))
916                                 continue;
917                         if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
918                                 guint32 offset;
919                                 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
920                                 field->offset = offset;
921                                 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
922                                         g_warning ("%s not initialized correctly (missing field layout info for %s)",
923                                                    class->name, field->name);
924                         }
925
926                         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
927                                 mono_metadata_field_info (m, idx, NULL, &rva, NULL);
928                                 if (!rva)
929                                         g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
930                                 field->data = mono_image_rva_map (class->image, rva);
931                         }
932                 }
933
934                 /* Only do these checks if we still think this type is blittable */
935                 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
936                         if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
937                                 blittable = FALSE;
938                         } else {
939                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
940                                 if (!field_class || !field_class->blittable)
941                                         blittable = FALSE;
942                         }
943                 }
944
945                 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
946                         class->enum_basetype = field->type;
947                         class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
948                         blittable = class->element_class->blittable;
949                 }
950
951                 /* The def_value of fields is compute lazily during vtable creation */
952         }
953
954         if (class == mono_defaults.string_class)
955                 blittable = FALSE;
956
957         class->blittable = blittable;
958
959         if (class->enumtype && !class->enum_basetype) {
960                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
961                         G_BREAKPOINT ();
962         }
963         if (explicit_size && real_size) {
964                 class->instance_size = MAX (real_size, class->instance_size);
965         }
966
967         if (class->exception_type)
968                 return;
969         mono_class_layout_fields (class);
970 }
971
972 /** 
973  * mono_class_setup_fields_locking:
974  * @class: The class to initialize
975  *
976  * Initializes the class->fields array of fields.
977  * Aquires the loader lock.
978  */
979 static void
980 mono_class_setup_fields_locking (MonoClass *class)
981 {
982         mono_loader_lock ();
983         mono_class_setup_fields (class);
984         mono_loader_unlock ();
985 }
986
987 /*
988  * mono_class_has_references:
989  *
990  *   Returns whenever @klass->has_references is set, initializing it if needed.
991  * Aquires the loader lock.
992  */
993 static gboolean
994 mono_class_has_references (MonoClass *klass)
995 {
996         if (klass->init_pending) {
997                 /* Be conservative */
998                 return TRUE;
999         } else {
1000                 mono_class_init (klass);
1001
1002                 return klass->has_references;
1003         }
1004 }
1005
1006 /* useful until we keep track of gc-references in corlib etc. */
1007 #ifdef HAVE_SGEN_GC
1008 #define IS_GC_REFERENCE(t) FALSE
1009 #else
1010 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
1011 #endif
1012
1013 /*
1014  * mono_class_layout_fields:
1015  * @class: a class
1016  *
1017  * Compute the placement of fields inside an object or struct, according to
1018  * the layout rules and set the following fields in @class:
1019  *  - has_references (if the class contains instance references firled or structs that contain references)
1020  *  - has_static_refs (same, but for static fields)
1021  *  - instance_size (size of the object in memory)
1022  *  - class_size (size needed for the static fields)
1023  *  - size_inited (flag set when the instance_size is set)
1024  *
1025  * LOCKING: this is supposed to be called with the loader lock held.
1026  */
1027 void
1028 mono_class_layout_fields (MonoClass *class)
1029 {
1030         int i;
1031         const int top = class->field.count;
1032         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1033         guint32 pass, passes, real_size;
1034         gboolean gc_aware_layout = FALSE;
1035         MonoClassField *field;
1036
1037         if (class->generic_container ||
1038             (class->generic_class && class->generic_class->inst->is_open))
1039                 return;
1040
1041         /*
1042          * Enable GC aware auto layout: in this mode, reference
1043          * fields are grouped together inside objects, increasing collector 
1044          * performance.
1045          * Requires that all classes whose layout is known to native code be annotated
1046          * with [StructLayout (LayoutKind.Sequential)]
1047          * Value types have gc_aware_layout disabled by default, as per
1048          * what the default is for other runtimes.
1049          */
1050          /* corlib is missing [StructLayout] directives in many places */
1051         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1052                 if (class->image != mono_defaults.corlib &&
1053                         class->byval_arg.type != MONO_TYPE_VALUETYPE)
1054                         gc_aware_layout = TRUE;
1055         }
1056
1057         /* Compute klass->has_references */
1058         /* 
1059          * Process non-static fields first, since static fields might recursively
1060          * refer to the class itself.
1061          */
1062         for (i = 0; i < top; i++) {
1063                 MonoType *ftype;
1064
1065                 field = &class->fields [i];
1066
1067                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1068                         ftype = mono_type_get_underlying_type (field->type);
1069                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1070                                 class->has_references = TRUE;
1071                 }
1072         }
1073
1074         for (i = 0; i < top; i++) {
1075                 MonoType *ftype;
1076
1077                 field = &class->fields [i];
1078
1079                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1080                         ftype = mono_type_get_underlying_type (field->type);
1081                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1082                                 class->has_static_refs = TRUE;
1083                 }
1084         }
1085
1086         for (i = 0; i < top; i++) {
1087                 MonoType *ftype;
1088
1089                 field = &class->fields [i];
1090
1091                 ftype = mono_type_get_underlying_type (field->type);
1092                 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1093                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1094                                 class->has_static_refs = TRUE;
1095                         else
1096                                 class->has_references = TRUE;
1097                 }
1098         }
1099
1100         /*
1101          * Compute field layout and total size (not considering static fields)
1102          */
1103
1104         switch (layout) {
1105         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1106         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1107
1108                 if (gc_aware_layout)
1109                         passes = 2;
1110                 else
1111                         passes = 1;
1112
1113                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1114                         passes = 1;
1115
1116                 if (class->parent)
1117                         real_size = class->parent->instance_size;
1118                 else
1119                         real_size = sizeof (MonoObject);
1120
1121                 for (pass = 0; pass < passes; ++pass) {
1122                         for (i = 0; i < top; i++){
1123                                 guint32 size, align;
1124
1125                                 field = &class->fields [i];
1126
1127                                 if (mono_field_is_deleted (field))
1128                                         continue;
1129                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1130                                         continue;
1131
1132                                 if (gc_aware_layout) {
1133                                         /* 
1134                                          * We process fields with reference type in the first pass,
1135                                          * and fields with non-reference type in the second pass.
1136                                          * We use IS_POINTER instead of IS_REFERENCE because in
1137                                          * some internal structures, we store GC_MALLOCed memory
1138                                          * in IntPtr fields...
1139                                          */
1140                                         if (MONO_TYPE_IS_POINTER (field->type)) {
1141                                                 if (pass == 1)
1142                                                         continue;
1143                                         } else {
1144                                                 if (pass == 0)
1145                                                         continue;
1146                                         }
1147                                 }
1148
1149                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1150                                         (strcmp (field->name, "$PRIVATE$") == 0)) {
1151                                         /* This field is a hack inserted by MCS to empty structures */
1152                                         continue;
1153                                 }
1154
1155                                 size = mono_type_size (field->type, &align);
1156                         
1157                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1158                                 align = class->packing_size ? MIN (class->packing_size, align): align;
1159                                 class->min_align = MAX (align, class->min_align);
1160                                 field->offset = real_size;
1161                                 field->offset += align - 1;
1162                                 field->offset &= ~(align - 1);
1163                                 real_size = field->offset + size;
1164                         }
1165
1166                         class->instance_size = MAX (real_size, class->instance_size);
1167        
1168                         if (class->instance_size & (class->min_align - 1)) {
1169                                 class->instance_size += class->min_align - 1;
1170                                 class->instance_size &= ~(class->min_align - 1);
1171                         }
1172                 }
1173                 break;
1174         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1175                 real_size = 0;
1176                 for (i = 0; i < top; i++) {
1177                         guint32 size, align;
1178
1179                         field = &class->fields [i];
1180
1181                         /*
1182                          * There must be info about all the fields in a type if it
1183                          * uses explicit layout.
1184                          */
1185
1186                         if (mono_field_is_deleted (field))
1187                                 continue;
1188                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1189                                 continue;
1190
1191                         size = mono_type_size (field->type, &align);
1192                         
1193                         /*
1194                          * When we get here, field->offset is already set by the
1195                          * loader (for either runtime fields or fields loaded from metadata).
1196                          * The offset is from the start of the object: this works for both
1197                          * classes and valuetypes.
1198                          */
1199                         field->offset += sizeof (MonoObject);
1200
1201                         /*
1202                          * Calc max size.
1203                          */
1204                         real_size = MAX (real_size, size + field->offset);
1205                 }
1206                 class->instance_size = MAX (real_size, class->instance_size);
1207                 break;
1208         }
1209
1210         if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1211                 /*
1212                  * For small structs, set min_align to at least the struct size, since the
1213                  * JIT memset/memcpy code assumes this and generates unaligned accesses
1214                  * otherwise. See #78990 for a testcase.
1215                  */
1216                 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1217                         class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1218         }
1219
1220         class->size_inited = 1;
1221
1222         /*
1223          * Compute static field layout and size
1224          */
1225         for (i = 0; i < top; i++){
1226                 guint32 size, align;
1227
1228                 field = &class->fields [i];
1229                         
1230                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1231                         continue;
1232                 if (mono_field_is_deleted (field))
1233                         continue;
1234
1235                 size = mono_type_size (field->type, &align);
1236                 field->offset = class->sizes.class_size;
1237                 field->offset += align - 1;
1238                 field->offset &= ~(align - 1);
1239                 class->sizes.class_size = field->offset + size;
1240         }
1241 }
1242
1243 /*
1244  * mono_class_setup_methods:
1245  * @class: a class
1246  *
1247  *   Initializes the 'methods' array in the klass.
1248  * Calling this method should be avoided if possible since it allocates a lot 
1249  * of long-living MonoMethod structures.
1250  * Methods belonging to an interface are assigned a sequential slot starting
1251  * from 0.
1252  */
1253 void
1254 mono_class_setup_methods (MonoClass *class)
1255 {
1256         int i;
1257         MonoMethod **methods;
1258
1259         if (class->methods)
1260                 return;
1261
1262         mono_loader_lock ();
1263
1264         if (class->methods) {
1265                 mono_loader_unlock ();
1266                 return;
1267         }
1268
1269         //printf ("INIT: %s.%s\n", class->name_space, class->name);
1270
1271         if (!class->methods) {
1272                 methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
1273                 for (i = 0; i < class->method.count; ++i) {
1274                         int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
1275                         methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
1276                 }
1277         }
1278
1279         if (MONO_CLASS_IS_INTERFACE (class))
1280                 for (i = 0; i < class->method.count; ++i)
1281                         methods [i]->slot = i;
1282
1283         /* Leave this assignment as the last op in this function */
1284         class->methods = methods;
1285
1286         mono_loader_unlock ();
1287 }
1288
1289
1290 static void
1291 mono_class_setup_properties (MonoClass *class)
1292 {
1293         guint startm, endm, i, j;
1294         guint32 cols [MONO_PROPERTY_SIZE];
1295         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1296         MonoProperty *properties;
1297         guint32 last;
1298
1299         if (class->properties)
1300                 return;
1301
1302         mono_loader_lock ();
1303
1304         if (class->properties) {
1305                 mono_loader_unlock ();
1306                 return;
1307         }
1308
1309         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1310         class->property.count = last - class->property.first;
1311
1312         if (class->property.count)
1313                 mono_class_setup_methods (class);
1314
1315         properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
1316         for (i = class->property.first; i < last; ++i) {
1317                 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
1318                 properties [i - class->property.first].parent = class;
1319                 properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
1320                 properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
1321
1322                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
1323                 for (j = startm; j < endm; ++j) {
1324                         MonoMethod *method;
1325
1326                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1327
1328                         if (class->image->uncompressed_metadata)
1329                                 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
1330                                 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
1331                         else
1332                                 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1333
1334                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1335                         case METHOD_SEMANTIC_SETTER:
1336                                 properties [i - class->property.first].set = method;
1337                                 break;
1338                         case METHOD_SEMANTIC_GETTER:
1339                                 properties [i - class->property.first].get = method;
1340                                 break;
1341                         default:
1342                                 break;
1343                         }
1344                 }
1345         }
1346
1347         /* Leave this assignment as the last op in the function */
1348         class->properties = properties;
1349
1350         mono_loader_unlock ();
1351 }
1352
1353 /*
1354  * LOCKING: assumes the loader lock is held.
1355  */
1356 static void
1357 inflate_event (MonoClass *class, MonoEvent *event, MonoInflatedGenericClass *gclass)
1358 {
1359         event->parent = class;
1360
1361         if (event->add) {
1362                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1363                         event->add, class, gclass->generic_class.context);
1364
1365                 event->add = mono_get_inflated_method (inflated);
1366         }
1367
1368         if (event->remove) {
1369                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1370                         event->remove, class, gclass->generic_class.context);
1371
1372                 event->remove = mono_get_inflated_method (inflated);
1373         }
1374
1375         if (event->raise) {
1376                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1377                         event->raise, class, gclass->generic_class.context);
1378
1379                 event->raise = mono_get_inflated_method (inflated);
1380         }
1381
1382         if (event->other) {
1383                 MonoMethod **om = event->other;
1384                 int count = 0;
1385                 while (*om) {
1386                         count++;
1387                         om++;
1388                 }
1389                 om = event->other;
1390                 event->other = g_new0 (MonoMethod*, count + 1);
1391                 count = 0;
1392                 while (*om) {
1393                         MonoMethod *inflated = mono_class_inflate_generic_method_full (
1394                                 *om, class, gclass->generic_class.context);
1395
1396                         event->other [count++] = mono_get_inflated_method (inflated);
1397                         om++;
1398                 }
1399         }
1400 }
1401
1402 static void
1403 mono_class_setup_events (MonoClass *class)
1404 {
1405         guint startm, endm, i, j;
1406         guint32 cols [MONO_EVENT_SIZE];
1407         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1408         guint32 last;
1409         MonoEvent *events;
1410
1411         if (class->events)
1412                 return;
1413
1414         mono_loader_lock ();
1415
1416         if (class->events) {
1417                 mono_loader_unlock ();
1418                 return;
1419         }
1420
1421         if (class->generic_class) {
1422                 MonoInflatedGenericClass *gclass;
1423                 MonoClass *gklass;
1424
1425                 gclass = mono_get_inflated_generic_class (class->generic_class);
1426                 gklass = gclass->generic_class.container_class;
1427
1428                 mono_class_setup_events (gklass);
1429                 class->event = gklass->event;
1430
1431                 class->events = g_new0 (MonoEvent, class->event.count);
1432
1433                 for (i = 0; i < class->event.count; i++) {
1434                         class->events [i] = gklass->events [i];
1435                         inflate_event (class, &class->events [i], gclass);
1436                 }
1437
1438                 mono_loader_unlock ();
1439                 return;
1440         }
1441
1442         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1443         class->event.count = last - class->event.first;
1444
1445         if (class->event.count)
1446                 mono_class_setup_methods (class);
1447
1448         events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
1449         for (i = class->event.first; i < last; ++i) {
1450                 MonoEvent *event = &events [i - class->event.first];
1451
1452                 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
1453                 event->parent = class;
1454                 event->attrs = cols [MONO_EVENT_FLAGS];
1455                 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
1456
1457                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
1458                 for (j = startm; j < endm; ++j) {
1459                         MonoMethod *method;
1460
1461                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1462
1463                         if (class->image->uncompressed_metadata)
1464                                 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
1465                                 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
1466                         else
1467                                 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1468
1469                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1470                         case METHOD_SEMANTIC_ADD_ON:
1471                                 event->add = method;
1472                                 break;
1473                         case METHOD_SEMANTIC_REMOVE_ON:
1474                                 event->remove = method;
1475                                 break;
1476                         case METHOD_SEMANTIC_FIRE:
1477                                 event->raise = method;
1478                                 break;
1479                         case METHOD_SEMANTIC_OTHER: {
1480                                 int n = 0;
1481
1482                                 if (event->other == NULL) {
1483                                         event->other = g_new0 (MonoMethod*, 2);
1484                                 } else {
1485                                         while (event->other [n])
1486                                                 n++;
1487                                         event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
1488                                 }
1489                                 event->other [n] = method;
1490                                 /* NULL terminated */
1491                                 event->other [n + 1] = NULL;
1492                                 break;
1493                         }
1494                         default:
1495                                 break;
1496                         }
1497                 }
1498         }
1499         /* Leave this assignment as the last op in the function */
1500         class->events = events;
1501
1502         mono_loader_unlock ();
1503 }
1504
1505 /*
1506  * Global pool of interface IDs, represented as a bitset.
1507  * LOCKING: this is supposed to be accessed with the loader lock held.
1508  */
1509 static MonoBitSet *global_interface_bitset = NULL;
1510
1511 /*
1512  * mono_unload_interface_ids:
1513  * @bitset: bit set of interface IDs
1514  *
1515  * When an image is unloaded, the interface IDs associated with
1516  * the image are put back in the global pool of IDs so the numbers
1517  * can be reused.
1518  */
1519 void
1520 mono_unload_interface_ids (MonoBitSet *bitset)
1521 {
1522         mono_loader_lock ();
1523         mono_bitset_sub (global_interface_bitset, bitset);
1524         mono_loader_unlock ();
1525 }
1526
1527 /*
1528  * mono_get_unique_iid:
1529  * @class: interface
1530  *
1531  * Assign a unique integer ID to the interface represented by @class.
1532  * The ID will positive and as small as possible.
1533  * LOCKING: this is supposed to be called with the loader lock held.
1534  * Returns: the new ID.
1535  */
1536 static guint
1537 mono_get_unique_iid (MonoClass *class)
1538 {
1539         int iid;
1540         
1541         g_assert (MONO_CLASS_IS_INTERFACE (class));
1542
1543         if (!global_interface_bitset) {
1544                 global_interface_bitset = mono_bitset_new (128, 0);
1545         }
1546
1547         iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
1548         if (iid < 0) {
1549                 int old_size = mono_bitset_size (global_interface_bitset);
1550                 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
1551                 mono_bitset_free (global_interface_bitset);
1552                 global_interface_bitset = new_set;
1553                 iid = old_size;
1554         }
1555         mono_bitset_set (global_interface_bitset, iid);
1556         /* set the bit also in the per-image set */
1557         if (class->image->interface_bitset) {
1558                 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
1559                         MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
1560                         mono_bitset_free (class->image->interface_bitset);
1561                         class->image->interface_bitset = new_set;
1562                 }
1563         } else {
1564                 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
1565         }
1566         mono_bitset_set (class->image->interface_bitset, iid);
1567
1568         if (mono_print_vtable) {
1569                 int generic_id;
1570                 char *type_name = mono_type_full_name (&class->byval_arg);
1571                 if (class->generic_class && !class->generic_class->inst->is_open) {
1572                         generic_id = class->generic_class->inst->id;
1573                         g_assert (generic_id != 0);
1574                 } else {
1575                         generic_id = 0;
1576                 }
1577                 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
1578                 g_free (type_name);
1579         }
1580
1581         g_assert (iid <= 65535);
1582         return iid;
1583 }
1584
1585 static void
1586 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
1587 {
1588         int i;
1589         MonoClass *ic;
1590         
1591         for (i = 0; i < klass->interface_count; i++) {
1592                 ic = klass->interfaces [i];
1593
1594                 if (*res == NULL)
1595                         *res = g_ptr_array_new ();
1596                 g_ptr_array_add (*res, ic);
1597                 mono_class_init (ic);
1598
1599                 collect_implemented_interfaces_aux (ic, res);
1600         }
1601 }
1602
1603 GPtrArray*
1604 mono_class_get_implemented_interfaces (MonoClass *klass)
1605 {
1606         GPtrArray *res = NULL;
1607
1608         collect_implemented_interfaces_aux (klass, &res);
1609         return res;
1610 }
1611
1612 typedef struct _IOffsetInfo IOffsetInfo;
1613 struct _IOffsetInfo {
1614         IOffsetInfo *next;
1615         int size;
1616         int next_free;
1617         int data [MONO_ZERO_LEN_ARRAY];
1618 };
1619
1620 static IOffsetInfo *cached_offset_info = NULL;
1621 static int next_offset_info_size = 128;
1622
1623 static int*
1624 cache_interface_offsets (int max_iid, int *data)
1625 {
1626         IOffsetInfo *cached_info;
1627         int *cached;
1628         int new_size;
1629         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1630                 cached = cached_info->data;
1631                 while (cached < cached_info->data + cached_info->size && *cached) {
1632                         if (*cached == max_iid) {
1633                                 int i, matched = TRUE;
1634                                 cached++;
1635                                 for (i = 0; i < max_iid; ++i) {
1636                                         if (cached [i] != data [i]) {
1637                                                 matched = FALSE;
1638                                                 break;
1639                                         }
1640                                 }
1641                                 if (matched)
1642                                         return cached;
1643                                 cached += max_iid;
1644                         } else {
1645                                 cached += *cached + 1;
1646                         }
1647                 }
1648         }
1649         /* find a free slot */
1650         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1651                 if (cached_info->size - cached_info->next_free >= max_iid + 1) {
1652                         cached = &cached_info->data [cached_info->next_free];
1653                         *cached++ = max_iid;
1654                         memcpy (cached, data, max_iid * sizeof (int));
1655                         cached_info->next_free += max_iid + 1;
1656                         return cached;
1657                 }
1658         }
1659         /* allocate a new chunk */
1660         if (max_iid + 1 < next_offset_info_size) {
1661                 new_size = next_offset_info_size;
1662                 if (next_offset_info_size < 4096)
1663                         next_offset_info_size += next_offset_info_size >> 2;
1664         } else {
1665                 new_size = max_iid + 1;
1666         }
1667         cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
1668         cached_info->size = new_size;
1669         /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
1670         cached = &cached_info->data [0];
1671         *cached++ = max_iid;
1672         memcpy (cached, data, max_iid * sizeof (int));
1673         cached_info->next_free += max_iid + 1;
1674         cached_info->next = cached_offset_info;
1675         cached_offset_info = cached_info;
1676         return cached;
1677 }
1678
1679 /*
1680  * LOCKING: this is supposed to be called with the loader lock held.
1681  */
1682 static int
1683 setup_interface_offsets (MonoClass *class, int cur_slot)
1684 {
1685         MonoClass *k, *ic;
1686         int i, max_iid;
1687         int *cached_data;
1688         GPtrArray *ifaces;
1689
1690         /* compute maximum number of slots and maximum interface id */
1691         max_iid = 0;
1692         for (k = class; k ; k = k->parent) {
1693                 for (i = 0; i < k->interface_count; i++) {
1694                         ic = k->interfaces [i];
1695
1696                         if (!ic->inited)
1697                                 mono_class_init (ic);
1698
1699                         if (max_iid < ic->interface_id)
1700                                 max_iid = ic->interface_id;
1701                 }
1702                 ifaces = mono_class_get_implemented_interfaces (k);
1703                 if (ifaces) {
1704                         for (i = 0; i < ifaces->len; ++i) {
1705                                 ic = g_ptr_array_index (ifaces, i);
1706                                 if (max_iid < ic->interface_id)
1707                                         max_iid = ic->interface_id;
1708                         }
1709                         g_ptr_array_free (ifaces, TRUE);
1710                 }
1711         }
1712
1713         if (MONO_CLASS_IS_INTERFACE (class)) {
1714                 if (max_iid < class->interface_id)
1715                         max_iid = class->interface_id;
1716         }
1717         class->max_interface_id = max_iid;
1718         /* compute vtable offset for interfaces */
1719         class->interface_offsets = g_malloc (sizeof (int) * (max_iid + 1));
1720
1721         for (i = 0; i <= max_iid; i++)
1722                 class->interface_offsets [i] = -1;
1723
1724         ifaces = mono_class_get_implemented_interfaces (class);
1725         if (ifaces) {
1726                 for (i = 0; i < ifaces->len; ++i) {
1727                         ic = g_ptr_array_index (ifaces, i);
1728                         class->interface_offsets [ic->interface_id] = cur_slot;
1729                         cur_slot += ic->method.count;
1730                 }
1731                 g_ptr_array_free (ifaces, TRUE);
1732         }
1733
1734         for (k = class->parent; k ; k = k->parent) {
1735                 ifaces = mono_class_get_implemented_interfaces (k);
1736                 if (ifaces) {
1737                         for (i = 0; i < ifaces->len; ++i) {
1738                                 ic = g_ptr_array_index (ifaces, i);
1739
1740                                 if (class->interface_offsets [ic->interface_id] == -1) {
1741                                         int io = k->interface_offsets [ic->interface_id];
1742
1743                                         g_assert (io >= 0);
1744
1745                                         class->interface_offsets [ic->interface_id] = io;
1746                                 }
1747                         }
1748                         g_ptr_array_free (ifaces, TRUE);
1749                 }
1750         }
1751
1752         if (MONO_CLASS_IS_INTERFACE (class))
1753                 class->interface_offsets [class->interface_id] = cur_slot;
1754
1755         cached_data = cache_interface_offsets (max_iid + 1, class->interface_offsets);
1756         g_free (class->interface_offsets);
1757         class->interface_offsets = cached_data;
1758
1759         return cur_slot;
1760 }
1761
1762 /*
1763  * Setup interface offsets for interfaces. Used by Ref.Emit.
1764  */
1765 void
1766 mono_class_setup_interface_offsets (MonoClass *class)
1767 {
1768         mono_loader_lock ();
1769
1770         setup_interface_offsets (class, 0);
1771
1772         mono_loader_unlock ();
1773 }
1774
1775 void
1776 mono_class_setup_vtable (MonoClass *class)
1777 {
1778         MonoMethod **overrides;
1779         MonoGenericContext *context;
1780         guint32 type_token;
1781         int onum = 0;
1782         gboolean ok = TRUE;
1783
1784         if (class->vtable)
1785                 return;
1786
1787         mono_class_setup_methods (class);
1788
1789         if (MONO_CLASS_IS_INTERFACE (class))
1790                 return;
1791
1792         mono_loader_lock ();
1793
1794         if (class->vtable) {
1795                 mono_loader_unlock ();
1796                 return;
1797         }
1798
1799         mono_stats.generic_vtable_count ++;
1800
1801         if (class->generic_class) {
1802                 context = class->generic_class->context;
1803                 type_token = class->generic_class->container_class->type_token;
1804         } else {
1805                 context = (MonoGenericContext *) class->generic_container;              
1806                 type_token = class->type_token;
1807         }
1808
1809         if (class->image->dynamic)
1810                 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
1811         else {
1812                 /* The following call fails if there are missing methods in the type */
1813                 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
1814         }
1815
1816         if (ok)
1817                 mono_class_setup_vtable_general (class, overrides, onum);
1818                 
1819         g_free (overrides);
1820
1821         mono_loader_unlock ();
1822
1823         return;
1824 }
1825
1826 /*
1827  * LOCKING: this is supposed to be called with the loader lock held.
1828  */
1829 void
1830 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum)
1831 {
1832         MonoClass *k, *ic;
1833         MonoMethod **vtable;
1834         int i, max_vtsize = 0, max_iid, cur_slot = 0;
1835         GPtrArray *ifaces, *pifaces = NULL;
1836         GHashTable *override_map = NULL;
1837         gboolean security_enabled = mono_is_security_manager_active ();
1838
1839         if (class->vtable)
1840                 return;
1841
1842         ifaces = mono_class_get_implemented_interfaces (class);
1843         if (ifaces) {
1844                 for (i = 0; i < ifaces->len; i++) {
1845                         MonoClass *ic = g_ptr_array_index (ifaces, i);
1846                         max_vtsize += ic->method.count;
1847                 }
1848                 g_ptr_array_free (ifaces, TRUE);
1849         }
1850         
1851         if (class->parent) {
1852                 mono_class_init (class->parent);
1853                 mono_class_setup_vtable (class->parent);
1854                 max_vtsize += class->parent->vtable_size;
1855                 cur_slot = class->parent->vtable_size;
1856         }
1857
1858         max_vtsize += class->method.count;
1859
1860         vtable = alloca (sizeof (gpointer) * max_vtsize);
1861         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
1862
1863         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
1864
1865         cur_slot = setup_interface_offsets (class, cur_slot);
1866         max_iid = class->max_interface_id;
1867
1868         if (class->parent && class->parent->vtable_size)
1869                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
1870
1871         /* override interface methods */
1872         for (i = 0; i < onum; i++) {
1873                 MonoMethod *decl = overrides [i*2];
1874                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
1875                         int dslot;
1876                         mono_class_setup_methods (decl->klass);
1877                         g_assert (decl->slot != -1);
1878                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
1879                         vtable [dslot] = overrides [i*2 + 1];
1880                         vtable [dslot]->slot = dslot;
1881                         if (!override_map)
1882                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1883
1884                         g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
1885                 }
1886         }
1887
1888         for (k = class; k ; k = k->parent) {
1889                 int nifaces = 0;
1890
1891                 ifaces = mono_class_get_implemented_interfaces (k);
1892                 if (ifaces) {
1893                         nifaces = ifaces->len;
1894                         if (k->generic_class) {
1895                                 pifaces = mono_class_get_implemented_interfaces (
1896                                         k->generic_class->container_class);
1897                                 g_assert (pifaces && (pifaces->len == nifaces));
1898                         }
1899                 }
1900                 for (i = 0; i < nifaces; i++) {
1901                         MonoClass *pic = NULL;
1902                         int j, l, io;
1903
1904                         ic = g_ptr_array_index (ifaces, i);
1905                         if (pifaces)
1906                                 pic = g_ptr_array_index (pifaces, i);
1907                         g_assert (ic->interface_id <= k->max_interface_id);
1908                         io = k->interface_offsets [ic->interface_id];
1909
1910                         g_assert (io >= 0);
1911                         g_assert (io <= max_vtsize);
1912
1913                         if (k == class) {
1914                                 mono_class_setup_methods (ic);
1915                                 for (l = 0; l < ic->method.count; l++) {
1916                                         MonoMethod *im = ic->methods [l];                                               
1917
1918                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1919                                                 continue;
1920
1921                                         for (j = 0; j < class->method.count; ++j) {
1922                                                 MonoMethod *cm = class->methods [j];
1923                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1924                                                     !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
1925                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
1926                                                         continue;
1927                                                 if (!strcmp(cm->name, im->name) && 
1928                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1929
1930                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1931                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1932                                                                 mono_secman_inheritancedemand_method (cm, im);
1933                                                         }
1934
1935                                                         g_assert (io + l <= max_vtsize);
1936                                                         vtable [io + l] = cm;
1937                                                 }
1938                                         }
1939                                 }
1940                         } else {
1941                                 /* already implemented */
1942                                 if (io >= k->vtable_size)
1943                                         continue;
1944                         }
1945                                 
1946                         for (l = 0; l < ic->method.count; l++) {
1947                                 MonoMethod *im = ic->methods [l];                                               
1948                                 MonoClass *k1;
1949
1950                                 g_assert (io + l <= max_vtsize);
1951
1952                                 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1953                                         continue;
1954                                         
1955                                 for (k1 = class; k1; k1 = k1->parent) {
1956                                         for (j = 0; j < k1->method.count; ++j) {
1957                                                 MonoMethod *cm = k1->methods [j];
1958
1959                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1960                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
1961                                                         continue;
1962                                                 
1963                                                 if (!strcmp(cm->name, im->name) && 
1964                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1965
1966                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1967                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1968                                                                 mono_secman_inheritancedemand_method (cm, im);
1969                                                         }
1970
1971                                                         g_assert (io + l <= max_vtsize);
1972                                                         vtable [io + l] = cm;
1973                                                         break;
1974                                                 }
1975                                                 
1976                                         }
1977                                         g_assert (io + l <= max_vtsize);
1978                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1979                                                 break;
1980                                 }
1981                         }
1982
1983                         for (l = 0; l < ic->method.count; l++) {
1984                                 MonoMethod *im = ic->methods [l];                                               
1985                                 char *qname, *fqname, *cname, *the_cname;
1986                                 MonoClass *k1;
1987                                 
1988                                 if (vtable [io + l])
1989                                         continue;
1990
1991                                 if (pic) {
1992                                         the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
1993                                         cname = the_cname;
1994                                 } else {
1995                                         the_cname = NULL;
1996                                         cname = (char*)ic->name;
1997                                 }
1998                                         
1999                                 qname = g_strconcat (cname, ".", im->name, NULL);
2000                                 if (ic->name_space && ic->name_space [0])
2001                                         fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
2002                                 else
2003                                         fqname = NULL;
2004
2005                                 for (k1 = class; k1; k1 = k1->parent) {
2006                                         for (j = 0; j < k1->method.count; ++j) {
2007                                                 MonoMethod *cm = k1->methods [j];
2008
2009                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2010                                                         continue;
2011
2012                                                 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
2013                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
2014
2015                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
2016                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2017                                                                 mono_secman_inheritancedemand_method (cm, im);
2018                                                         }
2019
2020                                                         g_assert (io + l <= max_vtsize);
2021                                                         vtable [io + l] = cm;
2022                                                         break;
2023                                                 }
2024                                         }
2025                                 }
2026                                 g_free (the_cname);
2027                                 g_free (qname);
2028                                 g_free (fqname);
2029                         }
2030
2031                         
2032                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
2033                                 for (l = 0; l < ic->method.count; l++) {
2034                                         char *msig;
2035                                         MonoMethod *im = ic->methods [l];
2036                                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
2037                                                         continue;
2038                                         g_assert (io + l <= max_vtsize);
2039
2040                                         /* 
2041                                          * If one of our parents already implements this interface
2042                                          * we can inherit the implementation.
2043                                          */
2044                                         if (!(vtable [io + l])) {
2045                                                 MonoClass *parent = class->parent;
2046                                                 
2047                                                 for (; parent; parent = parent->parent) {
2048                                                         if ((ic->interface_id <= parent->max_interface_id) && 
2049                                                                         (parent->interface_offsets [ic->interface_id] != -1) &&
2050                                                                         parent->vtable) {
2051                                                                 vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
2052                                                         }
2053                                                 }
2054                                         }
2055
2056                                         if (!(vtable [io + l])) {
2057                                                 for (j = 0; j < onum; ++j) {
2058                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
2059                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
2060                                                 }
2061                                                 msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
2062                                                 printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
2063                                                         mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space, class->name);
2064                                                 g_free (msig);
2065                                                 for (j = 0; j < class->method.count; ++j) {
2066                                                         MonoMethod *cm = class->methods [j];
2067                                                         msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
2068                                                         
2069                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
2070                                                         g_free (msig);
2071                                                 }
2072                                                 g_assert_not_reached ();
2073                                         }
2074                                 }
2075                         }
2076                 
2077                         for (l = 0; l < ic->method.count; l++) {
2078                                 MonoMethod *im = vtable [io + l];
2079
2080                                 if (im) {
2081                                         g_assert (io + l <= max_vtsize);
2082                                         if (im->slot < 0) {
2083                                                 /* FIXME: why do we need this ? */
2084                                                 im->slot = io + l;
2085                                                 /* g_assert_not_reached (); */
2086                                         }
2087                                 }
2088                         }
2089                 }
2090                 if (ifaces)
2091                         g_ptr_array_free (ifaces, TRUE);
2092         } 
2093
2094         for (i = 0; i < class->method.count; ++i) {
2095                 MonoMethod *cm;
2096                
2097                 cm = class->methods [i];
2098                 
2099                 /*
2100                  * Non-virtual method have no place in the vtable.
2101                  * This also catches static methods (since they are not virtual).
2102                  */
2103                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2104                         continue;
2105                 
2106                 /*
2107                  * If the method is REUSE_SLOT, we must check in the
2108                  * base class for a method to override.
2109                  */
2110                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
2111                         int slot = -1;
2112                         for (k = class->parent; k ; k = k->parent) {
2113                                 int j;
2114                                 for (j = 0; j < k->method.count; ++j) {
2115                                         MonoMethod *m1 = k->methods [j];
2116                                         MonoMethodSignature *cmsig, *m1sig;
2117
2118                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
2119                                                 continue;
2120
2121                                         cmsig = mono_method_signature (cm);
2122                                         m1sig = mono_method_signature (m1);
2123
2124                                         if (!cmsig || !m1sig) {
2125                                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2126                                                 return;
2127                                         }
2128
2129                                         if (!strcmp(cm->name, m1->name) && 
2130                                             mono_metadata_signature_equal (cmsig, m1sig)) {
2131
2132                                                 /* CAS - SecurityAction.InheritanceDemand */
2133                                                 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2134                                                         mono_secman_inheritancedemand_method (cm, m1);
2135                                                 }
2136
2137                                                 slot = k->methods [j]->slot;
2138                                                 g_assert (cm->slot < max_vtsize);
2139                                                 if (!override_map)
2140                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
2141                                                 g_hash_table_insert (override_map, m1, cm);
2142                                                 break;
2143                                         }
2144                                 }
2145                                 if (slot >= 0) 
2146                                         break;
2147                         }
2148                         if (slot >= 0)
2149                                 cm->slot = slot;
2150                 }
2151
2152                 if (cm->slot < 0)
2153                         cm->slot = cur_slot++;
2154
2155                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
2156                         vtable [cm->slot] = cm;
2157         }
2158
2159         /* override non interface methods */
2160         for (i = 0; i < onum; i++) {
2161                 MonoMethod *decl = overrides [i*2];
2162                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
2163                         g_assert (decl->slot != -1);
2164                         vtable [decl->slot] = overrides [i*2 + 1];
2165                         overrides [i * 2 + 1]->slot = decl->slot;
2166                         if (!override_map)
2167                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
2168                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
2169                 }
2170         }
2171
2172         /*
2173          * If a method occupies more than one place in the vtable, and it is
2174          * overriden, then change the other occurances too.
2175          */
2176         if (override_map) {
2177                 for (i = 0; i < max_vtsize; ++i)
2178                         if (vtable [i]) {
2179                                 MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]);
2180                                 if (cm)
2181                                         vtable [i] = cm;
2182                         }
2183
2184                 g_hash_table_destroy (override_map);
2185         }
2186
2187         if (class->generic_class) {
2188                 MonoClass *gklass = class->generic_class->container_class;
2189
2190                 mono_class_init (gklass);
2191
2192                 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
2193         } else
2194                 class->vtable_size = cur_slot;
2195
2196         /* Try to share the vtable with our parent. */
2197         if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
2198                 class->vtable = class->parent->vtable;
2199         } else {
2200                 class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
2201                 memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
2202         }
2203
2204         if (mono_print_vtable) {
2205                 int icount = 0;
2206
2207                 for (i = 0; i <= max_iid; i++)
2208                         if (class->interface_offsets [i] != -1)
2209                                 icount++;
2210
2211                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg), 
2212                         class->vtable_size, icount); 
2213
2214                 for (i = 0; i < class->vtable_size; ++i) {
2215                         MonoMethod *cm;
2216                
2217                         cm = vtable [i];
2218                         if (cm) {
2219                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
2220                                         mono_method_full_name (cm, TRUE));
2221                         }
2222                 }
2223
2224
2225                 if (icount) {
2226                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
2227                                 class->name, max_iid);
2228         
2229                         for (i = 0; i < class->interface_count; i++) {
2230                                 ic = class->interfaces [i];
2231                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
2232                                         class->interface_offsets [ic->interface_id],
2233                                         ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2234                         }
2235
2236                         for (k = class->parent; k ; k = k->parent) {
2237                                 for (i = 0; i < k->interface_count; i++) {
2238                                         ic = k->interfaces [i]; 
2239                                         printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
2240                                                 class->interface_offsets [ic->interface_id],
2241                                                 ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2242                                 }
2243                         }
2244                 }
2245         }
2246 }
2247
2248 static MonoMethod *default_ghc = NULL;
2249 static MonoMethod *default_finalize = NULL;
2250 static int finalize_slot = -1;
2251 static int ghc_slot = -1;
2252
2253 static void
2254 initialize_object_slots (MonoClass *class)
2255 {
2256         int i;
2257         if (default_ghc)
2258                 return;
2259         if (class == mono_defaults.object_class) { 
2260                 mono_class_setup_vtable (class);                       
2261                 for (i = 0; i < class->vtable_size; ++i) {
2262                         MonoMethod *cm = class->vtable [i];
2263        
2264                         if (!strcmp (cm->name, "GetHashCode"))
2265                                 ghc_slot = i;
2266                         else if (!strcmp (cm->name, "Finalize"))
2267                                 finalize_slot = i;
2268                 }
2269
2270                 g_assert (ghc_slot > 0);
2271                 default_ghc = class->vtable [ghc_slot];
2272
2273                 g_assert (finalize_slot > 0);
2274                 default_finalize = class->vtable [finalize_slot];
2275         }
2276 }
2277
2278 static GList*
2279 g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
2280 {
2281         GList* n = mono_mempool_alloc (mp, sizeof (GList));
2282         n->next = l;
2283         n->prev = NULL;
2284         n->data = datum;
2285         return n;
2286 }
2287
2288 static void
2289 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
2290 {
2291         MonoGenericContext *context;
2292         int i;
2293
2294         context = g_new0 (MonoGenericContext, 1);
2295         context->container = iface->generic_class->context->container;
2296         context->gmethod = g_new0 (MonoGenericMethod, 1);
2297         context->gmethod->generic_class = iface->generic_class;
2298         context->gmethod->inst = iface->generic_class->inst;
2299
2300         for (i = 0; i < class->parent->method.count; i++) {
2301                 MonoMethod *m = class->parent->methods [i];
2302                 MonoMethod *inflated;
2303                 const char *mname, *iname;
2304                 gchar *name;
2305
2306                 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
2307                         iname = "System.Collections.Generic.ICollection`1.";
2308                         mname = m->name + 27;
2309                 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
2310                         iname = "System.Collections.Generic.IEnumerable`1.";
2311                         mname = m->name + 27;
2312                 } else if (!strncmp (m->name, "InternalArray__", 15)) {
2313                         iname = "System.Collections.Generic.IList`1.";
2314                         mname = m->name + 15;
2315                 } else {
2316                         continue;
2317                 }
2318
2319                 name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
2320                 strcpy (name, iname);
2321                 strcpy (name + strlen (iname), mname);
2322
2323                 inflated = mono_class_inflate_generic_method (m, context);
2324                 class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
2325         }
2326 }
2327
2328 /**
2329  * mono_class_init:
2330  * @class: the class to initialize
2331  *
2332  * compute the instance_size, class_size and other infos that cannot be 
2333  * computed at mono_class_get() time. Also compute a generic vtable and 
2334  * the method slot numbers. We use this infos later to create a domain
2335  * specific vtable.
2336  *
2337  * Returns TRUE on success or FALSE if there was a problem in loading
2338  * the type (incorrect assemblies, missing assemblies, methods, etc). 
2339  */
2340 gboolean
2341 mono_class_init (MonoClass *class)
2342 {
2343         int i;
2344         MonoCachedClassInfo cached_info;
2345         gboolean has_cached_info;
2346         int class_init_ok = TRUE;
2347         
2348         g_assert (class);
2349
2350         if (class->inited)
2351                 return TRUE;
2352
2353         /*g_print ("Init class %s\n", class->name);*/
2354
2355         /* We do everything inside the lock to prevent races */
2356         mono_loader_lock ();
2357
2358         if (class->inited) {
2359                 mono_loader_unlock ();
2360                 /* Somebody might have gotten in before us */
2361                 return TRUE;
2362         }
2363
2364         if (class->init_pending) {
2365                 mono_loader_unlock ();
2366                 /* this indicates a cyclic dependency */
2367                 g_error ("pending init %s.%s\n", class->name_space, class->name);
2368         }
2369
2370         class->init_pending = 1;
2371
2372         /* CAS - SecurityAction.InheritanceDemand */
2373         if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
2374                 mono_secman_inheritancedemand_class (class, class->parent);
2375         }
2376
2377         if (mono_debugger_start_class_init_func)
2378                 mono_debugger_start_class_init_func (class);
2379
2380         mono_stats.initialized_class_count++;
2381
2382         if (class->generic_class && !class->generic_class->is_dynamic) {
2383                 MonoInflatedGenericClass *gclass;
2384                 MonoClass *gklass;
2385
2386                 gclass = mono_get_inflated_generic_class (class->generic_class);
2387                 gklass = gclass->generic_class.container_class;
2388
2389                 mono_stats.generic_class_count++;
2390
2391                 class->method = gklass->method;
2392                 class->field = gklass->field;
2393
2394                 mono_class_init (gklass);
2395                 mono_class_setup_methods (gklass);
2396                 mono_class_setup_properties (gklass);
2397
2398                 if (MONO_CLASS_IS_INTERFACE (class))
2399                         class->interface_id = mono_get_unique_iid (class);
2400
2401                 g_assert (class->method.count == gklass->method.count);
2402                 class->methods = g_new0 (MonoMethod *, class->method.count);
2403
2404                 for (i = 0; i < class->method.count; i++) {
2405                         MonoMethod *inflated = mono_class_inflate_generic_method_full (
2406                                 gklass->methods [i], class, gclass->generic_class.context);
2407
2408                         class->methods [i] = mono_get_inflated_method (inflated);
2409                 }
2410
2411                 class->property = gklass->property;
2412                 class->properties = g_new0 (MonoProperty, class->property.count);
2413
2414                 for (i = 0; i < class->property.count; i++) {
2415                         MonoProperty *prop = &class->properties [i];
2416
2417                         *prop = gklass->properties [i];
2418
2419                         if (prop->get)
2420                                 prop->get = mono_class_inflate_generic_method_full (
2421                                         prop->get, class, gclass->generic_class.context);
2422                         if (prop->set)
2423                                 prop->set = mono_class_inflate_generic_method_full (
2424                                         prop->set, class, gclass->generic_class.context);
2425
2426                         prop->parent = class;
2427                 }
2428
2429                 g_assert (class->interface_count == gklass->interface_count);
2430         }
2431
2432         if (class->parent && !class->parent->inited)
2433                 mono_class_init (class->parent);
2434
2435         has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
2436
2437         if (!class->generic_class && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
2438                 i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
2439                 while (i) {
2440                         MonoClass* nclass;
2441                         guint32 cols [MONO_NESTED_CLASS_SIZE];
2442                         mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
2443                         nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
2444                         class->nested_classes = g_list_prepend_mempool (class->nested_classes, class->image->mempool, nclass);
2445
2446                         i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
2447                 }
2448         }
2449
2450         /*
2451          * Computes the size used by the fields, and their locations
2452          */
2453         if (has_cached_info) {
2454                 class->instance_size = cached_info.instance_size;
2455                 class->sizes.class_size = cached_info.class_size;
2456                 class->packing_size = cached_info.packing_size;
2457                 class->min_align = cached_info.min_align;
2458                 class->blittable = cached_info.blittable;
2459                 class->has_references = cached_info.has_references;
2460                 class->has_static_refs = cached_info.has_static_refs;
2461                 class->no_special_static_fields = cached_info.no_special_static_fields;
2462         }
2463         else
2464                 if (!class->size_inited){
2465                         mono_class_setup_fields (class);
2466                         if (class->exception_type || mono_loader_get_last_error ()){
2467                                 class_init_ok = FALSE;
2468                                 goto leave;
2469                         }
2470                 }
2471                                 
2472
2473         /* initialize method pointers */
2474         if (class->rank) {
2475                 MonoMethod *ctor;
2476                 MonoMethodSignature *sig;
2477                 int count_generic = 0, first_generic = 0;
2478
2479                 class->method.count = (class->rank > 1? 2: 1);
2480
2481                 if (class->interface_count) {
2482                         for (i = 0; i < class->parent->method.count; i++) {
2483                                 MonoMethod *m = class->parent->methods [i];
2484                                 if (!strncmp (m->name, "InternalArray__", 15))
2485                                         count_generic++;
2486                         }
2487                         first_generic = class->method.count;
2488                         class->method.count += class->interface_count * count_generic;
2489                 }
2490
2491                 sig = mono_metadata_signature_alloc (class->image, class->rank);
2492                 sig->ret = &mono_defaults.void_class->byval_arg;
2493                 sig->pinvoke = TRUE;
2494                 for (i = 0; i < class->rank; ++i)
2495                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2496
2497                 ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
2498                 ctor->klass = class;
2499                 ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2500                 ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2501                 ctor->signature = sig;
2502                 ctor->name = ".ctor";
2503                 ctor->slot = -1;
2504                 class->methods = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
2505                 class->methods [0] = ctor;
2506                 if (class->rank > 1) {
2507                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2508                         sig->ret = &mono_defaults.void_class->byval_arg;
2509                         sig->pinvoke = TRUE;
2510                         for (i = 0; i < class->rank * 2; ++i)
2511                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2512
2513                         ctor = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
2514                         ctor->klass = class;
2515                         ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2516                         ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2517                         ctor->signature = sig;
2518                         ctor->name = ".ctor";
2519                         ctor->slot = -1;
2520                         class->methods [1] = ctor;
2521                 }
2522
2523                 for (i = 0; i < class->interface_count; i++)
2524                         setup_generic_array_ifaces (class, class->interfaces [i], first_generic + i * count_generic);
2525         }
2526
2527         mono_class_setup_supertypes (class);
2528
2529         if (!default_ghc)
2530                 initialize_object_slots (class);
2531
2532         /*
2533          * If possible, avoid the creation of the generic vtable by requesting
2534          * cached info from the runtime.
2535          */
2536         if (has_cached_info) {
2537                 guint32 cur_slot = 0;
2538
2539                 class->vtable_size = cached_info.vtable_size;
2540                 class->has_finalize = cached_info.has_finalize;
2541                 class->ghcimpl = cached_info.ghcimpl;
2542                 class->has_cctor = cached_info.has_cctor;
2543
2544                 if (class->parent) {
2545                         mono_class_init (class->parent);
2546                         cur_slot = class->parent->vtable_size;
2547                 }
2548
2549                 setup_interface_offsets (class, cur_slot);
2550         }
2551         else {
2552                 mono_class_setup_vtable (class);
2553
2554                 if (class->exception_type || mono_loader_get_last_error ()){
2555                         class_init_ok = FALSE;
2556                         goto leave;
2557                 }
2558
2559                 class->ghcimpl = 1;
2560                 if (class->parent) { 
2561                         MonoMethod *cmethod = class->vtable [ghc_slot];
2562                         if (cmethod->is_inflated)
2563                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2564                         if (cmethod == default_ghc) {
2565                                 class->ghcimpl = 0;
2566                         }
2567                 }
2568
2569                 /* Object::Finalize should have empty implemenatation */
2570                 class->has_finalize = 0;
2571                 if (class->parent) { 
2572                         MonoMethod *cmethod = class->vtable [finalize_slot];
2573                         if (cmethod->is_inflated)
2574                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2575                         if (cmethod != default_finalize) {
2576                                 class->has_finalize = 1;
2577                         }
2578                 }
2579
2580                 for (i = 0; i < class->method.count; ++i) {
2581                         MonoMethod *method = class->methods [i];
2582                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
2583                                 (strcmp (".cctor", method->name) == 0)) {
2584                                 class->has_cctor = 1;
2585                                 break;
2586                         }
2587                 }
2588         }
2589
2590         if (MONO_CLASS_IS_INTERFACE (class)) {
2591                 /* 
2592                  * class->interface_offsets is needed for the castclass/isinst code, so
2593                  * we have to setup them for interfaces, too.
2594                  */
2595                 setup_interface_offsets (class, 0);
2596         }
2597
2598  leave:
2599         class->inited = 1;
2600         class->init_pending = 0;
2601
2602         mono_loader_unlock ();
2603
2604         if (mono_debugger_class_init_func)
2605                 mono_debugger_class_init_func (class);
2606
2607         return class_init_ok;
2608 }
2609
2610 /*
2611  * LOCKING: this assumes the loader lock is held
2612  */
2613 void
2614 mono_class_setup_mono_type (MonoClass *class)
2615 {
2616         const char *name = class->name;
2617         const char *nspace = class->name_space;
2618
2619         class->this_arg.byref = 1;
2620         class->this_arg.data.klass = class;
2621         class->this_arg.type = MONO_TYPE_CLASS;
2622         class->byval_arg.data.klass = class;
2623         class->byval_arg.type = MONO_TYPE_CLASS;
2624
2625         if (!strcmp (nspace, "System")) {
2626                 if (!strcmp (name, "ValueType")) {
2627                         /*
2628                          * do not set the valuetype bit for System.ValueType.
2629                          * class->valuetype = 1;
2630                          */
2631                         class->blittable = TRUE;
2632                 } else if (!strcmp (name, "Enum")) {
2633                         /*
2634                          * do not set the valuetype bit for System.Enum.
2635                          * class->valuetype = 1;
2636                          */
2637                         class->valuetype = 0;
2638                         class->enumtype = 0;
2639                 } else if (!strcmp (name, "Object")) {
2640                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
2641                 } else if (!strcmp (name, "String")) {
2642                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
2643                 } else if (!strcmp (name, "TypedReference")) {
2644                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
2645                 }
2646         }
2647         
2648         if (class->valuetype) {
2649                 int t = MONO_TYPE_VALUETYPE;
2650                 if (!strcmp (nspace, "System")) {
2651                         switch (*name) {
2652                         case 'B':
2653                                 if (!strcmp (name, "Boolean")) {
2654                                         t = MONO_TYPE_BOOLEAN;
2655                                 } else if (!strcmp(name, "Byte")) {
2656                                         t = MONO_TYPE_U1;
2657                                         class->blittable = TRUE;                                                
2658                                 }
2659                                 break;
2660                         case 'C':
2661                                 if (!strcmp (name, "Char")) {
2662                                         t = MONO_TYPE_CHAR;
2663                                 }
2664                                 break;
2665                         case 'D':
2666                                 if (!strcmp (name, "Double")) {
2667                                         t = MONO_TYPE_R8;
2668                                         class->blittable = TRUE;                                                
2669                                 }
2670                                 break;
2671                         case 'I':
2672                                 if (!strcmp (name, "Int32")) {
2673                                         t = MONO_TYPE_I4;
2674                                         class->blittable = TRUE;
2675                                 } else if (!strcmp(name, "Int16")) {
2676                                         t = MONO_TYPE_I2;
2677                                         class->blittable = TRUE;
2678                                 } else if (!strcmp(name, "Int64")) {
2679                                         t = MONO_TYPE_I8;
2680                                         class->blittable = TRUE;
2681                                 } else if (!strcmp(name, "IntPtr")) {
2682                                         t = MONO_TYPE_I;
2683                                         class->blittable = TRUE;
2684                                 }
2685                                 break;
2686                         case 'S':
2687                                 if (!strcmp (name, "Single")) {
2688                                         t = MONO_TYPE_R4;
2689                                         class->blittable = TRUE;                                                
2690                                 } else if (!strcmp(name, "SByte")) {
2691                                         t = MONO_TYPE_I1;
2692                                         class->blittable = TRUE;
2693                                 }
2694                                 break;
2695                         case 'U':
2696                                 if (!strcmp (name, "UInt32")) {
2697                                         t = MONO_TYPE_U4;
2698                                         class->blittable = TRUE;
2699                                 } else if (!strcmp(name, "UInt16")) {
2700                                         t = MONO_TYPE_U2;
2701                                         class->blittable = TRUE;
2702                                 } else if (!strcmp(name, "UInt64")) {
2703                                         t = MONO_TYPE_U8;
2704                                         class->blittable = TRUE;
2705                                 } else if (!strcmp(name, "UIntPtr")) {
2706                                         t = MONO_TYPE_U;
2707                                         class->blittable = TRUE;
2708                                 }
2709                                 break;
2710                         case 'T':
2711                                 if (!strcmp (name, "TypedReference")) {
2712                                         t = MONO_TYPE_TYPEDBYREF;
2713                                         class->blittable = TRUE;
2714                                 }
2715                                 break;
2716                         case 'V':
2717                                 if (!strcmp (name, "Void")) {
2718                                         t = MONO_TYPE_VOID;
2719                                 }
2720                                 break;
2721                         default:
2722                                 break;
2723                         }
2724                 }
2725                 class->this_arg.type = class->byval_arg.type = t;
2726         }
2727
2728         if (MONO_CLASS_IS_INTERFACE (class))
2729                 class->interface_id = mono_get_unique_iid (class);
2730
2731 }
2732
2733 /*
2734  * LOCKING: this assumes the loader lock is held
2735  */
2736 void
2737 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
2738 {
2739         gboolean system_namespace;
2740
2741         system_namespace = !strcmp (class->name_space, "System");
2742
2743         /* if root of the hierarchy */
2744         if (system_namespace && !strcmp (class->name, "Object")) {
2745                 class->parent = NULL;
2746                 class->instance_size = sizeof (MonoObject);
2747                 return;
2748         }
2749         if (!strcmp (class->name, "<Module>")) {
2750                 class->parent = NULL;
2751                 class->instance_size = 0;
2752                 return;
2753         }
2754
2755         if (!MONO_CLASS_IS_INTERFACE (class)) {
2756                 /* Imported COM Objects always derive from __ComObject. */
2757                 if (MONO_CLASS_IS_IMPORT (class)) {
2758                         if (parent == mono_defaults.object_class)
2759                                 parent = mono_defaults.com_object_class;
2760                 }
2761                 class->parent = parent;
2762
2763
2764                 if (!parent)
2765                         g_assert_not_reached (); /* FIXME */
2766
2767                 if (parent->generic_class && !parent->name) {
2768                         /*
2769                          * If the parent is a generic instance, we may get
2770                          * called before it is fully initialized, especially
2771                          * before it has its name.
2772                          */
2773                         return;
2774                 }
2775
2776                 class->marshalbyref = parent->marshalbyref;
2777                 class->contextbound  = parent->contextbound;
2778                 class->delegate  = parent->delegate;
2779                 if (MONO_CLASS_IS_IMPORT (class))
2780                         class->is_com_object = 1;
2781                 else
2782                         class->is_com_object = parent->is_com_object;
2783                 
2784                 if (system_namespace) {
2785                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
2786                                 class->marshalbyref = 1;
2787
2788                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
2789                                 class->contextbound  = 1;
2790
2791                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
2792                                 class->delegate  = 1;
2793                 }
2794
2795                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
2796                                                 (strcmp (class->parent->name_space, "System") == 0)))
2797                         class->valuetype = 1;
2798                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
2799                         class->valuetype = class->enumtype = 1;
2800                 }
2801                 /*class->enumtype = class->parent->enumtype; */
2802                 mono_class_setup_supertypes (class);
2803         } else {
2804                 class->parent = NULL;
2805         }
2806
2807 }
2808
2809 /*
2810  * mono_class_setup_supertypes:
2811  * @class: a class
2812  *
2813  * Build the data structure needed to make fast type checks work.
2814  * This currently sets two fields in @class:
2815  *  - idepth: distance between @class and System.Object in the type
2816  *    hierarchy + 1
2817  *  - supertypes: array of classes: each element has a class in the hierarchy
2818  *    starting from @class up to System.Object
2819  * 
2820  * LOCKING: this assumes the loader lock is held
2821  */
2822 void
2823 mono_class_setup_supertypes (MonoClass *class)
2824 {
2825         int ms;
2826
2827         if (class->supertypes)
2828                 return;
2829
2830         if (class->parent && !class->parent->supertypes)
2831                 mono_class_setup_supertypes (class->parent);
2832         if (class->parent)
2833                 class->idepth = class->parent->idepth + 1;
2834         else
2835                 class->idepth = 1;
2836
2837         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
2838         class->supertypes = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClass *) * ms);
2839
2840         if (class->parent) {
2841                 class->supertypes [class->idepth - 1] = class;
2842                 memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
2843         } else {
2844                 class->supertypes [0] = class;
2845         }
2846 }       
2847
2848 MonoGenericInst *
2849 mono_get_shared_generic_inst (MonoGenericContainer *container)
2850 {
2851         MonoGenericInst *nginst;
2852         int i;
2853
2854         nginst = g_new0 (MonoGenericInst, 1);
2855         nginst->type_argc = container->type_argc;
2856         nginst->type_argv = g_new0 (MonoType *, nginst->type_argc);
2857         nginst->is_reference = 1;
2858         nginst->is_open = 1;
2859
2860         for (i = 0; i < nginst->type_argc; i++) {
2861                 MonoType *t = g_new0 (MonoType, 1);
2862
2863                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2864                 t->data.generic_param = &container->type_params [i];
2865
2866                 nginst->type_argv [i] = t;
2867         }
2868
2869         return mono_metadata_lookup_generic_inst (nginst);
2870 }
2871
2872 /*
2873  * In preparation for implementing shared code.
2874  */
2875 MonoGenericClass *
2876 mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
2877 {
2878         MonoInflatedGenericClass *igclass;
2879         MonoGenericClass *gclass;
2880
2881         if (is_dynamic) {
2882                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
2883                 igclass = &dgclass->generic_class;
2884                 gclass = &igclass->generic_class;
2885                 gclass->is_inflated = 1;
2886                 gclass->is_dynamic = 1;
2887         } else {
2888                 igclass = g_new0 (MonoInflatedGenericClass, 1);
2889                 gclass = &igclass->generic_class;
2890                 gclass->is_inflated = 1;
2891         }
2892
2893         gclass->context = &container->context;
2894         gclass->container_class = container->klass;
2895         gclass->inst = mono_get_shared_generic_inst (container);
2896
2897         if (!is_dynamic) {
2898                 MonoGenericClass *cached = mono_metadata_lookup_generic_class (gclass);
2899
2900                 if (cached) {
2901                         g_free (gclass);
2902                         return cached;
2903                 }
2904         }
2905
2906         igclass->klass = container->klass;
2907
2908         return gclass;
2909 }
2910
2911 /**
2912  * mono_class_create_from_typedef:
2913  * @image: image where the token is valid
2914  * @type_token:  typedef token
2915  *
2916  * Create the MonoClass* representing the specified type token.
2917  * @type_token must be a TypeDef token.
2918  */
2919 static MonoClass *
2920 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
2921 {
2922         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
2923         MonoClass *class, *parent = NULL;
2924         guint32 cols [MONO_TYPEDEF_SIZE];
2925         guint32 cols_next [MONO_TYPEDEF_SIZE];
2926         guint tidx = mono_metadata_token_index (type_token);
2927         MonoGenericContext *context = NULL;
2928         const char *name, *nspace;
2929         guint icount = 0; 
2930         MonoClass **interfaces;
2931         guint32 field_last, method_last;
2932         guint32 nesting_tokeen;
2933
2934         mono_loader_lock ();
2935
2936         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
2937                 mono_loader_unlock ();
2938                 return class;
2939         }
2940
2941         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
2942
2943         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
2944         
2945         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2946         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2947
2948         class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
2949
2950         class->name = name;
2951         class->name_space = nspace;
2952
2953         class->image = image;
2954         class->type_token = type_token;
2955         class->flags = cols [MONO_TYPEDEF_FLAGS];
2956
2957         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
2958
2959         /*
2960          * Check whether we're a generic type definition.
2961          */
2962         class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
2963         if (class->generic_container) {
2964                 class->generic_container->klass = class;
2965                 context = &class->generic_container->context;
2966
2967                 context->gclass = mono_get_shared_generic_class (context->container, FALSE);
2968         }
2969
2970         if (cols [MONO_TYPEDEF_EXTENDS]) {
2971                 parent = mono_class_get_full (
2972                         image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
2973                 if (parent == NULL){
2974                         g_hash_table_remove (image->class_cache, GUINT_TO_POINTER (type_token));
2975                         mono_loader_unlock ();
2976                         return NULL;
2977                 }
2978         }
2979
2980         /* do this early so it's available for interfaces in setup_mono_type () */
2981         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token)))
2982                 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
2983
2984         mono_class_setup_parent (class, parent);
2985
2986         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
2987         mono_class_setup_mono_type (class);
2988
2989         if (!class->enumtype) {
2990                 if (!mono_metadata_interfaces_from_typedef_full (
2991                             image, type_token, &interfaces, &icount, context)){
2992                         mono_loader_unlock ();
2993                         return NULL;
2994                 }
2995
2996                 class->interfaces = interfaces;
2997                 class->interface_count = icount;
2998         }
2999
3000         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
3001                 class->unicode = 1;
3002
3003 #if PLATFORM_WIN32
3004         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
3005                 class->unicode = 1;
3006 #endif
3007
3008         class->cast_class = class->element_class = class;
3009
3010         /*g_print ("Load class %s\n", name);*/
3011
3012         /*
3013          * Compute the field and method lists
3014          */
3015         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
3016         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
3017
3018         if (tt->rows > tidx){           
3019                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
3020                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
3021                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
3022         } else {
3023                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
3024                 method_last = image->tables [MONO_TABLE_METHOD].rows;
3025         }
3026
3027         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
3028             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
3029                 class->field.count = field_last - class->field.first;
3030         else
3031                 class->field.count = 0;
3032
3033         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
3034                 class->method.count = method_last - class->method.first;
3035         else
3036                 class->method.count = 0;
3037
3038         /* reserve space to store vector pointer in arrays */
3039         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
3040                 class->instance_size += 2 * sizeof (gpointer);
3041                 g_assert (class->field.count == 0);
3042         }
3043
3044         if (class->enumtype) {
3045                 class->enum_basetype = mono_class_find_enum_basetype (class);
3046                 class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
3047         }
3048
3049         /*
3050          * If we're a generic type definition, load the constraints.
3051          * We must do this after the class has been constructed to make certain recursive scenarios
3052          * work.
3053          */
3054         if (class->generic_container)
3055                 mono_metadata_load_generic_param_constraints (
3056                         image, type_token, class->generic_container);
3057
3058         mono_loader_unlock ();
3059
3060         return class;
3061 }
3062
3063 /** is klass Nullable<T>? */
3064 gboolean
3065 mono_class_is_nullable (MonoClass *klass)
3066 {
3067        return klass->generic_class != NULL &&
3068                klass->generic_class->container_class == mono_defaults.generic_nullable_class;
3069 }
3070
3071
3072 /** if klass is T? return T */
3073 MonoClass*
3074 mono_class_get_nullable_param (MonoClass *klass)
3075 {
3076        g_assert (mono_class_is_nullable (klass));
3077        return mono_class_from_mono_type (klass->generic_class->inst->type_argv [0]);
3078 }
3079
3080 /*
3081  * Create the `MonoClass' for an instantiation of a generic type.
3082  * We only do this if we actually need it.
3083  */
3084 static void
3085 mono_class_create_generic (MonoInflatedGenericClass *gclass)
3086 {
3087         MonoClass *klass, *gklass;
3088         int i;
3089
3090         mono_loader_lock ();
3091         if (gclass->is_initialized) {
3092                 mono_loader_unlock ();
3093                 return;
3094         }
3095
3096         if (!gclass->klass)
3097                 gclass->klass = g_malloc0 (sizeof (MonoClass));
3098         klass = gclass->klass;
3099
3100         gklass = gclass->generic_class.container_class;
3101
3102         if (gklass->nested_in) {
3103                 /* 
3104                  * FIXME: the nested type context should include everything the
3105                  * nesting context should have, but it may also have additional
3106                  * generic parameters...
3107                  */
3108                 MonoType *inflated = mono_class_inflate_generic_type (
3109                         &gklass->nested_in->byval_arg, gclass->generic_class.context);
3110                 klass->nested_in = mono_class_from_mono_type (inflated);
3111         }
3112
3113         klass->name = gklass->name;
3114         klass->name_space = gklass->name_space;
3115         klass->image = gklass->image;
3116         klass->flags = gklass->flags;
3117         klass->type_token = gklass->type_token;
3118
3119         klass->generic_class = &gclass->generic_class;
3120
3121         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
3122         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = &gclass->generic_class;
3123         klass->this_arg.byref = TRUE;
3124
3125         klass->cast_class = klass->element_class = klass;
3126
3127         if (mono_class_is_nullable (klass))
3128                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
3129
3130         if (gclass->generic_class.is_dynamic) {
3131                 klass->instance_size = gklass->instance_size;
3132                 klass->sizes.class_size = gklass->sizes.class_size;
3133                 klass->size_inited = 1;
3134                 klass->inited = 1;
3135
3136                 klass->valuetype = gklass->valuetype;
3137
3138                 mono_class_setup_supertypes (klass);
3139         }
3140
3141         klass->interface_count = gklass->interface_count;
3142         klass->interfaces = g_new0 (MonoClass *, klass->interface_count);
3143         for (i = 0; i < klass->interface_count; i++) {
3144                 MonoType *it = &gklass->interfaces [i]->byval_arg;
3145                 MonoType *inflated = mono_class_inflate_generic_type (
3146                         it, gclass->generic_class.context);
3147                 klass->interfaces [i] = mono_class_from_mono_type (inflated);
3148         }
3149
3150         i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, 1);
3151         while (i) {
3152                 MonoClass* nclass;
3153                 guint32 cols [MONO_NESTED_CLASS_SIZE];
3154                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
3155                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
3156                 klass->nested_classes = g_list_prepend (klass->nested_classes, nclass);
3157                 
3158                 i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, i + 1);
3159         }
3160
3161         if (gklass->parent) {
3162                 MonoType *inflated = mono_class_inflate_generic_type (
3163                         &gklass->parent->byval_arg, gclass->generic_class.context);
3164
3165                 klass->parent = mono_class_from_mono_type (inflated);
3166         }
3167
3168         if (klass->parent)
3169                 mono_class_setup_parent (klass, klass->parent);
3170
3171         if (MONO_CLASS_IS_INTERFACE (klass))
3172                 setup_interface_offsets (klass, 0);
3173         gclass->is_initialized = TRUE;
3174         mono_loader_unlock ();
3175 }
3176
3177 MonoClass *
3178 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
3179 {
3180         MonoClass *klass, **ptr;
3181         int count, pos, i;
3182
3183         if (param->pklass)
3184                 return param->pklass;
3185
3186         klass = param->pklass = g_new0 (MonoClass, 1);
3187
3188         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
3189                 ;
3190
3191         pos = 0;
3192         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
3193                 klass->parent = param->constraints [0];
3194                 pos++;
3195         } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
3196                 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
3197         else
3198                 klass->parent = mono_defaults.object_class;
3199
3200         if (count - pos > 0) {
3201                 klass->interface_count = count - pos;
3202                 klass->interfaces = g_new0 (MonoClass *, count - pos);
3203                 for (i = pos; i < count; i++)
3204                         klass->interfaces [i - pos] = param->constraints [i];
3205         }
3206
3207         if (param->name)
3208                 klass->name = param->name;
3209         else
3210                 klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
3211
3212         klass->name_space = "";
3213
3214         if (image)
3215                 klass->image = image;
3216         else if (is_mvar && param->method && param->method->klass)
3217                 klass->image = param->method->klass->image;
3218         else if (param->owner && param->owner->klass)
3219                 klass->image = param->owner->klass->image;
3220         else
3221                 klass->image = mono_defaults.corlib;
3222
3223         klass->inited = TRUE;
3224         klass->cast_class = klass->element_class = klass;
3225         klass->enum_basetype = &klass->element_class->byval_arg;
3226         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
3227
3228         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
3229         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
3230         klass->this_arg.byref = TRUE;
3231
3232         mono_class_setup_supertypes (klass);
3233
3234         return klass;
3235 }
3236
3237 MonoClass *
3238 mono_ptr_class_get (MonoType *type)
3239 {
3240         MonoClass *result;
3241         MonoClass *el_class;
3242         MonoImage *image;
3243         char *name;
3244
3245         el_class = mono_class_from_mono_type (type);
3246         image = el_class->image;
3247
3248         mono_loader_lock ();
3249
3250         if (!image->ptr_cache)
3251                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
3252
3253         if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
3254                 mono_loader_unlock ();
3255                 return result;
3256         }
3257         result = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
3258
3259         result->parent = NULL; /* no parent for PTR types */
3260         result->name_space = el_class->name_space;
3261         name = g_strdup_printf ("%s*", el_class->name);
3262         result->name = mono_mempool_strdup (image->mempool, name);
3263         g_free (name);
3264         result->image = el_class->image;
3265         result->inited = TRUE;
3266         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
3267         /* Can pointers get boxed? */
3268         result->instance_size = sizeof (gpointer);
3269         result->cast_class = result->element_class = el_class;
3270         result->enum_basetype = &result->element_class->byval_arg;
3271         result->blittable = TRUE;
3272
3273         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
3274         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
3275         result->this_arg.byref = TRUE;
3276
3277         mono_class_setup_supertypes (result);
3278
3279         g_hash_table_insert (image->ptr_cache, el_class, result);
3280
3281         mono_loader_unlock ();
3282
3283         return result;
3284 }
3285
3286 static MonoClass *
3287 mono_fnptr_class_get (MonoMethodSignature *sig)
3288 {
3289         MonoClass *result;
3290         static GHashTable *ptr_hash = NULL;
3291
3292         /* FIXME: These should be allocate from a mempool as well, but which one ? */
3293
3294         mono_loader_lock ();
3295
3296         if (!ptr_hash)
3297                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3298         
3299         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
3300                 mono_loader_unlock ();
3301                 return result;
3302         }
3303         result = g_new0 (MonoClass, 1);
3304
3305         result->parent = NULL; /* no parent for PTR types */
3306         result->name_space = "System";
3307         result->name = "MonoFNPtrFakeClass";
3308         result->image = mono_defaults.corlib; /* need to fix... */
3309         result->inited = TRUE;
3310         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
3311         /* Can pointers get boxed? */
3312         result->instance_size = sizeof (gpointer);
3313         result->cast_class = result->element_class = result;
3314         result->blittable = TRUE;
3315
3316         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
3317         result->this_arg.data.method = result->byval_arg.data.method = sig;
3318         result->this_arg.byref = TRUE;
3319         result->enum_basetype = &result->element_class->byval_arg;
3320         result->blittable = TRUE;
3321
3322         mono_class_setup_supertypes (result);
3323
3324         g_hash_table_insert (ptr_hash, sig, result);
3325
3326         mono_loader_unlock ();
3327
3328         return result;
3329 }
3330
3331 MonoClass *
3332 mono_class_from_mono_type (MonoType *type)
3333 {
3334         switch (type->type) {
3335         case MONO_TYPE_OBJECT:
3336                 return type->data.klass? type->data.klass: mono_defaults.object_class;
3337         case MONO_TYPE_VOID:
3338                 return type->data.klass? type->data.klass: mono_defaults.void_class;
3339         case MONO_TYPE_BOOLEAN:
3340                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
3341         case MONO_TYPE_CHAR:
3342                 return type->data.klass? type->data.klass: mono_defaults.char_class;
3343         case MONO_TYPE_I1:
3344                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
3345         case MONO_TYPE_U1:
3346                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
3347         case MONO_TYPE_I2:
3348                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
3349         case MONO_TYPE_U2:
3350                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
3351         case MONO_TYPE_I4:
3352                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
3353         case MONO_TYPE_U4:
3354                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
3355         case MONO_TYPE_I:
3356                 return type->data.klass? type->data.klass: mono_defaults.int_class;
3357         case MONO_TYPE_U:
3358                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
3359         case MONO_TYPE_I8:
3360                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
3361         case MONO_TYPE_U8:
3362                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
3363         case MONO_TYPE_R4:
3364                 return type->data.klass? type->data.klass: mono_defaults.single_class;
3365         case MONO_TYPE_R8:
3366                 return type->data.klass? type->data.klass: mono_defaults.double_class;
3367         case MONO_TYPE_STRING:
3368                 return type->data.klass? type->data.klass: mono_defaults.string_class;
3369         case MONO_TYPE_TYPEDBYREF:
3370                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
3371         case MONO_TYPE_ARRAY:
3372                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
3373         case MONO_TYPE_PTR:
3374                 return mono_ptr_class_get (type->data.type);
3375         case MONO_TYPE_FNPTR:
3376                 return mono_fnptr_class_get (type->data.method);
3377         case MONO_TYPE_SZARRAY:
3378                 return mono_array_class_get (type->data.klass, 1);
3379         case MONO_TYPE_CLASS:
3380         case MONO_TYPE_VALUETYPE:
3381                 return type->data.klass;
3382         case MONO_TYPE_GENERICINST: {
3383                 MonoInflatedGenericClass *gclass;
3384                 gclass = mono_get_inflated_generic_class (type->data.generic_class);
3385                 g_assert (gclass->klass);
3386                 return gclass->klass;
3387         }
3388         case MONO_TYPE_VAR:
3389                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
3390         case MONO_TYPE_MVAR:
3391                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
3392         default:
3393                 g_warning ("implement me 0x%02x\n", type->type);
3394                 g_assert_not_reached ();
3395         }
3396         
3397         return NULL;
3398 }
3399
3400 /**
3401  * @image: context where the image is created
3402  * @type_spec:  typespec token
3403  * @context: the generic context used to evaluate generic instantiations in
3404  */
3405 static MonoClass *
3406 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
3407 {
3408         MonoType *t = mono_type_create_from_typespec (image, type_spec);
3409         if (!t)
3410                 return NULL;
3411         if (context && (context->gclass || context->gmethod)) {
3412                 MonoType *inflated = inflate_generic_type (t, context);
3413                 if (inflated)
3414                         t = inflated;
3415         }
3416         return mono_class_from_mono_type (t);
3417 }
3418
3419 /**
3420  * mono_bounded_array_class_get:
3421  * @element_class: element class 
3422  * @rank: the dimension of the array class
3423  * @bounded: whenever the array has non-zero bounds
3424  *
3425  * Returns: a class object describing the array with element type @element_type and 
3426  * dimension @rank. 
3427  */
3428 MonoClass *
3429 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
3430 {
3431         MonoImage *image;
3432         MonoClass *class;
3433         MonoClass *parent = NULL;
3434         GSList *list, *rootlist;
3435         int nsize;
3436         char *name;
3437         gboolean corlib_type = FALSE;
3438
3439         g_assert (rank <= 255);
3440
3441         if (rank > 1)
3442                 /* bounded only matters for one-dimensional arrays */
3443                 bounded = FALSE;
3444
3445         image = eclass->image;
3446
3447         mono_loader_lock ();
3448
3449         if (!image->array_cache)
3450                 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
3451
3452         if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
3453                 for (; list; list = list->next) {
3454                         class = list->data;
3455                         if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
3456                                 mono_loader_unlock ();
3457                                 return class;
3458                         }
3459                 }
3460         }
3461
3462         /* for the building corlib use System.Array from it */
3463         if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
3464                 parent = mono_class_from_name (image, "System", "Array");
3465                 corlib_type = TRUE;
3466         } else {
3467                 parent = mono_defaults.array_class;
3468                 if (!parent->inited)
3469                         mono_class_init (parent);
3470         }
3471
3472         class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
3473
3474         class->image = image;
3475         class->name_space = eclass->name_space;
3476         nsize = strlen (eclass->name);
3477         name = g_malloc (nsize + 2 + rank);
3478         memcpy (name, eclass->name, nsize);
3479         name [nsize] = '[';
3480         if (rank > 1)
3481                 memset (name + nsize + 1, ',', rank - 1);
3482         name [nsize + rank] = ']';
3483         name [nsize + rank + 1] = 0;
3484         class->name = mono_mempool_strdup (image->mempool, name);
3485         g_free (name);
3486         class->type_token = 0;
3487         /* all arrays are marked serializable and sealed, bug #42779 */
3488         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
3489                 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
3490         class->parent = parent;
3491         class->instance_size = mono_class_instance_size (class->parent);
3492         class->sizes.element_size = mono_class_array_element_size (eclass);
3493         mono_class_setup_supertypes (class);
3494
3495         if (mono_defaults.generic_ilist_class) {
3496                 MonoClass *fclass = NULL;
3497                 int i;
3498
3499                 if (eclass->valuetype) {
3500                         if (eclass == mono_defaults.int16_class)
3501                                 fclass = mono_defaults.uint16_class;
3502                         if (eclass == mono_defaults.uint16_class)
3503                                 fclass = mono_defaults.int16_class;
3504                         if (eclass == mono_defaults.int32_class)
3505                                 fclass = mono_defaults.uint32_class;
3506                         if (eclass == mono_defaults.uint32_class)
3507                                 fclass = mono_defaults.int32_class;
3508                         if (eclass == mono_defaults.int64_class)
3509                                 fclass = mono_defaults.uint64_class;
3510                         if (eclass == mono_defaults.uint64_class)
3511                                 fclass = mono_defaults.int64_class;
3512                         if (eclass == mono_defaults.byte_class)
3513                                 fclass = mono_defaults.sbyte_class;
3514                         if (eclass == mono_defaults.sbyte_class)
3515                                 fclass = mono_defaults.byte_class;
3516
3517                         class->interface_count = fclass ? 2 : 1;
3518                 } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
3519                         class->interface_count = 2 + eclass->interface_count;
3520                 } else {
3521                         class->interface_count = eclass->idepth + eclass->interface_count;
3522                 }
3523
3524                 class->interfaces = g_new0 (MonoClass *, class->interface_count);
3525
3526                 for (i = 0; i < class->interface_count; i++) {
3527                         MonoType *inflated, **args;
3528                         MonoClass *iface;
3529
3530                         if (eclass->valuetype)
3531                                 iface = (i == 0) ? eclass : fclass;
3532                         else if (MONO_CLASS_IS_INTERFACE (eclass)) {
3533                                 if (i == 0)
3534                                         iface = mono_defaults.object_class;
3535                                 else if (i == 1)
3536                                         iface = eclass;
3537                                 else
3538                                         iface = eclass->interfaces [i - 2];
3539                         } else {
3540                                 if (i < eclass->idepth)
3541                                         iface = eclass->supertypes [i];
3542                                 else
3543                                         iface = eclass->interfaces [i - eclass->idepth];
3544                         }
3545
3546                         args = g_new0 (MonoType *, 1);
3547                         args [0] = &iface->byval_arg;
3548
3549                         inflated = mono_class_bind_generic_parameters (
3550                                 &mono_defaults.generic_ilist_class->byval_arg, 1, args);
3551
3552                         class->interfaces [i] = mono_class_from_mono_type (inflated);
3553                 }
3554         }
3555
3556         if (eclass->generic_class)
3557                 mono_class_init (eclass);
3558         if (!eclass->size_inited)
3559                 mono_class_setup_fields (eclass);
3560         class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
3561
3562         class->rank = rank;
3563         
3564         if (eclass->enumtype)
3565                 class->cast_class = eclass->element_class;
3566         else
3567                 class->cast_class = eclass;
3568
3569         class->element_class = eclass;
3570
3571         if ((rank > 1) || bounded) {
3572                 MonoArrayType *at = mono_mempool_alloc0 (image->mempool, sizeof (MonoArrayType));
3573                 class->byval_arg.type = MONO_TYPE_ARRAY;
3574                 class->byval_arg.data.array = at;
3575                 at->eklass = eclass;
3576                 at->rank = rank;
3577                 /* FIXME: complete.... */
3578         } else {
3579                 class->byval_arg.type = MONO_TYPE_SZARRAY;
3580                 class->byval_arg.data.klass = eclass;
3581         }
3582         class->this_arg = class->byval_arg;
3583         class->this_arg.byref = 1;
3584         if (corlib_type) {
3585                 class->inited = 1;
3586         }
3587
3588         class->generic_container = eclass->generic_container;
3589
3590         list = g_slist_append (rootlist, class);
3591         g_hash_table_insert (image->array_cache, eclass, list);
3592
3593         mono_loader_unlock ();
3594
3595         return class;
3596 }
3597
3598 /**
3599  * mono_array_class_get:
3600  * @element_class: element class 
3601  * @rank: the dimension of the array class
3602  *
3603  * Returns: a class object describing the array with element type @element_type and 
3604  * dimension @rank. 
3605  */
3606 MonoClass *
3607 mono_array_class_get (MonoClass *eclass, guint32 rank)
3608 {
3609         return mono_bounded_array_class_get (eclass, rank, FALSE);
3610 }
3611
3612 /**
3613  * mono_class_instance_size:
3614  * @klass: a class 
3615  * 
3616  * Returns: the size of an object instance
3617  */
3618 gint32
3619 mono_class_instance_size (MonoClass *klass)
3620 {       
3621         if (!klass->size_inited)
3622                 mono_class_init (klass);
3623
3624         return klass->instance_size;
3625 }
3626
3627 /**
3628  * mono_class_min_align:
3629  * @klass: a class 
3630  * 
3631  * Returns: minimm alignment requirements 
3632  */
3633 gint32
3634 mono_class_min_align (MonoClass *klass)
3635 {       
3636         if (!klass->size_inited)
3637                 mono_class_init (klass);
3638
3639         return klass->min_align;
3640 }
3641
3642 /**
3643  * mono_class_value_size:
3644  * @klass: a class 
3645  *
3646  * This function is used for value types, and return the
3647  * space and the alignment to store that kind of value object.
3648  *
3649  * Returns: the size of a value of kind @klass
3650  */
3651 gint32
3652 mono_class_value_size      (MonoClass *klass, guint32 *align)
3653 {
3654         gint32 size;
3655
3656         /* fixme: check disable, because we still have external revereces to
3657          * mscorlib and Dummy Objects 
3658          */
3659         /*g_assert (klass->valuetype);*/
3660
3661         size = mono_class_instance_size (klass) - sizeof (MonoObject);
3662
3663         if (align)
3664                 *align = klass->min_align;
3665
3666         return size;
3667 }
3668
3669 /**
3670  * mono_class_data_size:
3671  * @klass: a class 
3672  * 
3673  * Returns: the size of the static class data
3674  */
3675 gint32
3676 mono_class_data_size (MonoClass *klass)
3677 {       
3678         if (!klass->inited)
3679                 mono_class_init (klass);
3680
3681         /* in arrays, sizes.class_size is unioned with element_size
3682          * and arrays have no static fields
3683          */
3684         if (klass->rank)
3685                 return 0;
3686         return klass->sizes.class_size;
3687 }
3688
3689 /*
3690  * Auxiliary routine to mono_class_get_field
3691  *
3692  * Takes a field index instead of a field token.
3693  */
3694 static MonoClassField *
3695 mono_class_get_field_idx (MonoClass *class, int idx)
3696 {
3697         mono_class_setup_fields_locking (class);
3698
3699         while (class) {
3700                 if (class->image->uncompressed_metadata) {
3701                         /* 
3702                          * class->field.first points to the FieldPtr table, while idx points into the
3703                          * Field table, so we have to do a search.
3704                          */
3705                         const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
3706                         int i;
3707
3708                         for (i = 0; i < class->field.count; ++i)
3709                                 if (class->fields [i].name == name)
3710                                         return &class->fields [i];
3711                         g_assert_not_reached ();
3712                 } else {                        
3713                         if (class->field.count) {
3714                                 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
3715                                         return &class->fields [idx - class->field.first];
3716                                 }
3717                         }
3718                 }
3719                 class = class->parent;
3720         }
3721         return NULL;
3722 }
3723
3724 /**
3725  * mono_class_get_field:
3726  * @class: the class to lookup the field.
3727  * @field_token: the field token
3728  *
3729  * Returns: A MonoClassField representing the type and offset of
3730  * the field, or a NULL value if the field does not belong to this
3731  * class.
3732  */
3733 MonoClassField *
3734 mono_class_get_field (MonoClass *class, guint32 field_token)
3735 {
3736         int idx = mono_metadata_token_index (field_token);
3737
3738         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
3739
3740         return mono_class_get_field_idx (class, idx - 1);
3741 }
3742
3743 /**
3744  * mono_class_get_field_from_name:
3745  * @klass: the class to lookup the field.
3746  * @name: the field name
3747  *
3748  * Search the class @klass and it's parents for a field with the name @name.
3749  * 
3750  * Returns: the MonoClassField pointer of the named field or NULL
3751  */
3752 MonoClassField *
3753 mono_class_get_field_from_name (MonoClass *klass, const char *name)
3754 {
3755         int i;
3756
3757         mono_class_setup_fields_locking (klass);
3758         while (klass) {
3759                 for (i = 0; i < klass->field.count; ++i) {
3760                         if (strcmp (name, klass->fields [i].name) == 0)
3761                                 return &klass->fields [i];
3762                 }
3763                 klass = klass->parent;
3764         }
3765         return NULL;
3766 }
3767
3768 /**
3769  * mono_class_get_field_token:
3770  * @field: the field we need the token of
3771  *
3772  * Get the token of a field. Note that the tokesn is only valid for the image
3773  * the field was loaded from. Don't use this function for fields in dynamic types.
3774  * 
3775  * Returns: the token representing the field in the image it was loaded from.
3776  */
3777 guint32
3778 mono_class_get_field_token (MonoClassField *field)
3779 {
3780         MonoClass *klass = field->parent;
3781         int i;
3782
3783         mono_class_setup_fields_locking (klass);
3784         while (klass) {
3785                 for (i = 0; i < klass->field.count; ++i) {
3786                         if (&klass->fields [i] == field) {
3787                                 int idx = klass->field.first + i + 1;
3788
3789                                 if (klass->image->uncompressed_metadata)
3790                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
3791                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
3792                         }
3793                 }
3794                 klass = klass->parent;
3795         }
3796
3797         g_assert_not_reached ();
3798         return 0;
3799 }
3800
3801 guint32
3802 mono_class_get_event_token (MonoEvent *event)
3803 {
3804         MonoClass *klass = event->parent;
3805         int i;
3806
3807         while (klass) {
3808                 for (i = 0; i < klass->event.count; ++i) {
3809                         if (&klass->events [i] == event)
3810                                 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->event.first + i + 1);
3811                 }
3812                 klass = klass->parent;
3813         }
3814
3815         g_assert_not_reached ();
3816         return 0;
3817 }
3818
3819 MonoProperty*
3820 mono_class_get_property_from_name (MonoClass *klass, const char *name)
3821 {
3822         while (klass) {
3823                 MonoProperty* p;
3824                 gpointer iter = NULL;
3825                 while ((p = mono_class_get_properties (klass, &iter))) {
3826                         if (! strcmp (name, p->name))
3827                                 return p;
3828                 }
3829                 klass = klass->parent;
3830         }
3831         return NULL;
3832 }
3833
3834 guint32
3835 mono_class_get_property_token (MonoProperty *prop)
3836 {
3837         MonoClass *klass = prop->parent;
3838         while (klass) {
3839                 MonoProperty* p;
3840                 int i = 0;
3841                 gpointer iter = NULL;
3842                 while ((p = mono_class_get_properties (klass, &iter))) {
3843                         if (&klass->properties [i] == prop)
3844                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->property.first + i + 1);
3845                         
3846                         i ++;
3847                 }
3848                 klass = klass->parent;
3849         }
3850
3851         g_assert_not_reached ();
3852         return 0;
3853 }
3854
3855 char *
3856 mono_class_name_from_token (MonoImage *image, guint32 type_token)
3857 {
3858         const char *name, *nspace;
3859         if (image->dynamic)
3860                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
3861         
3862         switch (type_token & 0xff000000){
3863         case MONO_TOKEN_TYPE_DEF: {
3864                 guint32 cols [MONO_TYPEDEF_SIZE];
3865                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
3866                 guint tidx = mono_metadata_token_index (type_token);
3867
3868                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
3869                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3870                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3871                 if (strlen (nspace) == 0)
3872                         return g_strdup_printf ("%s", name);
3873                 else
3874                         return g_strdup_printf ("%s.%s", nspace, name);
3875         }
3876
3877         case MONO_TOKEN_TYPE_REF: {
3878                 guint32 cols [MONO_TYPEREF_SIZE];
3879                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
3880
3881                 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
3882                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
3883                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
3884                 if (strlen (nspace) == 0)
3885                         return g_strdup_printf ("%s", name);
3886                 else
3887                         return g_strdup_printf ("%s.%s", nspace, name);
3888         }
3889                 
3890         case MONO_TOKEN_TYPE_SPEC:
3891                 return g_strdup_printf ("Typespec 0x%08x", type_token);
3892         default:
3893                 g_assert_not_reached ();
3894         }
3895
3896         return NULL;
3897 }
3898
3899 static char *
3900 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
3901 {
3902         if (image->dynamic)
3903                 return g_strdup_printf ("DynamicAssembly %s", image->name);
3904         
3905         switch (type_token & 0xff000000){
3906         case MONO_TOKEN_TYPE_DEF:
3907                 return mono_stringify_assembly_name (&image->assembly->aname);
3908                 break;
3909         case MONO_TOKEN_TYPE_REF: {
3910                 MonoAssemblyName aname;
3911                 guint32 cols [MONO_TYPEREF_SIZE];
3912                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
3913                 guint32 idx;
3914         
3915                 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
3916
3917                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
3918                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
3919                 case MONO_RESOLTION_SCOPE_MODULE:
3920                         /* FIXME: */
3921                         return g_strdup ("");
3922                 case MONO_RESOLTION_SCOPE_MODULEREF:
3923                         /* FIXME: */
3924                         return g_strdup ("");
3925                 case MONO_RESOLTION_SCOPE_TYPEREF:
3926                         /* FIXME: */
3927                         return g_strdup ("");
3928                 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
3929                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
3930                         return mono_stringify_assembly_name (&aname);
3931                 default:
3932                         g_assert_not_reached ();
3933                 }
3934                 break;
3935         }
3936         case MONO_TOKEN_TYPE_SPEC:
3937                 /* FIXME: */
3938                 return g_strdup ("");
3939         default:
3940                 g_assert_not_reached ();
3941         }
3942
3943         return NULL;
3944 }
3945
3946 /**
3947  * mono_class_get_full:
3948  * @image: the image where the class resides
3949  * @type_token: the token for the class
3950  * @context: the generic context used to evaluate generic instantiations in
3951  *
3952  * Returns: the MonoClass that represents @type_token in @image
3953  */
3954 MonoClass *
3955 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
3956 {
3957         MonoClass *class = NULL;
3958
3959         if (image->dynamic)
3960                 return mono_lookup_dynamic_token (image, type_token);
3961
3962         switch (type_token & 0xff000000){
3963         case MONO_TOKEN_TYPE_DEF:
3964                 class = mono_class_create_from_typedef (image, type_token);
3965                 break;          
3966         case MONO_TOKEN_TYPE_REF:
3967                 class = mono_class_from_typeref (image, type_token);
3968                 break;
3969         case MONO_TOKEN_TYPE_SPEC:
3970                 class = mono_class_create_from_typespec (image, type_token, context);
3971                 break;
3972         default:
3973                 g_warning ("unknown token type %x", type_token & 0xff000000);
3974                 g_assert_not_reached ();
3975         }
3976
3977         if (!class){
3978                 char *name = mono_class_name_from_token (image, type_token);
3979                 char *assembly = mono_assembly_name_from_token (image, type_token);
3980                 mono_loader_set_error_type_load (name, assembly);
3981         }
3982
3983         return class;
3984 }
3985
3986 MonoClass *
3987 mono_class_get (MonoImage *image, guint32 type_token)
3988 {
3989         return mono_class_get_full (image, type_token, NULL);
3990 }
3991
3992 /**
3993  * mono_image_init_name_cache:
3994  *
3995  *  Initializes the class name cache stored in image->name_cache.
3996  *
3997  * LOCKING: Acquires the loader lock.
3998  */
3999 void
4000 mono_image_init_name_cache (MonoImage *image)
4001 {
4002         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
4003         guint32 cols [MONO_TYPEDEF_SIZE];
4004         const char *name;
4005         const char *nspace;
4006         guint32 i, visib, nspace_index;
4007         GHashTable *name_cache2, *nspace_table;
4008
4009         mono_loader_lock ();
4010
4011         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
4012
4013         if (image->dynamic) {
4014                 mono_loader_unlock ();
4015                 return;
4016         }
4017
4018         /* Temporary hash table to avoid lookups in the nspace_table */
4019         name_cache2 = g_hash_table_new (NULL, NULL);
4020
4021         for (i = 1; i <= t->rows; ++i) {
4022                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
4023                 /* nested types are accessed from the nesting name */
4024                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4025                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
4026                         continue;
4027                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
4028                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
4029
4030                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
4031                 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
4032                 if (!nspace_table) {
4033                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4034                         g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
4035                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
4036                                                                  nspace_table);
4037                 }
4038                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
4039         }
4040
4041         /* Load type names from EXPORTEDTYPES table */
4042         {
4043                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
4044                 guint32 cols [MONO_EXP_TYPE_SIZE];
4045                 int i;
4046
4047                 for (i = 0; i < t->rows; ++i) {
4048                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
4049                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
4050                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
4051
4052                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
4053                         nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
4054                         if (!nspace_table) {
4055                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4056                                 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
4057                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
4058                                                                          nspace_table);
4059                         }
4060                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
4061                 }
4062         }
4063
4064         g_hash_table_destroy (name_cache2);
4065
4066         mono_loader_unlock ();
4067 }
4068
4069 void
4070 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
4071                                                           const char *name, guint32 index)
4072 {
4073         GHashTable *nspace_table;
4074         GHashTable *name_cache;
4075
4076         mono_loader_lock ();
4077
4078         if (!image->name_cache)
4079                 mono_image_init_name_cache (image);
4080
4081         name_cache = image->name_cache;
4082         if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
4083                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4084                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
4085         }
4086         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
4087
4088         mono_loader_unlock ();
4089 }
4090
4091 typedef struct {
4092         gconstpointer key;
4093         gpointer value;
4094 } FindUserData;
4095
4096 static void
4097 find_nocase (gpointer key, gpointer value, gpointer user_data)
4098 {
4099         char *name = (char*)key;
4100         FindUserData *data = (FindUserData*)user_data;
4101
4102         if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
4103                 data->value = value;
4104 }
4105
4106 /**
4107  * mono_class_from_name_case:
4108  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
4109  * @name_space: the type namespace
4110  * @name: the type short name.
4111  *
4112  * Obtains a MonoClass with a given namespace and a given name which
4113  * is located in the given MonoImage.   The namespace and name
4114  * lookups are case insensitive.
4115  */
4116 MonoClass *
4117 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
4118 {
4119         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
4120         guint32 cols [MONO_TYPEDEF_SIZE];
4121         const char *n;
4122         const char *nspace;
4123         guint32 i, visib;
4124
4125         if (image->dynamic) {
4126                 guint32 token = 0;
4127                 FindUserData user_data;
4128
4129                 mono_loader_lock ();
4130
4131                 if (!image->name_cache)
4132                         mono_image_init_name_cache (image);
4133
4134                 user_data.key = name_space;
4135                 user_data.value = NULL;
4136                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
4137
4138                 if (user_data.value) {
4139                         GHashTable *nspace_table = (GHashTable*)user_data.value;
4140
4141                         user_data.key = name;
4142                         user_data.value = NULL;
4143
4144                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
4145                         
4146                         if (user_data.value)
4147                                 token = GPOINTER_TO_UINT (user_data.value);
4148                 }
4149
4150                 mono_loader_unlock ();
4151                 
4152                 if (token)
4153                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
4154                 else
4155                         return NULL;
4156
4157         }
4158
4159         /* add a cache if needed */
4160         for (i = 1; i <= t->rows; ++i) {
4161                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
4162                 /* nested types are accessed from the nesting name */
4163                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4164                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
4165                         continue;
4166                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
4167                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
4168                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
4169                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
4170         }
4171         return NULL;
4172 }
4173
4174 static MonoClass*
4175 return_nested_in (MonoClass *class, char *nested) {
4176         MonoClass *found;
4177         char *s = strchr (nested, '/');
4178         GList *tmp;
4179
4180         if (s) {
4181                 *s = 0;
4182                 s++;
4183         }
4184         for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
4185                 found = tmp->data;
4186                 if (strcmp (found->name, nested) == 0) {
4187                         if (s)
4188                                 return return_nested_in (found, s);
4189                         return found;
4190                 }
4191         }
4192         return NULL;
4193 }
4194
4195
4196 /**
4197  * mono_class_from_name:
4198  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
4199  * @name_space: the type namespace
4200  * @name: the type short name.
4201  *
4202  * Obtains a MonoClass with a given namespace and a given name which
4203  * is located in the given MonoImage.   
4204  */
4205 MonoClass *
4206 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
4207 {
4208         GHashTable *nspace_table;
4209         MonoImage *loaded_image;
4210         guint32 token = 0;
4211         MonoClass *class;
4212         char *nested;
4213         char buf [1024];
4214
4215         if ((nested = strchr (name, '/'))) {
4216                 int pos = nested - name;
4217                 int len = strlen (name);
4218                 if (len > 1023)
4219                         return NULL;
4220                 memcpy (buf, name, len + 1);
4221                 buf [pos] = 0;
4222                 nested = buf + pos + 1;
4223                 name = buf;
4224         }
4225
4226         if (get_class_from_name) {
4227                 gboolean res = get_class_from_name (image, name_space, name, &class);
4228                 if (res) {
4229                         if (nested)
4230                                 return class ? return_nested_in (class, nested) : NULL;
4231                         else
4232                                 return class;
4233                 }
4234         }
4235
4236         mono_loader_lock ();
4237
4238         if (!image->name_cache)
4239                 mono_image_init_name_cache (image);
4240
4241         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
4242
4243         if (nspace_table)
4244                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
4245
4246         mono_loader_unlock ();
4247
4248         if (!token)
4249                 return NULL;
4250
4251         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
4252                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
4253                 guint32 cols [MONO_EXP_TYPE_SIZE];
4254                 guint32 idx, impl;
4255
4256                 idx = mono_metadata_token_index (token);
4257
4258                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
4259
4260                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
4261                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
4262                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
4263                         if (!loaded_image)
4264                                 return NULL;
4265                         class = mono_class_from_name (loaded_image, name_space, name);
4266                         if (nested)
4267                                 return return_nested_in (class, nested);
4268                         return class;
4269                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
4270                         MonoAssembly **references = image->references;
4271                         if (!references [idx - 1])
4272                                 mono_assembly_load_reference (image, idx - 1);
4273                         g_assert (references == image->references);
4274                         g_assert (references [idx - 1]);
4275                         if (references [idx - 1] == (gpointer)-1)
4276                                 return NULL;                    
4277                         else
4278                                 /* FIXME: Cycle detection */
4279                                 return mono_class_from_name (references [idx - 1]->image, name_space, name);
4280                 } else {
4281                         g_error ("not yet implemented");
4282                 }
4283         }
4284
4285         token = MONO_TOKEN_TYPE_DEF | token;
4286
4287         class = mono_class_get (image, token);
4288         if (nested)
4289                 return return_nested_in (class, nested);
4290         return class;
4291 }
4292
4293 gboolean
4294 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
4295                            gboolean check_interfaces)
4296 {
4297         g_assert (klassc->idepth > 0);
4298         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
4299                 if ((klassc->interface_id <= klass->max_interface_id) &&
4300                         (klass->interface_offsets [klassc->interface_id] >= 0))
4301                         return TRUE;
4302         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
4303                 int i;
4304
4305                 for (i = 0; i < klass->interface_count; i ++) {
4306                         MonoClass *ic =  klass->interfaces [i];
4307                         if (ic == klassc)
4308                                 return TRUE;
4309                 }
4310         } else {
4311                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
4312                         return TRUE;
4313         }
4314
4315         /* 
4316          * MS.NET thinks interfaces are a subclass of Object, so we think it as
4317          * well.
4318          */
4319         if (klassc == mono_defaults.object_class)
4320                 return TRUE;
4321
4322         return FALSE;
4323 }
4324
4325 gboolean
4326 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
4327 {
4328         if (!klass->inited)
4329                 mono_class_init (klass);
4330
4331         if (!oklass->inited)
4332                 mono_class_init (oklass);
4333
4334         if (MONO_CLASS_IS_INTERFACE (klass)) {
4335                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
4336                         return FALSE;
4337
4338                 /* interface_offsets might not be set for dynamic classes */
4339                 if (oklass->reflection_info && !oklass->interface_offsets)
4340                         /* 
4341                          * oklass might be a generic type parameter but they have 
4342                          * interface_offsets set.
4343                          */
4344                         return mono_reflection_call_is_assignable_to (oklass, klass);
4345
4346                 if ((klass->interface_id <= oklass->max_interface_id) &&
4347                     (oklass->interface_offsets [klass->interface_id] != -1))
4348                         return TRUE;
4349         } else if (klass->rank) {
4350                 MonoClass *eclass, *eoclass;
4351
4352                 if (oklass->rank != klass->rank)
4353                         return FALSE;
4354
4355                 /* vectors vs. one dimensional arrays */
4356                 if (oklass->byval_arg.type != klass->byval_arg.type)
4357                         return FALSE;
4358
4359                 eclass = klass->cast_class;
4360                 eoclass = oklass->cast_class;
4361
4362                 /* 
4363                  * a is b does not imply a[] is b[] when a is a valuetype, and
4364                  * b is a reference type.
4365                  */
4366
4367                 if (eoclass->valuetype) {
4368                         if ((eclass == mono_defaults.enum_class) || 
4369                                 (eclass == mono_defaults.enum_class->parent) ||
4370                                 (eclass == mono_defaults.object_class))
4371                                 return FALSE;
4372                 }
4373
4374                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
4375         } else if (mono_class_is_nullable (klass))
4376                 return (mono_class_is_assignable_from (klass->cast_class, oklass));
4377         else if (klass == mono_defaults.object_class)
4378                 return TRUE;
4379
4380         return mono_class_has_parent (oklass, klass);
4381 }       
4382
4383 /*
4384  * mono_class_get_cctor:
4385  *
4386  *   Returns the static constructor of @klass if it exists, NULL otherwise.
4387  */
4388 MonoMethod*
4389 mono_class_get_cctor (MonoClass *klass)
4390 {
4391         MonoCachedClassInfo cached_info;
4392
4393         if (!klass->has_cctor)
4394                 return NULL;
4395
4396         if (mono_class_get_cached_class_info (klass, &cached_info))
4397                 return mono_get_method (klass->image, cached_info.cctor_token, klass);
4398
4399         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
4400 }
4401
4402 /*
4403  * mono_class_get_finalizer:
4404  *
4405  *   Returns the finalizer method of @klass if it exists, NULL otherwise.
4406  */
4407 MonoMethod*
4408 mono_class_get_finalizer (MonoClass *klass)
4409 {
4410         MonoCachedClassInfo cached_info;
4411
4412         if (!klass->inited)
4413                 mono_class_init (klass);
4414         if (!klass->has_finalize)
4415                 return NULL;
4416
4417         if (mono_class_get_cached_class_info (klass, &cached_info))
4418                 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
4419         else {
4420                 mono_class_setup_vtable (klass);
4421                 return klass->vtable [finalize_slot];
4422         }
4423 }
4424
4425 /*
4426  * mono_class_needs_cctor_run:
4427  *
4428  *  Determines whenever the class has a static constructor and whenever it
4429  * needs to be called when executing CALLER.
4430  */
4431 gboolean
4432 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
4433 {
4434         MonoMethod *method;
4435
4436         method = mono_class_get_cctor (klass);
4437         if (method)
4438                 return (method == caller) ? FALSE : TRUE;
4439         else
4440                 return TRUE;
4441 }
4442
4443 /**
4444  * mono_class_array_element_size:
4445  * @klass: 
4446  *
4447  * Returns: the number of bytes an element of type @klass
4448  * uses when stored into an array.
4449  */
4450 gint32
4451 mono_class_array_element_size (MonoClass *klass)
4452 {
4453         MonoType *type = &klass->byval_arg;
4454         
4455 handle_enum:
4456         switch (type->type) {
4457         case MONO_TYPE_I1:
4458         case MONO_TYPE_U1:
4459         case MONO_TYPE_BOOLEAN:
4460                 return 1;
4461         case MONO_TYPE_I2:
4462         case MONO_TYPE_U2:
4463         case MONO_TYPE_CHAR:
4464                 return 2;
4465         case MONO_TYPE_I4:
4466         case MONO_TYPE_U4:
4467         case MONO_TYPE_R4:
4468                 return 4;
4469         case MONO_TYPE_I:
4470         case MONO_TYPE_U:
4471         case MONO_TYPE_PTR:
4472         case MONO_TYPE_CLASS:
4473         case MONO_TYPE_STRING:
4474         case MONO_TYPE_OBJECT:
4475         case MONO_TYPE_SZARRAY:
4476         case MONO_TYPE_ARRAY: 
4477         case MONO_TYPE_VAR:
4478         case MONO_TYPE_MVAR:   
4479                 return sizeof (gpointer);
4480         case MONO_TYPE_I8:
4481         case MONO_TYPE_U8:
4482         case MONO_TYPE_R8:
4483                 return 8;
4484         case MONO_TYPE_VALUETYPE:
4485                 if (type->data.klass->enumtype) {
4486                         type = type->data.klass->enum_basetype;
4487                         klass = klass->element_class;
4488                         goto handle_enum;
4489                 }
4490                 return mono_class_instance_size (klass) - sizeof (MonoObject);
4491         case MONO_TYPE_GENERICINST:
4492                 type = &type->data.generic_class->container_class->byval_arg;
4493                 goto handle_enum;
4494         default:
4495                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
4496         }
4497         return -1;
4498 }
4499
4500 /**
4501  * mono_array_element_size:
4502  * @ac: pointer to a #MonoArrayClass
4503  *
4504  * Returns: the size of single array element.
4505  */
4506 gint32
4507 mono_array_element_size (MonoClass *ac)
4508 {
4509         g_assert (ac->rank);
4510         return ac->sizes.element_size;
4511 }
4512
4513 gpointer
4514 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
4515               MonoGenericContext *context)
4516 {
4517         if (image->dynamic) {
4518                 MonoClass *tmp_handle_class;
4519                 gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class);
4520
4521                 g_assert (tmp_handle_class);
4522                 if (handle_class)
4523                         *handle_class = tmp_handle_class;
4524
4525                 if (tmp_handle_class == mono_defaults.typehandle_class)
4526                         return &((MonoClass*)obj)->byval_arg;
4527                 else
4528                         return obj;
4529         }
4530
4531         switch (token & 0xff000000) {
4532         case MONO_TOKEN_TYPE_DEF:
4533         case MONO_TOKEN_TYPE_REF:
4534         case MONO_TOKEN_TYPE_SPEC: {
4535                 MonoClass *class;
4536                 if (handle_class)
4537                         *handle_class = mono_defaults.typehandle_class;
4538                 class = mono_class_get_full (image, token, context);
4539                 if (!class)
4540                         return NULL;
4541                 mono_class_init (class);
4542                 /* We return a MonoType* as handle */
4543                 return &class->byval_arg;
4544         }
4545         case MONO_TOKEN_FIELD_DEF: {
4546                 MonoClass *class;
4547                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
4548                 if (handle_class)
4549                         *handle_class = mono_defaults.fieldhandle_class;
4550                 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
4551                 if (!class)
4552                         return NULL;
4553                 mono_class_init (class);
4554                 return mono_class_get_field (class, token);
4555         }
4556         case MONO_TOKEN_METHOD_DEF: {
4557                 MonoMethod *meth;
4558                 meth = mono_get_method_full (image, token, NULL, context);
4559                 if (handle_class)
4560                         *handle_class = mono_defaults.methodhandle_class;
4561                 return meth;
4562         }
4563         case MONO_TOKEN_MEMBER_REF: {
4564                 guint32 cols [MONO_MEMBERREF_SIZE];
4565                 const char *sig;
4566                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4567                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4568                 mono_metadata_decode_blob_size (sig, &sig);
4569                 if (*sig == 0x6) { /* it's a field */
4570                         MonoClass *klass;
4571                         MonoClassField *field;
4572                         field = mono_field_from_token (image, token, &klass, context);
4573                         if (handle_class)
4574                                 *handle_class = mono_defaults.fieldhandle_class;
4575                         return field;
4576                 } else {
4577                         MonoMethod *meth;
4578                         meth = mono_get_method_full (image, token, NULL, context);
4579                         if (handle_class)
4580                                 *handle_class = mono_defaults.methodhandle_class;
4581                         return meth;
4582                 }
4583         }
4584         default:
4585                 g_warning ("Unknown token 0x%08x in ldtoken", token);
4586                 break;
4587         }
4588         return NULL;
4589 }
4590
4591 /**
4592  * This function might need to call runtime functions so it can't be part
4593  * of the metadata library.
4594  */
4595 static MonoLookupDynamicToken lookup_dynamic = NULL;
4596
4597 void
4598 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
4599 {
4600         lookup_dynamic = func;
4601 }
4602
4603 gpointer
4604 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
4605 {
4606         MonoClass *handle_class;
4607
4608         return lookup_dynamic (image, token, &handle_class);
4609 }
4610
4611 gpointer
4612 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class)
4613 {
4614         return lookup_dynamic (image, token, handle_class);
4615 }
4616
4617 static MonoGetCachedClassInfo get_cached_class_info = NULL;
4618
4619 void
4620 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
4621 {
4622         get_cached_class_info = func;
4623 }
4624
4625 static gboolean
4626 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
4627 {
4628         if (!get_cached_class_info)
4629                 return FALSE;
4630         else
4631                 return get_cached_class_info (klass, res);
4632 }
4633
4634 void
4635 mono_install_get_class_from_name (MonoGetClassFromName func)
4636 {
4637         get_class_from_name = func;
4638 }
4639
4640 MonoImage*
4641 mono_class_get_image (MonoClass *klass)
4642 {
4643         return klass->image;
4644 }
4645
4646 /**
4647  * mono_class_get_element_class:
4648  * @klass: the MonoClass to act on
4649  *
4650  * Returns: the element class of an array or an enumeration.
4651  */
4652 MonoClass*
4653 mono_class_get_element_class (MonoClass *klass)
4654 {
4655         return klass->element_class;
4656 }
4657
4658 /**
4659  * mono_class_is_valuetype:
4660  * @klass: the MonoClass to act on
4661  *
4662  * Returns: true if the MonoClass represents a ValueType.
4663  */
4664 gboolean
4665 mono_class_is_valuetype (MonoClass *klass)
4666 {
4667         return klass->valuetype;
4668 }
4669
4670 /**
4671  * mono_class_is_enum:
4672  * @klass: the MonoClass to act on
4673  *
4674  * Returns: true if the MonoClass represents an enumeration.
4675  */
4676 gboolean
4677 mono_class_is_enum (MonoClass *klass)
4678 {
4679         return klass->enumtype;
4680 }
4681
4682 /**
4683  * mono_class_enum_basetype:
4684  * @klass: the MonoClass to act on
4685  *
4686  * Returns: the underlying type representation for an enumeration.
4687  */
4688 MonoType*
4689 mono_class_enum_basetype (MonoClass *klass)
4690 {
4691         return klass->enum_basetype;
4692 }
4693
4694 /**
4695  * mono_class_get_parent
4696  * @klass: the MonoClass to act on
4697  *
4698  * Returns: the parent class for this class.
4699  */
4700 MonoClass*
4701 mono_class_get_parent (MonoClass *klass)
4702 {
4703         return klass->parent;
4704 }
4705
4706 /**
4707  * mono_class_get_nesting_type;
4708  * @klass: the MonoClass to act on
4709  *
4710  * Returns: the container type where this type is nested or NULL if this type is not a nested type.
4711  */
4712 MonoClass*
4713 mono_class_get_nesting_type (MonoClass *klass)
4714 {
4715         return klass->nested_in;
4716 }
4717
4718 /**
4719  * mono_class_get_rank:
4720  * @klass: the MonoClass to act on
4721  *
4722  * Returns: the rank for the array (the number of dimensions).
4723  */
4724 int
4725 mono_class_get_rank (MonoClass *klass)
4726 {
4727         return klass->rank;
4728 }
4729
4730 /**
4731  * mono_class_get_flags:
4732  * @klass: the MonoClass to act on
4733  *
4734  * The type flags from the TypeDef table from the metadata.
4735  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
4736  * different values.
4737  *
4738  * Returns: the flags from the TypeDef table.
4739  */
4740 guint32
4741 mono_class_get_flags (MonoClass *klass)
4742 {
4743         return klass->flags;
4744 }
4745
4746 /**
4747  * mono_class_get_name
4748  * @klass: the MonoClass to act on
4749  *
4750  * Returns: the name of the class.
4751  */
4752 const char*
4753 mono_class_get_name (MonoClass *klass)
4754 {
4755         return klass->name;
4756 }
4757
4758 /**
4759  * mono_class_get_namespace:
4760  * @klass: the MonoClass to act on
4761  *
4762  * Returns: the namespace of the class.
4763  */
4764 const char*
4765 mono_class_get_namespace (MonoClass *klass)
4766 {
4767         return klass->name_space;
4768 }
4769
4770 /**
4771  * mono_class_get_type:
4772  * @klass: the MonoClass to act on
4773  *
4774  * This method returns the internal Type representation for the class.
4775  *
4776  * Returns: the MonoType from the class.
4777  */
4778 MonoType*
4779 mono_class_get_type (MonoClass *klass)
4780 {
4781         return &klass->byval_arg;
4782 }
4783
4784 /**
4785  * mono_class_get_type_token
4786  * @klass: the MonoClass to act on
4787  *
4788  * This method returns type token for the class.
4789  *
4790  * Returns: the type token for the class.
4791  */
4792 guint32
4793 mono_class_get_type_token (MonoClass *klass)
4794 {
4795   return klass->type_token;
4796 }
4797
4798 /**
4799  * mono_class_get_byref_type:
4800  * @klass: the MonoClass to act on
4801  *
4802  * 
4803  */
4804 MonoType*
4805 mono_class_get_byref_type (MonoClass *klass)
4806 {
4807         return &klass->this_arg;
4808 }
4809
4810 /**
4811  * mono_class_num_fields:
4812  * @klass: the MonoClass to act on
4813  *
4814  * Returns: the number of static and instance fields in the class.
4815  */
4816 int
4817 mono_class_num_fields (MonoClass *klass)
4818 {
4819         return klass->field.count;
4820 }
4821
4822 /**
4823  * mono_class_num_methods:
4824  * @klass: the MonoClass to act on
4825  *
4826  * Returns: the number of methods in the class.
4827  */
4828 int
4829 mono_class_num_methods (MonoClass *klass)
4830 {
4831         return klass->method.count;
4832 }
4833
4834 /**
4835  * mono_class_num_properties
4836  * @klass: the MonoClass to act on
4837  *
4838  * Returns: the number of properties in the class.
4839  */
4840 int
4841 mono_class_num_properties (MonoClass *klass)
4842 {
4843         mono_class_setup_properties (klass);
4844
4845         return klass->property.count;
4846 }
4847
4848 /**
4849  * mono_class_num_events:
4850  * @klass: the MonoClass to act on
4851  *
4852  * Returns: the number of events in the class.
4853  */
4854 int
4855 mono_class_num_events (MonoClass *klass)
4856 {
4857         mono_class_setup_events (klass);
4858
4859         return klass->event.count;
4860 }
4861
4862 /**
4863  * mono_class_get_fields:
4864  * @klass: the MonoClass to act on
4865  *
4866  * This routine is an iterator routine for retrieving the fields in a class.
4867  *
4868  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4869  * iterate over all of the elements.  When no more values are
4870  * available, the return value is NULL.
4871  *
4872  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
4873  */
4874 MonoClassField*
4875 mono_class_get_fields (MonoClass* klass, gpointer *iter)
4876 {
4877         MonoClassField* field;
4878         if (!iter)
4879                 return NULL;
4880         mono_class_setup_fields_locking (klass);
4881         if (!*iter) {
4882                 /* start from the first */
4883                 if (klass->field.count) {
4884                         return *iter = &klass->fields [0];
4885                 } else {
4886                         /* no fields */
4887                         return NULL;
4888                 }
4889         }
4890         field = *iter;
4891         field++;
4892         if (field < &klass->fields [klass->field.count]) {
4893                 return *iter = field;
4894         }
4895         return NULL;
4896 }
4897
4898 /**
4899  * mono_class_get_methods
4900  * @klass: the MonoClass to act on
4901  *
4902  * This routine is an iterator routine for retrieving the fields in a class.
4903  *
4904  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4905  * iterate over all of the elements.  When no more values are
4906  * available, the return value is NULL.
4907  *
4908  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
4909  */
4910 MonoMethod*
4911 mono_class_get_methods (MonoClass* klass, gpointer *iter)
4912 {
4913         MonoMethod** method;
4914         if (!iter)
4915                 return NULL;
4916         if (!klass->inited)
4917                 mono_class_init (klass);
4918         if (!*iter) {
4919                 mono_class_setup_methods (klass);
4920                 /* start from the first */
4921                 if (klass->method.count) {
4922                         *iter = &klass->methods [0];
4923                         return klass->methods [0];
4924                 } else {
4925                         /* no method */
4926                         return NULL;
4927                 }
4928         }
4929         method = *iter;
4930         method++;
4931         if (method < &klass->methods [klass->method.count]) {
4932                 *iter = method;
4933                 return *method;
4934         }
4935         return NULL;
4936 }
4937
4938 /**
4939  * mono_class_get_properties:
4940  * @klass: the MonoClass to act on
4941  *
4942  * This routine is an iterator routine for retrieving the properties in a class.
4943  *
4944  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4945  * iterate over all of the elements.  When no more values are
4946  * available, the return value is NULL.
4947  *
4948  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
4949  */
4950 MonoProperty*
4951 mono_class_get_properties (MonoClass* klass, gpointer *iter)
4952 {
4953         MonoProperty* property;
4954         if (!iter)
4955                 return NULL;
4956         if (!klass->inited)
4957                 mono_class_init (klass);
4958         if (!*iter) {
4959                 mono_class_setup_properties (klass);
4960                 /* start from the first */
4961                 if (klass->property.count) {
4962                         return *iter = &klass->properties [0];
4963                 } else {
4964                         /* no fields */
4965                         return NULL;
4966                 }
4967         }
4968         property = *iter;
4969         property++;
4970         if (property < &klass->properties [klass->property.count]) {
4971                 return *iter = property;
4972         }
4973         return NULL;
4974 }
4975
4976 /**
4977  * mono_class_get_events:
4978  * @klass: the MonoClass to act on
4979  *
4980  * This routine is an iterator routine for retrieving the properties in a class.
4981  *
4982  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4983  * iterate over all of the elements.  When no more values are
4984  * available, the return value is NULL.
4985  *
4986  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
4987  */
4988 MonoEvent*
4989 mono_class_get_events (MonoClass* klass, gpointer *iter)
4990 {
4991         MonoEvent* event;
4992         if (!iter)
4993                 return NULL;
4994         if (!klass->inited)
4995                 mono_class_init (klass);
4996         if (!*iter) {
4997                 mono_class_setup_events (klass);
4998                 /* start from the first */
4999                 if (klass->event.count) {
5000                         return *iter = &klass->events [0];
5001                 } else {
5002                         /* no fields */
5003                         return NULL;
5004                 }
5005         }
5006         event = *iter;
5007         event++;
5008         if (event < &klass->events [klass->event.count]) {
5009                 return *iter = event;
5010         }
5011         return NULL;
5012 }
5013
5014 /**
5015  * mono_class_get_interfaces
5016  * @klass: the MonoClass to act on
5017  *
5018  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
5019  *
5020  * You must pass a gpointer that points to zero and is treated as an opaque handle to
5021  * iterate over all of the elements.  When no more values are
5022  * available, the return value is NULL.
5023  *
5024  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
5025  */
5026 MonoClass*
5027 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
5028 {
5029         MonoClass** iface;
5030         if (!iter)
5031                 return NULL;
5032         if (!klass->inited)
5033                 mono_class_init (klass);
5034         if (!*iter) {
5035                 /* start from the first */
5036                 if (klass->interface_count) {
5037                         *iter = &klass->interfaces [0];
5038                         return klass->interfaces [0];
5039                 } else {
5040                         /* no interface */
5041                         return NULL;
5042                 }
5043         }
5044         iface = *iter;
5045         iface++;
5046         if (iface < &klass->interfaces [klass->interface_count]) {
5047                 *iter = iface;
5048                 return *iface;
5049         }
5050         return NULL;
5051 }
5052
5053 /**
5054  * mono_class_get_nested_types
5055  * @klass: the MonoClass to act on
5056  *
5057  * This routine is an iterator routine for retrieving the nested types of a class.
5058  *
5059  * You must pass a gpointer that points to zero and is treated as an opaque handle to
5060  * iterate over all of the elements.  When no more values are
5061  * available, the return value is NULL.
5062  *
5063  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
5064  */
5065 MonoClass*
5066 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
5067 {
5068         GList *item;
5069         if (!iter)
5070                 return NULL;
5071         if (!klass->inited)
5072                 mono_class_init (klass);
5073         if (!*iter) {
5074                 /* start from the first */
5075                 if (klass->nested_classes) {
5076                         *iter = klass->nested_classes;
5077                         return klass->nested_classes->data;
5078                 } else {
5079                         /* no nested types */
5080                         return NULL;
5081                 }
5082         }
5083         item = *iter;
5084         item = item->next;
5085         if (item) {
5086                 *iter = item;
5087                 return item->data;
5088         }
5089         return NULL;
5090 }
5091
5092 /**
5093  * mono_field_get_name:
5094  * @field: the MonoClassField to act on
5095  *
5096  * Returns: the name of the field.
5097  */
5098 const char*
5099 mono_field_get_name (MonoClassField *field)
5100 {
5101         return field->name;
5102 }
5103
5104 /**
5105  * mono_field_get_type:
5106  * @field: the MonoClassField to act on
5107  *
5108  * Returns: MonoType of the field.
5109  */
5110 MonoType*
5111 mono_field_get_type (MonoClassField *field)
5112 {
5113         return field->type;
5114 }
5115
5116 /**
5117  * mono_field_get_type:
5118  * @field: the MonoClassField to act on
5119  *
5120  * Returns: MonoClass where the field was defined.
5121  */
5122 MonoClass*
5123 mono_field_get_parent (MonoClassField *field)
5124 {
5125         return field->parent;
5126 }
5127
5128 /**
5129  * mono_field_get_flags;
5130  * @field: the MonoClassField to act on
5131  *
5132  * The metadata flags for a field are encoded using the
5133  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
5134  *
5135  * Returns: the flags for the field.
5136  */
5137 guint32
5138 mono_field_get_flags (MonoClassField *field)
5139 {
5140         return field->type->attrs;
5141 }
5142
5143 /**
5144  * mono_field_get_data;
5145  * @field: the MonoClassField to act on
5146  *
5147  * Returns: pointer to the metadata constant value or to the field
5148  * data if it has an RVA flag.
5149  */
5150 const char *
5151 mono_field_get_data  (MonoClassField *field)
5152 {
5153   return field->data;
5154 }
5155
5156 /**
5157  * mono_property_get_name: 
5158  * @prop: the MonoProperty to act on
5159  *
5160  * Returns: the name of the property
5161  */
5162 const char*
5163 mono_property_get_name (MonoProperty *prop)
5164 {
5165         return prop->name;
5166 }
5167
5168 /**
5169  * mono_property_get_set_method
5170  * @prop: the MonoProperty to act on.
5171  *
5172  * Returns: the setter method of the property (A MonoMethod)
5173  */
5174 MonoMethod*
5175 mono_property_get_set_method (MonoProperty *prop)
5176 {
5177         return prop->set;
5178 }
5179
5180 /**
5181  * mono_property_get_get_method
5182  * @prop: the MonoProperty to act on.
5183  *
5184  * Returns: the setter method of the property (A MonoMethod)
5185  */
5186 MonoMethod*
5187 mono_property_get_get_method (MonoProperty *prop)
5188 {
5189         return prop->get;
5190 }
5191
5192 /**
5193  * mono_property_get_parent:
5194  * @prop: the MonoProperty to act on.
5195  *
5196  * Returns: the MonoClass where the property was defined.
5197  */
5198 MonoClass*
5199 mono_property_get_parent (MonoProperty *prop)
5200 {
5201         return prop->parent;
5202 }
5203
5204 /**
5205  * mono_property_get_flags:
5206  * @prop: the MonoProperty to act on.
5207  *
5208  * The metadata flags for a property are encoded using the
5209  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
5210  *
5211  * Returns: the flags for the property.
5212  */
5213 guint32
5214 mono_property_get_flags (MonoProperty *prop)
5215 {
5216         return prop->attrs;
5217 }
5218
5219 /**
5220  * mono_event_get_name:
5221  * @event: the MonoEvent to act on
5222  *
5223  * Returns: the name of the event.
5224  */
5225 const char*
5226 mono_event_get_name (MonoEvent *event)
5227 {
5228         return event->name;
5229 }
5230
5231 /**
5232  * mono_event_get_add_method:
5233  * @event: The MonoEvent to act on.
5234  *
5235  * Returns: the @add' method for the event (a MonoMethod).
5236  */
5237 MonoMethod*
5238 mono_event_get_add_method (MonoEvent *event)
5239 {
5240         return event->add;
5241 }
5242
5243 /**
5244  * mono_event_get_remove_method:
5245  * @event: The MonoEvent to act on.
5246  *
5247  * Returns: the @remove method for the event (a MonoMethod).
5248  */
5249 MonoMethod*
5250 mono_event_get_remove_method (MonoEvent *event)
5251 {
5252         return event->remove;
5253 }
5254
5255 /**
5256  * mono_event_get_raise_method:
5257  * @event: The MonoEvent to act on.
5258  *
5259  * Returns: the @raise method for the event (a MonoMethod).
5260  */
5261 MonoMethod*
5262 mono_event_get_raise_method (MonoEvent *event)
5263 {
5264         return event->raise;
5265 }
5266
5267 /**
5268  * mono_event_get_parent:
5269  * @event: the MonoEvent to act on.
5270  *
5271  * Returns: the MonoClass where the event is defined.
5272  */
5273 MonoClass*
5274 mono_event_get_parent (MonoEvent *event)
5275 {
5276         return event->parent;
5277 }
5278
5279 /**
5280  * mono_event_get_flags
5281  * @event: the MonoEvent to act on.
5282  *
5283  * The metadata flags for an event are encoded using the
5284  * EVENT_* constants.  See the tabledefs.h file for details.
5285  *
5286  * Returns: the flags for the event.
5287  */
5288 guint32
5289 mono_event_get_flags (MonoEvent *event)
5290 {
5291         return event->attrs;
5292 }
5293
5294 /**
5295  * mono_class_get_method_from_name:
5296  * @klass: where to look for the method
5297  * @name_space: name of the method
5298  * @param_count: number of parameters. -1 for any number.
5299  *
5300  * Obtains a MonoMethod with a given name and number of parameters.
5301  * It only works if there are no multiple signatures for any given method name.
5302  */
5303 MonoMethod *
5304 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
5305 {
5306         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
5307 }
5308
5309 /**
5310  * mono_class_get_method_from_name_flags:
5311  * @klass: where to look for the method
5312  * @name_space: name of the method
5313  * @param_count: number of parameters. -1 for any number.
5314  * @flags: flags which must be set in the method
5315  *
5316  * Obtains a MonoMethod with a given name and number of parameters.
5317  * It only works if there are no multiple signatures for any given method name.
5318  */
5319 MonoMethod *
5320 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
5321 {
5322         MonoMethod *res = NULL;
5323         int i;
5324
5325         mono_class_init (klass);
5326
5327         if (klass->methods) {
5328                 mono_class_setup_methods (klass);
5329                 for (i = 0; i < klass->method.count; ++i) {
5330                         MonoMethod *method = klass->methods [i];
5331
5332                         if (method->name[0] == name [0] && 
5333                                 !strcmp (name, method->name) &&
5334                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
5335                                 ((method->flags & flags) == flags)) {
5336                                 res = method;
5337                                 break;
5338                         }
5339                 }
5340         }
5341         else {
5342                 /* Search directly in the metadata to avoid calling setup_methods () */
5343                 for (i = 0; i < klass->method.count; ++i) {
5344                         guint32 cols [MONO_METHOD_SIZE];
5345                         MonoMethod *method;
5346
5347                         /* class->method.first points into the methodptr table */
5348                         mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
5349
5350                         if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
5351                                 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
5352                                 if ((param_count == -1) || mono_method_signature (method)->param_count == param_count) {
5353                                         res = method;
5354                                         break;
5355                                 }
5356                         }
5357                 }
5358         }
5359
5360         return res;
5361 }
5362
5363 /**
5364  * mono_class_set_failure:
5365  * @klass: class in which the failure was detected
5366  * @ex_type: the kind of exception/error to be thrown (later)
5367  * @ex_data: exception data (specific to each type of exception/error)
5368  *
5369  * Keep a detected failure informations in the class for later processing.
5370  * Note that only the first failure is kept.
5371  */
5372 gboolean
5373 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
5374 {
5375         if (klass->exception_type)
5376                 return FALSE;
5377         klass->exception_type = ex_type;
5378         klass->exception_data = ex_data;
5379         return TRUE;
5380 }
5381
5382 /**
5383  * mono_classes_init:
5384  *
5385  * Initialize the resources used by this module.
5386  */
5387 void
5388 mono_classes_init (void)
5389 {
5390 }
5391
5392 /**
5393  * mono_classes_cleanup:
5394  *
5395  * Free the resources used by this module.
5396  */
5397 void
5398 mono_classes_cleanup (void)
5399 {
5400         IOffsetInfo *cached_info, *next;
5401
5402         if (global_interface_bitset)
5403                 mono_bitset_free (global_interface_bitset);
5404
5405         for (cached_info = cached_offset_info; cached_info;) {
5406                 next = cached_info->next;
5407
5408                 g_free (cached_info);
5409                 cached_info = next;
5410         }
5411 }
5412
5413 /**
5414  * mono_class_get_exception_for_failure:
5415  * @klass: class in which the failure was detected
5416  *
5417  * Return a constructed MonoException than the caller can then throw
5418  * using mono_raise_exception - or NULL if no failure is present (or
5419  * doesn't result in an exception).
5420  */
5421 MonoException*
5422 mono_class_get_exception_for_failure (MonoClass *klass)
5423 {
5424         switch (klass->exception_type) {
5425         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
5426                 MonoDomain *domain = mono_domain_get ();
5427                 MonoSecurityManager* secman = mono_security_manager_get_methods ();
5428                 MonoMethod *method = klass->exception_data;
5429                 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
5430                 MonoObject *exc = NULL;
5431                 gpointer args [4];
5432
5433                 args [0] = &error;
5434                 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
5435                 args [2] = mono_type_get_object (domain, &klass->byval_arg);
5436                 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
5437
5438                 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
5439                 return (MonoException*) exc;
5440         }
5441         case MONO_EXCEPTION_TYPE_LOAD:
5442                 return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
5443
5444         default: {
5445                 MonoLoaderError *error;
5446                 MonoException *ex;
5447                 
5448                 error = mono_loader_get_last_error ();
5449                 if (error != NULL){
5450                         ex = mono_loader_error_prepare_exception (error);
5451                         return ex;
5452                 }
5453                 
5454                 /* TODO - handle other class related failures */
5455                 return NULL;
5456         }
5457         }
5458 }