2005-05-13 Atsushi Enomoto <atsushi@ximian.com>
[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 Ximian, Inc.
8  *
9  * Possible Optimizations:
10  *     in mono_class_create, do not allocate the class right away,
11  *     but wait until you know the size of the FieldMap, so that
12  *     the class embeds directly the FieldMap after the vtable.
13  *
14  * 
15  */
16 #include <config.h>
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/cil-coff.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/mono-debug-debugger.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/os/gc_wrapper.h>
38
39 MonoStats mono_stats;
40
41 gboolean mono_print_vtable = FALSE;
42
43 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
44 static void mono_class_create_generic_2 (MonoGenericClass *gclass);
45 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
46
47 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
48 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
49
50 MonoClass *
51 mono_class_from_typeref (MonoImage *image, guint32 type_token)
52 {
53         guint32 cols [MONO_TYPEREF_SIZE];
54         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
55         guint32 idx;
56         const char *name, *nspace;
57         MonoClass *res;
58         MonoAssembly **references;
59         
60         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
61
62         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
63         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
64
65         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
66         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
67         case MONO_RESOLTION_SCOPE_MODULE:
68                 if (!idx)
69                         g_error ("null ResolutionScope not yet handled");
70                 /* a typedef in disguise */
71                 return mono_class_from_name (image, nspace, name);
72         case MONO_RESOLTION_SCOPE_MODULEREF:
73                 return mono_class_from_name (image->modules [idx - 1], nspace, name);
74         case MONO_RESOLTION_SCOPE_TYPEREF: {
75                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
76                 GList *tmp;
77                 mono_class_init (enclosing);
78                 for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
79                         res = tmp->data;
80                         if (strcmp (res->name, name) == 0)
81                                 return res;
82                 }
83                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
84                 return NULL;
85         }
86         case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
87                 break;
88         }
89
90         references = image->references;
91         if (!references [idx-1])
92                 mono_assembly_load_reference (image, idx - 1);
93         if (references [idx - 1] == (gpointer)-1)
94                 return NULL;
95
96         image = references [idx-1]->image;
97
98         return mono_class_from_name (image, nspace, name);
99 }
100
101 static inline MonoType*
102 dup_type (MonoType* t, const MonoType *original)
103 {
104         MonoType *r = g_new0 (MonoType, 1);
105         *r = *t;
106         r->attrs = original->attrs;
107         r->byref = original->byref;
108         if (t->type == MONO_TYPE_PTR)
109                 t->data.type = dup_type (t->data.type, original->data.type);
110         mono_stats.generics_metadata_size += sizeof (MonoType);
111         return r;
112 }
113
114 static void
115 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
116                             gboolean include_ns, gboolean include_arity,
117                             gboolean nested_plus)
118 {
119         MonoClass *klass;
120         
121         switch (type->type) {
122         case MONO_TYPE_ARRAY: {
123                 int i, rank = type->data.array->rank;
124
125                 mono_type_get_name_recurse (
126                         &type->data.array->eklass->byval_arg, str,
127                         FALSE, include_ns, include_arity, nested_plus);
128                 g_string_append_c (str, '[');
129                 for (i = 1; i < rank; i++)
130                         g_string_append_c (str, ',');
131                 g_string_append_c (str, ']');
132                 break;
133         }
134         case MONO_TYPE_SZARRAY:
135                 mono_type_get_name_recurse (
136                         &type->data.klass->byval_arg, str, FALSE, include_ns, include_arity,
137                         nested_plus);
138                 g_string_append (str, "[]");
139                 break;
140         case MONO_TYPE_PTR:
141                 mono_type_get_name_recurse (
142                         type->data.type, str, FALSE, include_ns, include_arity, nested_plus);
143                 g_string_append_c (str, '*');
144                 break;
145         default:
146                 klass = mono_class_from_mono_type (type);
147                 if (klass->nested_in) {
148                         mono_type_get_name_recurse (
149                                 &klass->nested_in->byval_arg, str, TRUE, include_ns, include_arity,
150                                 nested_plus);
151                         if (nested_plus)
152                                 g_string_append_c (str, '+');
153                         else
154                                 g_string_append_c (str, '.');
155                 }
156                 if (include_ns && *klass->name_space) {
157                         g_string_append (str, klass->name_space);
158                         g_string_append_c (str, '.');
159                 }
160                 if (!include_arity) {
161                         char *s = strchr (klass->name, '`');
162                         int len = s ? s - klass->name : strlen (klass->name);
163
164                         g_string_append_len (str, klass->name, len);
165                 } else
166                         g_string_append (str, klass->name);
167                 if (is_recursed)
168                         break;
169                 if (klass->generic_class) {
170                         MonoGenericClass *gclass = klass->generic_class;
171                         int i;
172
173                         g_string_append_c (str, '<');
174                         for (i = 0; i < gclass->inst->type_argc; i++) {
175                                 if (i)
176                                         g_string_append_c (str, ',');
177                                 mono_type_get_name_recurse (
178                                         gclass->inst->type_argv [i], str, FALSE, TRUE, include_arity,
179                                         nested_plus);
180                         }
181                         g_string_append_c (str, '>');
182                 } else if (klass->generic_container) {
183                         int i;
184
185                         g_string_append_c (str, '<');
186                         for (i = 0; i < klass->generic_container->type_argc; i++) {
187                                 if (i)
188                                         g_string_append_c (str, ',');
189                                 g_string_append (str, klass->generic_container->type_params [i].name);
190                         }
191                         g_string_append_c (str, '>');
192                 }
193                 break;
194         }
195 }
196
197 /**
198  * mono_type_get_name:
199  * @type: a type
200  *
201  * Returns: the string representation for type as required by System.Reflection.
202  * The inverse of mono_reflection_parse_type ().
203  */
204 static char*
205 _mono_type_get_name (MonoType *type, gboolean is_recursed, gboolean include_ns,
206                      gboolean include_arity, gboolean nested_plus)
207 {
208         GString* result = g_string_new ("");
209         mono_type_get_name_recurse (
210                 type, result, is_recursed, include_ns, include_arity, nested_plus);
211
212         if (type->byref)
213                 g_string_append_c (result, '&');
214
215         return g_string_free (result, FALSE);
216 }
217
218 char*
219 mono_type_get_name (MonoType *type)
220 {
221         return _mono_type_get_name (type, TRUE, TRUE, TRUE, TRUE);
222 }
223
224 char*
225 mono_type_get_full_name (MonoType *type)
226 {
227         return _mono_type_get_name (type, FALSE, TRUE, TRUE, TRUE);
228 }
229
230 char*
231 mono_class_get_name_full (MonoClass *klass, gboolean include_ns, gboolean include_arity,
232                           gboolean nested_plus)
233 {
234         return _mono_type_get_name (
235                 &klass->byval_arg, FALSE, include_ns, include_arity, nested_plus);
236 }
237
238 MonoType*
239 mono_type_get_underlying_type (MonoType *type)
240 {
241         switch (type->type) {
242         case MONO_TYPE_VALUETYPE:
243                 if (type->data.klass->enumtype)
244                         return type->data.klass->enum_basetype;
245                 break;
246         case MONO_TYPE_GENERICINST:
247                 return mono_type_get_underlying_type (&type->data.generic_class->container_class->byval_arg);
248         default:
249                 break;
250         }
251
252         return type;
253 }
254
255 gboolean
256 mono_class_is_open_constructed_type (MonoType *t)
257 {
258         switch (t->type) {
259         case MONO_TYPE_VAR:
260         case MONO_TYPE_MVAR:
261                 return TRUE;
262         case MONO_TYPE_SZARRAY:
263                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
264         case MONO_TYPE_ARRAY:
265                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
266         case MONO_TYPE_PTR:
267                 return mono_class_is_open_constructed_type (t->data.type);
268         case MONO_TYPE_GENERICINST: {
269                 MonoGenericClass *gclass = t->data.generic_class;
270                 int i;
271
272                 if (mono_class_is_open_constructed_type (&gclass->container_class->byval_arg))
273                         return TRUE;
274                 for (i = 0; i < gclass->inst->type_argc; i++)
275                         if (mono_class_is_open_constructed_type (gclass->inst->type_argv [i]))
276                                 return TRUE;
277                 return FALSE;
278         }
279         default:
280                 return FALSE;
281         }
282 }
283
284 static MonoGenericClass *
285 inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
286 {
287         MonoGenericClass *ngclass, *cached;
288
289         if (ogclass->is_dynamic) {
290                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
291                 ngclass = &dgclass->generic_class;
292                 ngclass->is_dynamic = 1;
293         } else
294                 ngclass = g_new0 (MonoGenericClass, 1);
295
296         *ngclass = *ogclass;
297
298         ngclass->inst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
299
300         ngclass->klass = NULL;
301
302         ngclass->context = g_new0 (MonoGenericContext, 1);
303         ngclass->context->container = context->container;
304         ngclass->context->gclass = ngclass;
305
306         mono_loader_lock ();
307         cached = mono_metadata_lookup_generic_class (ngclass);
308         mono_loader_unlock ();
309         if (cached) {
310                 g_free (ngclass);
311                 return cached;
312         }
313
314         mono_class_create_generic (ngclass);
315
316         return ngclass;
317 }
318
319 static MonoType*
320 inflate_generic_type (MonoType *type, MonoGenericContext *context)
321 {
322         switch (type->type) {
323         case MONO_TYPE_MVAR:
324                 if (context->gmethod && context->gmethod->inst->type_argv)
325                         return dup_type (
326                                 context->gmethod->inst->type_argv [type->data.generic_param->num],
327                                 type);
328                 else
329                         return NULL;
330         case MONO_TYPE_VAR:
331                 if (context->gclass)
332                         return dup_type (
333                                 context->gclass->inst->type_argv [type->data.generic_param->num],
334                                 type);
335                 else
336                         return NULL;
337         case MONO_TYPE_SZARRAY: {
338                 MonoClass *eclass = type->data.klass;
339                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
340                 if (!inflated)
341                         return NULL;
342                 nt = dup_type (type, type);
343                 nt->data.klass = mono_class_from_mono_type (inflated);
344                 return nt;
345         }
346         case MONO_TYPE_ARRAY: {
347                 MonoClass *eclass = type->data.array->eklass;
348                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
349                 if (!inflated)
350                         return NULL;
351                 nt = dup_type (type, type);
352                 nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
353                 nt->data.array->eklass = mono_class_from_mono_type (inflated);
354                 return nt;
355         }
356         case MONO_TYPE_GENERICINST: {
357                 MonoGenericClass *ngclass = inflate_generic_class (type->data.generic_class, context);
358                 MonoType *nt = dup_type (type, type);
359                 nt->data.generic_class = ngclass;
360                 return nt;
361         }
362         case MONO_TYPE_CLASS:
363         case MONO_TYPE_VALUETYPE: {
364                 MonoClass *klass = type->data.klass;
365                 MonoGenericClass *gclass;
366                 MonoType *nt;
367
368                 if (!klass->generic_container)
369                         return NULL;
370
371                 gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
372
373                 nt = dup_type (type, type);
374                 nt->type = MONO_TYPE_GENERICINST;
375                 nt->data.generic_class = gclass;
376                 return nt;
377         }
378         default:
379                 return NULL;
380         }
381         return NULL;
382 }
383
384 MonoType*
385 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
386 {
387         MonoType *inflated = inflate_generic_type (type, context);
388
389         if (!inflated)
390                 return dup_type (type, type);
391
392         mono_stats.inflated_type_count++;
393         return inflated;
394 }
395
396 MonoMethodSignature*
397 mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericContext *context)
398 {
399         MonoMethodSignature *res;
400         gboolean is_open;
401         int i;
402
403         if (!context)
404                 return sig;
405
406         res = mono_metadata_signature_alloc (image, sig->param_count);
407         res->ret = mono_class_inflate_generic_type (sig->ret, context);
408         is_open = mono_class_is_open_constructed_type (res->ret);
409         for (i = 0; i < sig->param_count; ++i) {
410                 res->params [i] = mono_class_inflate_generic_type (sig->params [i], context);
411                 if (!is_open)
412                         is_open = mono_class_is_open_constructed_type (res->params [i]);
413         }
414         res->hasthis = sig->hasthis;
415         res->explicit_this = sig->explicit_this;
416         res->call_convention = sig->call_convention;
417         res->generic_param_count = sig->generic_param_count;
418         res->sentinelpos = sig->sentinelpos;
419         res->has_type_parameters = is_open;
420         res->is_inflated = 1;
421         return res;
422 }
423
424 static MonoMethodHeader*
425 inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
426 {
427         MonoMethodHeader *res;
428         int i;
429         res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
430         res->code = header->code;
431         res->code_size = header->code_size;
432         res->max_stack = header->max_stack;
433         res->num_clauses = header->num_clauses;
434         res->init_locals = header->init_locals;
435         res->num_locals = header->num_locals;
436         res->clauses = header->clauses;
437         for (i = 0; i < header->num_locals; ++i)
438                 res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context);
439         return res;
440 }
441
442 static MonoGenericContext *
443 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
444 {
445         MonoGenericContext *res = g_new0 (MonoGenericContext, 1);
446
447         res->container = context->container;
448
449         if (context->gclass)
450                 res->gclass = inflate_generic_class (context->gclass, inflate_with);
451
452         if (context->gmethod) {
453                 res->gmethod = g_new0 (MonoGenericMethod, 1);
454
455                 res->gmethod->container = context->gmethod->container;
456                 res->gmethod->inst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
457         } else
458                 res->gmethod = inflate_with->gmethod;
459
460         return res;
461 }
462
463 MonoMethod*
464 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context,
465                                    MonoClass *klass)
466 {
467         MonoMethodInflated *result;
468
469         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
470             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
471                 return method;
472
473         if (method->is_inflated || mono_method_signature (method)->is_inflated) {
474                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
475
476                 context = inflate_generic_context (imethod->context, context);
477                 method = imethod->declaring;
478         }
479
480         mono_stats.inflated_method_count++;
481
482         result = g_new0 (MonoMethodInflated, 1);
483         result->nmethod = *(MonoMethodNormal*)method;
484         result->nmethod.method.is_inflated = 1;
485         result->context = context;
486         result->declaring = method;
487
488         if (result->nmethod.method.klass->generic_class)
489                 result->nmethod.method.klass = result->nmethod.method.klass->generic_class->container_class;
490
491         return (MonoMethod *) result;
492 }
493
494 MonoMethod *
495 mono_get_inflated_method (MonoMethod *method)
496 {
497         MonoMethodInflated *imethod, *res;
498         MonoMethodHeader *mh;
499         MonoType *dtype;
500         MonoClass *rklass;
501
502         if (!method->is_inflated)
503                 return method;
504
505         imethod = (MonoMethodInflated *) method;
506         if (imethod->inflated)
507                 return (MonoMethod *) imethod->inflated;
508
509         mono_stats.inflated_method_count_2++;
510         mono_stats.generics_metadata_size +=
511                 sizeof (MonoMethodInflated) - sizeof (MonoMethodNormal);
512
513         res = g_new0 (MonoMethodInflated, 1);
514         *res = *imethod;
515         res->inflated = imethod->inflated = res;
516
517         mh = mono_method_get_header (method);
518         if (mh)
519                 res->nmethod.header = inflate_generic_header (mh, imethod->context);
520
521         dtype = mono_class_inflate_generic_type (&method->klass->byval_arg, imethod->context);
522         rklass = res->nmethod.method.klass = mono_class_from_mono_type (dtype);
523
524         res->nmethod.method.signature = mono_class_inflate_generic_signature (
525                 method->klass->image, mono_method_signature (method), imethod->context);
526
527         return (MonoMethod *) res;
528 }
529
530 /** 
531  * class_compute_field_layout:
532  * @m: pointer to the metadata.
533  * @class: The class to initialize
534  *
535  * Initializes the class->fields.
536  */
537 static void
538 class_compute_field_layout (MonoClass *class)
539 {
540         MonoImage *m = class->image; 
541         const int top = class->field.count;
542         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
543         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
544         int i, blittable = TRUE, real_size = 0;
545         guint32 rva;
546         guint32 packing_size = 0;
547         gboolean explicit_size;
548         MonoClassField *field;
549
550         if (class->size_inited)
551                 return;
552
553         if (class->parent) {
554                 if (!class->parent->size_inited)
555                         class_compute_field_layout (class->parent);
556                 class->instance_size += class->parent->instance_size;
557                 class->min_align = class->parent->min_align;
558                 /* we use |= since it may have been set already */
559                 class->has_references |= class->parent->has_references;
560                 blittable = class->parent->blittable;
561         } else {
562                 class->instance_size = sizeof (MonoObject);
563                 class->min_align = 1;
564         }
565
566         /* Get the real size */
567         explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
568
569         if (explicit_size) {
570                 g_assert ((packing_size & 0xfffffff0) == 0);
571                 class->packing_size = packing_size;
572                 real_size += class->instance_size;
573         }
574
575         if (!top) {
576                 if (explicit_size && real_size) {
577                         class->instance_size = MAX (real_size, class->instance_size);
578                 }
579                 class->size_inited = 1;
580                 class->blittable = blittable;
581                 return;
582         }
583
584         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
585                 blittable = FALSE;
586
587         /* Prevent infinite loops if the class references itself */
588         class->size_inited = 1;
589
590         class->fields = g_new0 (MonoClassField, top);
591
592         /*
593          * Fetch all the field information.
594          */
595         for (i = 0; i < top; i++){
596                 const char *sig;
597                 guint32 cols [MONO_FIELD_SIZE];
598                 int idx = class->field.first + i;
599                 MonoGenericContainer *container = NULL;
600
601                 field = &class->fields [i];
602                 mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
603                 /* The name is needed for fieldrefs */
604                 field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
605                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
606                 mono_metadata_decode_value (sig, &sig);
607                 /* FIELD signature == 0x06 */
608                 g_assert (*sig == 0x06);
609                 if (class->generic_container)
610                         container = class->generic_container;
611                 else if (class->generic_class) {
612                         container = class->generic_class->container_class->generic_container;
613                         g_assert (container);
614                 }
615                 field->type = mono_metadata_parse_type_full (
616                         m, (MonoGenericContext *) container, MONO_PARSE_FIELD,
617                         cols [MONO_FIELD_FLAGS], sig + 1, &sig);
618                 if (mono_field_is_deleted (field))
619                         continue;
620                 if (class->generic_class) {
621                         field->type = mono_class_inflate_generic_type (
622                                 field->type, class->generic_class->context);
623                         field->type->attrs = cols [MONO_FIELD_FLAGS];
624                 }
625
626                 field->parent = class;
627
628                 /* Only do these checks if we still think this type is blittable */
629                 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
630                         if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
631                                 blittable = FALSE;
632                         } else {
633                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
634                                 if (!field_class || !field_class->blittable)
635                                         blittable = FALSE;
636                         }
637                 }
638
639                 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
640                         mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
641                         if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
642                                 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name);
643                 }
644
645                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
646                         mono_metadata_field_info (m, idx, NULL, &rva, NULL);
647                         if (!rva)
648                                 g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
649                         field->data = mono_image_rva_map (class->image, rva);
650                 }
651
652                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
653                         class->enum_basetype = field->type;
654                         class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
655                         blittable = class->element_class->blittable;
656                 }
657
658                 /* The def_value of fields is compute lazily during vtable creation */
659         }
660
661         if (class == mono_defaults.string_class)
662                 blittable = FALSE;
663
664         class->blittable = blittable;
665
666         if (class->enumtype && !class->enum_basetype) {
667                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
668                         G_BREAKPOINT ();
669         }
670         if (explicit_size && real_size) {
671                 class->instance_size = MAX (real_size, class->instance_size);
672         }
673
674         if (class->generic_container ||
675             (class->generic_class && class->generic_class->inst->is_open))
676                 return;
677
678         mono_class_layout_fields (class);
679 }
680
681 /* useful until we keep track of gc-references in corlib etc. */
682 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
683
684 /*
685  * LOCKING: this is supposed to be called with the loader lock held.
686  */
687 void
688 mono_class_layout_fields (MonoClass *class)
689 {
690         int i;
691         const int top = class->field.count;
692         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
693         guint32 pass, passes, real_size;
694         gboolean gc_aware_layout = FALSE;
695         MonoClassField *field;
696
697         /*
698          * Enable GC aware auto layout: in this mode, reference
699          * fields are grouped together inside objects, increasing collector 
700          * performance.
701          * Requires that all classes whose layout is known to native code be annotated
702          * with [StructLayout (LayoutKind.Sequential)]
703          * Value types have gc_aware_layout disabled by default, as per
704          * what the default is for other runtimes.
705          */
706          /* corlib is missing [StructLayout] directives in many places */
707         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
708                 if (class->image != mono_defaults.corlib &&
709                         class->byval_arg.type != MONO_TYPE_VALUETYPE)
710                         gc_aware_layout = TRUE;
711         }
712
713         /*
714          * Compute field layout and total size (not considering static fields)
715          */
716
717         switch (layout) {
718         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
719         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
720
721                 if (gc_aware_layout)
722                         passes = 2;
723                 else
724                         passes = 1;
725
726                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
727                         passes = 1;
728
729                 if (class->parent)
730                         real_size = class->parent->instance_size;
731                 else
732                         real_size = sizeof (MonoObject);
733
734                 for (pass = 0; pass < passes; ++pass) {
735                         for (i = 0; i < top; i++){
736                                 int size, align;
737                                 field = &class->fields [i];
738
739                                 if (mono_field_is_deleted (field))
740                                         continue;
741                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
742                                         continue;
743
744                                 if (gc_aware_layout) {
745                                         /* 
746                                          * We process fields with reference type in the first pass,
747                                          * and fields with non-reference type in the second pass.
748                                          * We use IS_POINTER instead of IS_REFERENCE because in
749                                          * some internal structures, we store GC_MALLOCed memory
750                                          * in IntPtr fields...
751                                          */
752                                         if (MONO_TYPE_IS_POINTER (field->type)) {
753                                                 if (pass == 1)
754                                                         continue;
755                                         } else {
756                                                 if (pass == 0)
757                                                         continue;
758                                         }
759                                 }
760
761                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
762                                         (strcmp (field->name, "$PRIVATE$") == 0)) {
763                                         /* This field is a hack inserted by MCS to empty structures */
764                                         continue;
765                                 }
766
767                                 size = mono_type_size (field->type, &align);
768                         
769                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
770                                 align = class->packing_size ? MIN (class->packing_size, align): align;
771                                 class->min_align = MAX (align, class->min_align);
772                                 field->offset = real_size;
773                                 field->offset += align - 1;
774                                 field->offset &= ~(align - 1);
775                                 real_size = field->offset + size;
776                                 if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
777                                         class->has_references = TRUE;
778                                 else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
779                                         class->has_references = TRUE;
780                         }
781
782                         class->instance_size = MAX (real_size, class->instance_size);
783        
784                         if (class->instance_size & (class->min_align - 1)) {
785                                 class->instance_size += class->min_align - 1;
786                                 class->instance_size &= ~(class->min_align - 1);
787                         }
788                 }
789                 break;
790         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
791                 real_size = 0;
792                 for (i = 0; i < top; i++) {
793                         int size, align;
794                         field = &class->fields [i];
795
796                         /*
797                          * There must be info about all the fields in a type if it
798                          * uses explicit layout.
799                          */
800
801                         if (mono_field_is_deleted (field))
802                                 continue;
803                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
804                                 continue;
805
806                         if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
807                                 class->has_references = TRUE;
808                         else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
809                                 class->has_references = TRUE;
810                         size = mono_type_size (field->type, &align);
811                         
812                         /*
813                          * When we get here, field->offset is already set by the
814                          * loader (for either runtime fields or fields loaded from metadata).
815                          * The offset is from the start of the object: this works for both
816                          * classes and valuetypes.
817                          */
818                         field->offset += sizeof (MonoObject);
819
820                         /*
821                          * Calc max size.
822                          */
823                         real_size = MAX (real_size, size + field->offset);
824                 }
825                 class->instance_size = MAX (real_size, class->instance_size);
826                 break;
827         }
828
829         class->size_inited = 1;
830
831         /*
832          * Compute static field layout and size
833          */
834         for (i = 0; i < top; i++){
835                 int size, align;
836                 field = &class->fields [i];
837                         
838                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
839                         continue;
840                 if (mono_field_is_deleted (field))
841                         continue;
842
843                 if (MONO_TYPE_IS_REFERENCE (field->type) || IS_GC_REFERENCE (field->type))
844                         class->has_static_refs = TRUE;
845                 else if (field->type->type == MONO_TYPE_VALUETYPE && field->type->data.klass->has_references)
846                         class->has_static_refs = TRUE;
847                 size = mono_type_size (field->type, &align);
848                 field->offset = class->class_size;
849                 field->offset += align - 1;
850                 field->offset &= ~(align - 1);
851                 class->class_size = field->offset + size;
852         }
853 }
854
855 /*
856  * mono_class_setup_methods:
857  *
858  *   Initializes the 'methods' array in the klass.
859  * Calling this method should be avoided if possible since it allocates a lot 
860  * of long-living MonoMethod structures.
861  */
862 void
863 mono_class_setup_methods (MonoClass *class)
864 {
865         int i;
866         MonoMethod **methods;
867
868         if (class->methods || class->generic_class)
869                 return;
870
871         mono_loader_lock ();
872
873         if (class->methods) {
874                 mono_loader_unlock ();
875                 return;
876         }
877
878         //printf ("INIT: %s.%s\n", class->name_space, class->name);
879
880         if (!class->generic_class && !class->methods) {
881                 methods = g_new (MonoMethod*, class->method.count);
882                 for (i = 0; i < class->method.count; ++i) {
883                         methods [i] = mono_get_method (class->image,
884                                                                                    MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
885                 }
886         }
887
888         if (MONO_CLASS_IS_INTERFACE (class))
889                 for (i = 0; i < class->method.count; ++i)
890                         methods [i]->slot = i;
891
892         class->methods = methods;
893
894         mono_loader_unlock ();
895 }
896
897
898 static void
899 mono_class_setup_properties (MonoClass *class)
900 {
901         guint startm, endm, i, j;
902         guint32 cols [MONO_PROPERTY_SIZE];
903         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
904         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
905         MonoProperty *properties;
906
907         if (class->properties)
908                 return;
909
910         mono_loader_lock ();
911
912         if (class->properties) {
913                 mono_loader_unlock ();
914                 return;
915         }
916
917         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
918         class->property.count = class->property.last - class->property.first;
919
920         if (class->property.count)
921                 mono_class_setup_methods (class);
922
923         properties = g_new0 (MonoProperty, class->property.count);
924         for (i = class->property.first; i < class->property.last; ++i) {
925                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
926                 properties [i - class->property.first].parent = class;
927                 properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
928                 properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
929
930                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
931                 for (j = startm; j < endm; ++j) {
932                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
933                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
934                         case METHOD_SEMANTIC_SETTER:
935                                 properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
936                                 break;
937                         case METHOD_SEMANTIC_GETTER:
938                                 properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
939                                 break;
940                         default:
941                                 break;
942                         }
943                 }
944         }
945
946         class->properties = properties;
947
948         mono_loader_unlock ();
949 }
950
951 static void
952 mono_class_setup_events (MonoClass *class)
953 {
954         guint startm, endm, i, j;
955         guint32 cols [MONO_EVENT_SIZE];
956         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
957         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
958
959         if (class->events)
960                 return;
961
962         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
963         class->event.count = class->event.last - class->event.first;
964
965         if (class->event.count)
966                 mono_class_setup_methods (class);
967
968         class->events = g_new0 (MonoEvent, class->event.count);
969         for (i = class->event.first; i < class->event.last; ++i) {
970                 MonoEvent *event = &class->events [i - class->event.first];
971                         
972                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
973                 event->parent = class;
974                 event->attrs = cols [MONO_EVENT_FLAGS];
975                 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
976
977                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
978                 for (j = startm; j < endm; ++j) {
979                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
980                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
981                         case METHOD_SEMANTIC_ADD_ON:
982                                 event->add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
983                                 break;
984                         case METHOD_SEMANTIC_REMOVE_ON:
985                                 event->remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
986                                 break;
987                         case METHOD_SEMANTIC_FIRE:
988                                 event->raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
989                                 break;
990                         case METHOD_SEMANTIC_OTHER: {
991                                 int n = 0;
992
993                                 if (event->other == NULL) {
994                                         event->other = g_new0 (MonoMethod*, 1);
995                                 } else {
996                                         while (event->other [n])
997                                                 n++;
998                                         event->other = g_realloc (event->other, (n + 1) * sizeof (MonoMethod*));
999                                 }
1000                                 event->other [n] = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1001                                 break;
1002                         }
1003                         default:
1004                                 break;
1005                         }
1006                 }
1007         }
1008 }
1009
1010 static guint
1011 mono_get_unique_iid (MonoClass *class)
1012 {
1013         static GHashTable *iid_hash = NULL;
1014         static guint iid = 0;
1015
1016         char *str;
1017         gpointer value;
1018         
1019         g_assert (MONO_CLASS_IS_INTERFACE (class));
1020
1021         mono_loader_lock ();
1022
1023         if (!iid_hash)
1024                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
1025
1026         str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
1027
1028         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
1029                 mono_loader_unlock ();
1030                 g_free (str);
1031                 return GPOINTER_TO_INT (value);
1032         } else {
1033                 g_hash_table_insert (iid_hash, str, GINT_TO_POINTER (iid));
1034                 ++iid;
1035         }
1036
1037         mono_loader_unlock ();
1038
1039         g_assert (iid <= 65535);
1040         return iid - 1;
1041 }
1042
1043 static void
1044 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
1045 {
1046         int i;
1047         MonoClass *ic;
1048         
1049         for (i = 0; i < klass->interface_count; i++) {
1050                 ic = klass->interfaces [i];
1051
1052                 if (*res == NULL)
1053                         *res = g_ptr_array_new ();
1054                 g_ptr_array_add (*res, ic);
1055                 mono_class_init (ic);
1056
1057                 collect_implemented_interfaces_aux (ic, res);
1058         }
1059 }
1060
1061 GPtrArray*
1062 mono_class_get_implemented_interfaces (MonoClass *klass)
1063 {
1064         GPtrArray *res = NULL;
1065
1066         collect_implemented_interfaces_aux (klass, &res);
1067         return res;
1068 }
1069
1070 typedef struct _IOffsetInfo IOffsetInfo;
1071 struct _IOffsetInfo {
1072         IOffsetInfo *next;
1073         int size;
1074         int next_free;
1075         int data [MONO_ZERO_LEN_ARRAY];
1076 };
1077
1078 static IOffsetInfo *cached_offset_info = NULL;
1079 static int next_offset_info_size = 128;
1080
1081 static int*
1082 cache_interface_offsets (int max_iid, int *data)
1083 {
1084         IOffsetInfo *cached_info;
1085         int *cached;
1086         int new_size;
1087         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1088                 cached = cached_info->data;
1089                 while (cached < cached_info->data + cached_info->size && *cached) {
1090                         if (*cached == max_iid) {
1091                                 int i, matched = TRUE;
1092                                 cached++;
1093                                 for (i = 0; i < max_iid; ++i) {
1094                                         if (cached [i] != data [i]) {
1095                                                 matched = FALSE;
1096                                                 break;
1097                                         }
1098                                 }
1099                                 if (matched)
1100                                         return cached;
1101                                 cached += max_iid;
1102                         } else {
1103                                 cached += *cached + 1;
1104                         }
1105                 }
1106         }
1107         /* find a free slot */
1108         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1109                 if (cached_info->size - cached_info->next_free >= max_iid + 1) {
1110                         cached = &cached_info->data [cached_info->next_free];
1111                         *cached++ = max_iid;
1112                         memcpy (cached, data, max_iid * sizeof (int));
1113                         cached_info->next_free += max_iid + 1;
1114                         return cached;
1115                 }
1116         }
1117         /* allocate a new chunk */
1118         if (max_iid + 1 < next_offset_info_size) {
1119                 new_size = next_offset_info_size;
1120                 if (next_offset_info_size < 4096)
1121                         next_offset_info_size += next_offset_info_size >> 2;
1122         } else {
1123                 new_size = max_iid + 1;
1124         }
1125         cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
1126         cached_info->size = new_size;
1127         /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
1128         cached = &cached_info->data [0];
1129         *cached++ = max_iid;
1130         memcpy (cached, data, max_iid * sizeof (int));
1131         cached_info->next_free += max_iid + 1;
1132         cached_info->next = cached_offset_info;
1133         cached_offset_info = cached_info;
1134         return cached;
1135 }
1136
1137 static int
1138 setup_interface_offsets (MonoClass *class, int cur_slot)
1139 {
1140         MonoClass *k, *ic;
1141         int i, max_iid;
1142         int *cached_data;
1143         GPtrArray *ifaces;
1144
1145         /* compute maximum number of slots and maximum interface id */
1146         max_iid = 0;
1147         for (k = class; k ; k = k->parent) {
1148                 for (i = 0; i < k->interface_count; i++) {
1149                         ic = k->interfaces [i];
1150
1151                         if (!ic->inited)
1152                                 mono_class_init (ic);
1153
1154                         if (max_iid < ic->interface_id)
1155                                 max_iid = ic->interface_id;
1156                 }
1157                 ifaces = mono_class_get_implemented_interfaces (k);
1158                 if (ifaces) {
1159                         for (i = 0; i < ifaces->len; ++i) {
1160                                 ic = g_ptr_array_index (ifaces, i);
1161                                 if (max_iid < ic->interface_id)
1162                                         max_iid = ic->interface_id;
1163                         }
1164                         g_ptr_array_free (ifaces, TRUE);
1165                 }
1166         }
1167
1168         if (MONO_CLASS_IS_INTERFACE (class)) {
1169                 if (max_iid < class->interface_id)
1170                         max_iid = class->interface_id;
1171         }
1172         class->max_interface_id = max_iid;
1173         /* compute vtable offset for interfaces */
1174         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
1175
1176         for (i = 0; i <= max_iid; i++)
1177                 class->interface_offsets [i] = -1;
1178
1179         ifaces = mono_class_get_implemented_interfaces (class);
1180         if (ifaces) {
1181                 for (i = 0; i < ifaces->len; ++i) {
1182                         ic = g_ptr_array_index (ifaces, i);
1183                         class->interface_offsets [ic->interface_id] = cur_slot;
1184                         cur_slot += ic->method.count;
1185                 }
1186                 g_ptr_array_free (ifaces, TRUE);
1187         }
1188
1189         for (k = class->parent; k ; k = k->parent) {
1190                 ifaces = mono_class_get_implemented_interfaces (k);
1191                 if (ifaces) {
1192                         for (i = 0; i < ifaces->len; ++i) {
1193                                 ic = g_ptr_array_index (ifaces, i);
1194
1195                                 if (class->interface_offsets [ic->interface_id] == -1) {
1196                                         int io = k->interface_offsets [ic->interface_id];
1197
1198                                         g_assert (io >= 0);
1199
1200                                         class->interface_offsets [ic->interface_id] = io;
1201                                 }
1202                         }
1203                         g_ptr_array_free (ifaces, TRUE);
1204                 }
1205         }
1206
1207         if (MONO_CLASS_IS_INTERFACE (class))
1208                 class->interface_offsets [class->interface_id] = cur_slot;
1209
1210         cached_data = cache_interface_offsets (max_iid + 1, class->interface_offsets);
1211         g_free (class->interface_offsets);
1212         class->interface_offsets = cached_data;
1213
1214         return cur_slot;
1215 }
1216
1217 void
1218 mono_class_setup_vtable (MonoClass *class)
1219 {
1220         MonoMethod **overrides;
1221         int onum = 0;
1222
1223         if (class->vtable)
1224                 return;
1225
1226         mono_class_setup_methods (class);
1227
1228         if (MONO_CLASS_IS_INTERFACE (class))
1229                 return;
1230
1231         mono_loader_lock ();
1232
1233         if (class->vtable) {
1234                 mono_loader_unlock ();
1235                 return;
1236         }
1237
1238         overrides = mono_class_get_overrides (class->image, class->type_token, &onum);  
1239         mono_class_setup_vtable_general (class, overrides, onum);
1240         g_free (overrides);
1241
1242         mono_loader_unlock ();
1243 }
1244
1245 static void
1246 setup_generic_vtable (MonoClass *class, MonoMethod **overrides, int onum)
1247 {
1248         MonoClass *gklass = class->generic_class->container_class;
1249         MonoGenericContext *gcontext = class->generic_class->context;
1250         int i;
1251
1252         mono_class_init (gklass);
1253         class->vtable_size = gklass->vtable_size;
1254
1255         class->vtable = g_new0 (gpointer, class->vtable_size);
1256         memcpy (class->vtable, gklass->vtable,  sizeof (gpointer) * class->vtable_size);
1257
1258         for (i = 0; i < class->vtable_size; i++) {
1259                 MonoMethod *m = class->vtable [i];
1260
1261                 if (!m)
1262                         continue;
1263
1264                 m = mono_class_inflate_generic_method (m, gcontext, class);
1265                 class->vtable [i] = mono_get_inflated_method (m);
1266         }
1267
1268         class->max_interface_id = gklass->max_interface_id;
1269         class->interface_offsets = g_new0 (gpointer, gklass->max_interface_id + 1);
1270         memcpy (class->interface_offsets, gklass->interface_offsets,
1271                 sizeof (gpointer) * (gklass->max_interface_id + 1));
1272 }
1273
1274 /*
1275  * LOCKING: this is supposed to be called with the loader lock held.
1276  */
1277 void
1278 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum)
1279 {
1280         MonoClass *k, *ic;
1281         MonoMethod **vtable;
1282         int i, max_vtsize = 0, max_iid, cur_slot = 0;
1283         GPtrArray *ifaces;
1284         GHashTable *override_map = NULL;
1285         gboolean security_enabled = mono_is_security_manager_active ();
1286
1287         if (class->vtable)
1288                 return;
1289
1290         if (class->generic_class) {
1291                 setup_generic_vtable (class, overrides, onum);
1292                 return;
1293         }
1294
1295         ifaces = mono_class_get_implemented_interfaces (class);
1296         if (ifaces) {
1297                 for (i = 0; i < ifaces->len; i++) {
1298                         MonoClass *ic = g_ptr_array_index (ifaces, i);
1299                         max_vtsize += ic->method.count;
1300                 }
1301                 g_ptr_array_free (ifaces, TRUE);
1302         }
1303         
1304         if (class->parent) {
1305                 mono_class_init (class->parent);
1306                 mono_class_setup_vtable (class->parent);
1307                 max_vtsize += class->parent->vtable_size;
1308                 cur_slot = class->parent->vtable_size;
1309         }
1310
1311         max_vtsize += class->method.count;
1312
1313         vtable = alloca (sizeof (gpointer) * max_vtsize);
1314         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
1315
1316         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
1317
1318         cur_slot = setup_interface_offsets (class, cur_slot);
1319         max_iid = class->max_interface_id;
1320
1321         if (class->parent && class->parent->vtable_size)
1322                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
1323
1324         /* override interface methods */
1325         for (i = 0; i < onum; i++) {
1326                 MonoMethod *decl = overrides [i*2];
1327                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
1328                         int dslot;
1329                         mono_class_setup_methods (decl->klass);
1330                         g_assert (decl->slot != -1);
1331                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
1332                         vtable [dslot] = overrides [i*2 + 1];
1333                         vtable [dslot]->slot = dslot;
1334                         if (!override_map)
1335                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1336
1337                         g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
1338                 }
1339         }
1340
1341         for (k = class; k ; k = k->parent) {
1342                 int nifaces = 0;
1343
1344                 ifaces = mono_class_get_implemented_interfaces (k);
1345                 if (ifaces)
1346                         nifaces = ifaces->len;
1347                 for (i = 0; i < nifaces; i++) {
1348                         int j, l, io;
1349
1350                         ic = g_ptr_array_index (ifaces, i);
1351                         io = k->interface_offsets [ic->interface_id];
1352
1353                         g_assert (io >= 0);
1354                         g_assert (io <= max_vtsize);
1355
1356                         if (k == class) {
1357                                 mono_class_setup_methods (ic);
1358                                 for (l = 0; l < ic->method.count; l++) {
1359                                         MonoMethod *im = ic->methods [l];                                               
1360
1361                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1362                                                 continue;
1363
1364                                         for (j = 0; j < class->method.count; ++j) {
1365                                                 MonoMethod *cm = class->methods [j];
1366                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1367                                                     !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
1368                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
1369                                                         continue;
1370                                                 if (!strcmp(cm->name, im->name) && 
1371                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1372
1373                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1374                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1375                                                                 mono_secman_inheritancedemand_method (cm, im);
1376                                                         }
1377
1378                                                         g_assert (io + l <= max_vtsize);
1379                                                         vtable [io + l] = cm;
1380                                                 }
1381                                         }
1382                                 }
1383                         } else {
1384                                 /* already implemented */
1385                                 if (io >= k->vtable_size)
1386                                         continue;
1387                         }
1388                                 
1389                         for (l = 0; l < ic->method.count; l++) {
1390                                 MonoMethod *im = ic->methods [l];                                               
1391                                 MonoClass *k1;
1392
1393                                 g_assert (io + l <= max_vtsize);
1394
1395                                 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1396                                         continue;
1397                                         
1398                                 for (k1 = class; k1; k1 = k1->parent) {
1399                                         for (j = 0; j < k1->method.count; ++j) {
1400                                                 MonoMethod *cm = k1->methods [j];
1401
1402                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1403                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
1404                                                         continue;
1405                                                 
1406                                                 if (!strcmp(cm->name, im->name) && 
1407                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1408
1409                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1410                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1411                                                                 mono_secman_inheritancedemand_method (cm, im);
1412                                                         }
1413
1414                                                         g_assert (io + l <= max_vtsize);
1415                                                         vtable [io + l] = cm;
1416                                                         break;
1417                                                 }
1418                                                 
1419                                         }
1420                                         g_assert (io + l <= max_vtsize);
1421                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1422                                                 break;
1423                                 }
1424                         }
1425
1426                         for (l = 0; l < ic->method.count; l++) {
1427                                 MonoMethod *im = ic->methods [l];                                               
1428                                 char *qname, *fqname, *cname, *the_cname;
1429                                 MonoClass *k1;
1430                                 
1431                                 if (vtable [io + l])
1432                                         continue;
1433
1434                                 if (ic->generic_class) {
1435                                         MonoClass *the_ic = ic->generic_class->container_class;
1436                                         the_cname = _mono_type_get_name (&ic->byval_arg, FALSE, TRUE, FALSE, TRUE);
1437                                         cname = the_cname;
1438                                 } else {
1439                                         the_cname = NULL;
1440                                         cname = (char*)ic->name;
1441                                 }
1442                                         
1443                                 qname = g_strconcat (cname, ".", im->name, NULL);
1444                                 if (ic->name_space && ic->name_space [0])
1445                                         fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
1446                                 else
1447                                         fqname = NULL;
1448
1449                                 for (k1 = class; k1; k1 = k1->parent) {
1450                                         for (j = 0; j < k1->method.count; ++j) {
1451                                                 MonoMethod *cm = k1->methods [j];
1452
1453                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1454                                                         continue;
1455
1456                                                 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
1457                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1458
1459                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1460                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1461                                                                 mono_secman_inheritancedemand_method (cm, im);
1462                                                         }
1463
1464                                                         g_assert (io + l <= max_vtsize);
1465                                                         vtable [io + l] = cm;
1466                                                         break;
1467                                                 }
1468                                         }
1469                                 }
1470                                 g_free (the_cname);
1471                                 g_free (qname);
1472                                 g_free (fqname);
1473                         }
1474
1475                         
1476                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
1477                                 for (l = 0; l < ic->method.count; l++) {
1478                                         char *msig;
1479                                         MonoMethod *im = ic->methods [l];
1480                                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
1481                                                         continue;
1482                                         g_assert (io + l <= max_vtsize);
1483
1484                                         /* 
1485                                          * If one of our parents already implements this interface
1486                                          * we can inherit the implementation.
1487                                          */
1488                                         if (!(vtable [io + l])) {
1489                                                 MonoClass *parent = class->parent;
1490
1491                                                 if ((ic->interface_id <= parent->max_interface_id) && 
1492                                                         (parent->interface_offsets [ic->interface_id]) &&
1493                                                         parent->vtable)
1494                                                         vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
1495                                         }
1496
1497                                         if (!(vtable [io + l])) {
1498                                                 for (j = 0; j < onum; ++j) {
1499                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
1500                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
1501                                                 }
1502                                                 msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
1503                                                 printf ("no implementation for interface method %s.%s::%s(%s) in class %s.%s\n",
1504                                                         ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
1505                                                 g_free (msig);
1506                                                 for (j = 0; j < class->method.count; ++j) {
1507                                                         MonoMethod *cm = class->methods [j];
1508                                                         msig = mono_signature_get_desc (mono_method_signature (cm), FALSE);
1509                                                         
1510                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
1511                                                         g_free (msig);
1512                                                 }
1513                                                 g_assert_not_reached ();
1514                                         }
1515                                 }
1516                         }
1517                 
1518                         for (l = 0; l < ic->method.count; l++) {
1519                                 MonoMethod *im = vtable [io + l];
1520
1521                                 if (im) {
1522                                         g_assert (io + l <= max_vtsize);
1523                                         if (im->slot < 0) {
1524                                                 /* FIXME: why do we need this ? */
1525                                                 im->slot = io + l;
1526                                                 /* g_assert_not_reached (); */
1527                                         }
1528                                 }
1529                         }
1530                 }
1531                 if (ifaces)
1532                         g_ptr_array_free (ifaces, TRUE);
1533         } 
1534
1535         for (i = 0; i < class->method.count; ++i) {
1536                 MonoMethod *cm;
1537                
1538                 cm = class->methods [i];
1539                 
1540                 /*
1541                  * Non-virtual method have no place in the vtable.
1542                  * This also catches static methods (since they are not virtual).
1543                  */
1544                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1545                         continue;
1546                 
1547                 /*
1548                  * If the method is REUSE_SLOT, we must check in the
1549                  * base class for a method to override.
1550                  */
1551                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
1552                         int slot = -1;
1553                         for (k = class->parent; k ; k = k->parent) {
1554                                 int j;
1555                                 for (j = 0; j < k->method.count; ++j) {
1556                                         MonoMethod *m1 = k->methods [j];
1557                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
1558                                                 continue;
1559                                         if (!strcmp(cm->name, m1->name) && 
1560                                             mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
1561
1562                                                 /* CAS - SecurityAction.InheritanceDemand */
1563                                                 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1564                                                         mono_secman_inheritancedemand_method (cm, m1);
1565                                                 }
1566
1567                                                 slot = k->methods [j]->slot;
1568                                                 g_assert (cm->slot < max_vtsize);
1569                                                 if (!override_map)
1570                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1571                                                 g_hash_table_insert (override_map, m1, cm);
1572                                                 break;
1573                                         }
1574                                 }
1575                                 if (slot >= 0) 
1576                                         break;
1577                         }
1578                         if (slot >= 0)
1579                                 cm->slot = slot;
1580                 }
1581
1582                 if (cm->slot < 0)
1583                         cm->slot = cur_slot++;
1584
1585                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && ! mono_method_signature (cm)->generic_param_count)
1586                         vtable [cm->slot] = cm;
1587         }
1588
1589         /* override non interface methods */
1590         for (i = 0; i < onum; i++) {
1591                 MonoMethod *decl = overrides [i*2];
1592                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
1593                         g_assert (decl->slot != -1);
1594                         vtable [decl->slot] = overrides [i*2 + 1];
1595                         overrides [i * 2 + 1]->slot = decl->slot;
1596                         if (!override_map)
1597                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1598                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
1599                 }
1600         }
1601
1602         /*
1603          * If a method occupies more than one place in the vtable, and it is
1604          * overriden, then change the other occurances too.
1605          */
1606         if (override_map) {
1607                 for (i = 0; i < max_vtsize; ++i)
1608                         if (vtable [i]) {
1609                                 MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]);
1610                                 if (cm)
1611                                         vtable [i] = cm;
1612                         }
1613
1614                 g_hash_table_destroy (override_map);
1615         }
1616
1617         if (class->generic_class) {
1618                 MonoClass *gklass = class->generic_class->container_class;
1619
1620                 mono_class_init (gklass);
1621                 class->vtable_size = gklass->vtable_size;
1622         } else       
1623                 class->vtable_size = cur_slot;
1624
1625         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
1626         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
1627
1628         if (mono_print_vtable) {
1629                 int icount = 0;
1630
1631                 for (i = 0; i <= max_iid; i++)
1632                         if (class->interface_offsets [i] != -1)
1633                                 icount++;
1634
1635                 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space, 
1636                         class->name, class->vtable_size, icount); 
1637
1638                 for (i = 0; i < class->vtable_size; ++i) {
1639                         MonoMethod *cm;
1640                
1641                         cm = vtable [i];
1642                         if (cm) {
1643                                 printf ("  slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
1644                                         cm->klass->name_space, cm->klass->name,
1645                                         cm->name);
1646                         }
1647                 }
1648
1649
1650                 if (icount) {
1651                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
1652                                 class->name, max_iid);
1653         
1654                         for (i = 0; i < class->interface_count; i++) {
1655                                 ic = class->interfaces [i];
1656                                 printf ("  slot %03d(%03d) %s.%s\n",  
1657                                         class->interface_offsets [ic->interface_id],
1658                                         ic->method.count, ic->name_space, ic->name);
1659                         }
1660
1661                         for (k = class->parent; k ; k = k->parent) {
1662                                 for (i = 0; i < k->interface_count; i++) {
1663                                         ic = k->interfaces [i]; 
1664                                         printf ("  slot %03d(%03d) %s.%s\n", 
1665                                                 class->interface_offsets [ic->interface_id],
1666                                                 ic->method.count, ic->name_space, ic->name);
1667                                 }
1668                         }
1669                 }
1670         }
1671 }
1672
1673 /**
1674  * mono_class_init:
1675  * @class: the class to initialize
1676  *
1677  * compute the instance_size, class_size and other infos that cannot be 
1678  * computed at mono_class_get() time. Also compute a generic vtable and 
1679  * the method slot numbers. We use this infos later to create a domain
1680  * specific vtable.  
1681  */
1682 void
1683 mono_class_init (MonoClass *class)
1684 {
1685         int i;
1686         static MonoMethod *default_ghc = NULL;
1687         static MonoMethod *default_finalize = NULL;
1688         static int finalize_slot = -1;
1689         static int ghc_slot = -1;
1690         MonoCachedClassInfo cached_info;
1691
1692         g_assert (class);
1693
1694         if (class->inited)
1695                 return;
1696
1697         /*g_print ("Init class %s\n", class->name);*/
1698
1699         /* We do everything inside the lock to prevent races */
1700         mono_loader_lock ();
1701
1702         if (class->inited) {
1703                 mono_loader_unlock ();
1704                 /* Somebody might have gotten in before us */
1705                 return;
1706         }
1707
1708         if (class->init_pending) {
1709                 /*
1710                  * We might be called recursively from mono_class_from_typeref if
1711                  * one of our fields has a type which is a nested type of this class,
1712                  * and the compiler encodes it as a typeref, like older versions of
1713                  * MS ilasm do.
1714                  */
1715                 if (class->size_inited) {
1716                         mono_loader_unlock ();
1717                         return;
1718                 }
1719
1720                 /* this indicates a cyclic dependency */
1721                 g_error ("pending init %s.%s\n", class->name_space, class->name);
1722         }
1723
1724         class->init_pending = 1;
1725
1726         /* CAS - SecurityAction.InheritanceDemand */
1727         if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
1728                 mono_secman_inheritancedemand_class (class, class->parent);
1729         }
1730
1731         if (mono_debugger_start_class_init_func)
1732                 mono_debugger_start_class_init_func (class);
1733
1734         mono_stats.initialized_class_count++;
1735
1736         if (class->generic_class && !class->generic_class->is_dynamic) {
1737                 MonoGenericClass *gclass = class->generic_class;
1738                 MonoClass *gklass = gclass->container_class;
1739
1740                 mono_stats.generic_class_count++;
1741
1742                 class->method = gklass->method;
1743                 class->field = gklass->field;
1744
1745                 mono_class_create_generic_2 (gclass);
1746
1747                 mono_class_init (gklass);
1748                 mono_class_setup_methods (gklass);
1749                 mono_class_setup_properties (gklass);
1750
1751                 if (MONO_CLASS_IS_INTERFACE (class))
1752                         class->interface_id = mono_get_unique_iid (class);
1753
1754                 g_assert (class->method.count == gklass->method.count);
1755                 class->methods = g_new0 (MonoMethod *, class->method.count);
1756
1757                 for (i = 0; i < class->method.count; i++) {
1758                         MonoMethod *inflated = mono_class_inflate_generic_method (
1759                                 gklass->methods [i], gclass->context, gclass->klass);
1760
1761                         class->methods [i] = mono_get_inflated_method (inflated);
1762                 }
1763
1764                 g_assert (class->field.count == gklass->field.count);
1765                 class->fields = g_new0 (MonoClassField, class->field.count);
1766
1767                 for (i = 0; i < class->field.count; i++) {
1768                         MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
1769                         ifield->generic_type = gklass->fields [i].type;
1770
1771                         class->fields [i] = gklass->fields [i];
1772                         class->fields [i].generic_info = ifield;
1773                         class->fields [i].parent = class;
1774                         class->fields [i].type = mono_class_inflate_generic_type (
1775                                 class->fields [i].type, gclass->context);
1776                 }
1777
1778                 class->property = gklass->property;
1779                 class->properties = g_new0 (MonoProperty, class->property.count);
1780
1781                 for (i = 0; i < class->property.count; i++) {
1782                         MonoProperty *prop = &class->properties [i];
1783
1784                         *prop = gklass->properties [i];
1785
1786                         if (prop->get)
1787                                 prop->get = mono_class_inflate_generic_method (
1788                                         prop->get, gclass->context, gclass->klass);
1789                         if (prop->set)
1790                                 prop->set = mono_class_inflate_generic_method (
1791                                         prop->set, gclass->context, gclass->klass);
1792
1793                         prop->parent = class;
1794                 }
1795
1796                 g_assert (class->interface_count == gklass->interface_count);
1797         }
1798
1799         if (class->parent && !class->parent->inited)
1800                 mono_class_init (class->parent);
1801
1802         if (!class->generic_class) {
1803                 i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
1804                 while (i) {
1805                         MonoClass* nclass;
1806                         guint32 cols [MONO_NESTED_CLASS_SIZE];
1807                         mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
1808                         nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
1809                         class->nested_classes = g_list_prepend (class->nested_classes, nclass);
1810
1811                         i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
1812                 }
1813         }
1814
1815         /*
1816          * Computes the size used by the fields, and their locations
1817          */
1818         if (!class->size_inited)
1819                 class_compute_field_layout (class);
1820
1821         /* initialize method pointers */
1822         if (class->rank) {
1823                 MonoMethod *ctor;
1824                 MonoMethodSignature *sig;
1825                 class->method.count = class->rank > 1? 2: 1;
1826                 sig = mono_metadata_signature_alloc (class->image, class->rank);
1827                 sig->ret = &mono_defaults.void_class->byval_arg;
1828                 sig->pinvoke = TRUE;
1829                 for (i = 0; i < class->rank; ++i)
1830                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
1831
1832                 ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1833                 ctor->klass = class;
1834                 ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1835                 ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1836                 ctor->signature = sig;
1837                 ctor->name = ".ctor";
1838                 ctor->slot = -1;
1839                 class->methods = g_new (MonoMethod*, class->method.count);
1840                 class->methods [0] = ctor;
1841                 if (class->rank > 1) {
1842                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
1843                         sig->ret = &mono_defaults.void_class->byval_arg;
1844                         sig->pinvoke = TRUE;
1845                         for (i = 0; i < class->rank * 2; ++i)
1846                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
1847
1848                         ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1849                         ctor->klass = class;
1850                         ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1851                         ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1852                         ctor->signature = sig;
1853                         ctor->name = ".ctor";
1854                         ctor->slot = -1;
1855                         class->methods [1] = ctor;
1856                 }
1857         }
1858
1859         mono_class_setup_supertypes (class);
1860
1861         if (MONO_CLASS_IS_INTERFACE (class)) {
1862                 class->init_pending = 0;
1863                 class->inited = 1;
1864                 /* 
1865                  * class->interface_offsets is needed for the castclass/isinst code, so
1866                  * we have to setup them for interfaces, too.
1867                  */
1868                 setup_interface_offsets (class, 0);
1869                 mono_loader_unlock ();
1870
1871                 if (mono_debugger_class_init_func)
1872                         mono_debugger_class_init_func (class);
1873
1874                 return;
1875         }
1876
1877         if (!default_ghc) {
1878                 if (class == mono_defaults.object_class) { 
1879                         mono_class_setup_vtable (class);                       
1880                         for (i = 0; i < class->vtable_size; ++i) {
1881                                 MonoMethod *cm = class->vtable [i];
1882                
1883                                 if (!strcmp (cm->name, "GetHashCode")) {
1884                                         ghc_slot = i;
1885                                         break;
1886                                 }
1887                         }
1888
1889                         g_assert (ghc_slot > 0);
1890
1891                         default_ghc = class->vtable [ghc_slot];
1892                 }
1893         }
1894
1895         if (!default_finalize) {
1896                 if (class == mono_defaults.object_class) { 
1897                         mono_class_setup_vtable (class);                       
1898                         for (i = 0; i < class->vtable_size; ++i) {
1899                                 MonoMethod *cm = class->vtable [i];
1900                
1901                                 if (!strcmp (cm->name, "Finalize")) {
1902                                         finalize_slot = i;
1903                                         break;
1904                                 }
1905                         }
1906
1907                         g_assert (finalize_slot > 0);
1908
1909                         default_finalize = class->vtable [finalize_slot];
1910                 }
1911         }
1912
1913         /*
1914          * If possible, avoid the creation of the generic vtable by requesting
1915          * cached info from the runtime.
1916          */
1917         if (mono_class_get_cached_class_info (class, &cached_info)) {
1918                 guint32 cur_slot = 0;
1919
1920                 class->vtable_size = cached_info.vtable_size;
1921                 class->has_finalize = cached_info.has_finalize;
1922                 class->ghcimpl = cached_info.ghcimpl;
1923                 class->has_cctor = cached_info.has_cctor;
1924
1925                 if (class->parent) {
1926                         mono_class_init (class->parent);
1927                         cur_slot = class->parent->vtable_size;
1928                 }
1929
1930                 setup_interface_offsets (class, cur_slot);
1931         }
1932         else {
1933                 mono_class_setup_vtable (class);
1934         
1935                 class->ghcimpl = 1;
1936                 if (class->parent) { 
1937                         if (class->vtable [ghc_slot] == default_ghc) {
1938                                 class->ghcimpl = 0;
1939                         }
1940                 }
1941
1942                 /* Object::Finalize should have empty implemenatation */
1943                 class->has_finalize = 0;
1944                 if (class->parent) { 
1945                         if (class->vtable [finalize_slot] != default_finalize)
1946                                 class->has_finalize = 1;
1947                 }
1948
1949                 for (i = 0; i < class->method.count; ++i) {
1950                         MonoMethod *method = class->methods [i];
1951                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
1952                                 (strcmp (".cctor", method->name) == 0)) {
1953                                 class->has_cctor = 1;
1954                                 break;
1955                         }
1956                 }
1957         }
1958
1959         class->inited = 1;
1960         class->init_pending = 0;
1961         
1962         mono_loader_unlock ();
1963
1964         if (mono_debugger_class_init_func)
1965                 mono_debugger_class_init_func (class);
1966 }
1967
1968 /*
1969  * LOCKING: this assumes the loader lock is held
1970  */
1971 void
1972 mono_class_setup_mono_type (MonoClass *class)
1973 {
1974         const char *name = class->name;
1975         const char *nspace = class->name_space;
1976
1977         if (MONO_CLASS_IS_INTERFACE (class))
1978                 class->interface_id = mono_get_unique_iid (class);
1979
1980         class->this_arg.byref = 1;
1981         class->this_arg.data.klass = class;
1982         class->this_arg.type = MONO_TYPE_CLASS;
1983         class->byval_arg.data.klass = class;
1984         class->byval_arg.type = MONO_TYPE_CLASS;
1985
1986         if (!strcmp (nspace, "System")) {
1987                 if (!strcmp (name, "ValueType")) {
1988                         /*
1989                          * do not set the valuetype bit for System.ValueType.
1990                          * class->valuetype = 1;
1991                          */
1992                         class->blittable = TRUE;
1993                 } else if (!strcmp (name, "Enum")) {
1994                         /*
1995                          * do not set the valuetype bit for System.Enum.
1996                          * class->valuetype = 1;
1997                          */
1998                         class->valuetype = 0;
1999                         class->enumtype = 0;
2000                 } else if (!strcmp (name, "Object")) {
2001                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
2002                 } else if (!strcmp (name, "String")) {
2003                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
2004                 } else if (!strcmp (name, "TypedReference")) {
2005                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
2006                 }
2007         }
2008         
2009         if (class->valuetype) {
2010                 int t = MONO_TYPE_VALUETYPE;
2011                 if (!strcmp (nspace, "System")) {
2012                         switch (*name) {
2013                         case 'B':
2014                                 if (!strcmp (name, "Boolean")) {
2015                                         t = MONO_TYPE_BOOLEAN;
2016                                 } else if (!strcmp(name, "Byte")) {
2017                                         t = MONO_TYPE_U1;
2018                                         class->blittable = TRUE;                                                
2019                                 }
2020                                 break;
2021                         case 'C':
2022                                 if (!strcmp (name, "Char")) {
2023                                         t = MONO_TYPE_CHAR;
2024                                 }
2025                                 break;
2026                         case 'D':
2027                                 if (!strcmp (name, "Double")) {
2028                                         t = MONO_TYPE_R8;
2029                                         class->blittable = TRUE;                                                
2030                                 }
2031                                 break;
2032                         case 'I':
2033                                 if (!strcmp (name, "Int32")) {
2034                                         t = MONO_TYPE_I4;
2035                                         class->blittable = TRUE;
2036                                 } else if (!strcmp(name, "Int16")) {
2037                                         t = MONO_TYPE_I2;
2038                                         class->blittable = TRUE;
2039                                 } else if (!strcmp(name, "Int64")) {
2040                                         t = MONO_TYPE_I8;
2041                                         class->blittable = TRUE;
2042                                 } else if (!strcmp(name, "IntPtr")) {
2043                                         t = MONO_TYPE_I;
2044                                         class->blittable = TRUE;
2045                                 }
2046                                 break;
2047                         case 'S':
2048                                 if (!strcmp (name, "Single")) {
2049                                         t = MONO_TYPE_R4;
2050                                         class->blittable = TRUE;                                                
2051                                 } else if (!strcmp(name, "SByte")) {
2052                                         t = MONO_TYPE_I1;
2053                                         class->blittable = TRUE;
2054                                 }
2055                                 break;
2056                         case 'U':
2057                                 if (!strcmp (name, "UInt32")) {
2058                                         t = MONO_TYPE_U4;
2059                                         class->blittable = TRUE;
2060                                 } else if (!strcmp(name, "UInt16")) {
2061                                         t = MONO_TYPE_U2;
2062                                         class->blittable = TRUE;
2063                                 } else if (!strcmp(name, "UInt64")) {
2064                                         t = MONO_TYPE_U8;
2065                                         class->blittable = TRUE;
2066                                 } else if (!strcmp(name, "UIntPtr")) {
2067                                         t = MONO_TYPE_U;
2068                                         class->blittable = TRUE;
2069                                 }
2070                                 break;
2071                         case 'T':
2072                                 if (!strcmp (name, "TypedReference")) {
2073                                         t = MONO_TYPE_TYPEDBYREF;
2074                                         class->blittable = TRUE;
2075                                 }
2076                                 break;
2077                         case 'V':
2078                                 if (!strcmp (name, "Void")) {
2079                                         t = MONO_TYPE_VOID;
2080                                 }
2081                                 break;
2082                         default:
2083                                 break;
2084                         }
2085                 }
2086                 class->this_arg.type = class->byval_arg.type = t;
2087         }
2088 }
2089
2090 /*
2091  * LOCKING: this assumes the loader lock is held
2092  */
2093 void
2094 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
2095 {
2096         gboolean system_namespace;
2097
2098         system_namespace = !strcmp (class->name_space, "System");
2099
2100         /* if root of the hierarchy */
2101         if (system_namespace && !strcmp (class->name, "Object")) {
2102                 class->parent = NULL;
2103                 class->instance_size = sizeof (MonoObject);
2104                 return;
2105         }
2106         if (!strcmp (class->name, "<Module>")) {
2107                 class->parent = NULL;
2108                 class->instance_size = 0;
2109                 return;
2110         }
2111
2112         if (parent && parent->generic_class)
2113                 mono_class_create_generic_2 (parent->generic_class);
2114
2115         if (!MONO_CLASS_IS_INTERFACE (class)) {
2116                 class->parent = parent;
2117
2118                 if (!parent)
2119                         g_assert_not_reached (); /* FIXME */
2120
2121                 if (parent->generic_class && !parent->name) {
2122                         /*
2123                          * If the parent is a generic instance, we may get
2124                          * called before it is fully initialized, especially
2125                          * before it has its name.
2126                          */
2127                         return;
2128                 }
2129
2130                 class->marshalbyref = parent->marshalbyref;
2131                 class->contextbound  = parent->contextbound;
2132                 class->delegate  = parent->delegate;
2133                 
2134                 if (system_namespace) {
2135                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
2136                                 class->marshalbyref = 1;
2137
2138                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
2139                                 class->contextbound  = 1;
2140
2141                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
2142                                 class->delegate  = 1;
2143                 }
2144
2145                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
2146                                                 (strcmp (class->parent->name_space, "System") == 0)))
2147                         class->valuetype = 1;
2148                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
2149                         class->valuetype = class->enumtype = 1;
2150                 }
2151                 /*class->enumtype = class->parent->enumtype; */
2152                 mono_class_setup_supertypes (class);
2153         } else {
2154                 class->parent = NULL;
2155         }
2156
2157 }
2158
2159 /*
2160  * LOCKING: this assumes the loader lock is held
2161  */
2162 void
2163 mono_class_setup_supertypes (MonoClass *class)
2164 {
2165         int ms;
2166
2167         if (class->supertypes)
2168                 return;
2169
2170         if (class->parent && !class->parent->supertypes)
2171                 mono_class_setup_supertypes (class->parent);
2172         if (class->parent)
2173                 class->idepth = class->parent->idepth + 1;
2174         else
2175                 class->idepth = 1;
2176
2177         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
2178         class->supertypes = g_new0 (MonoClass *, ms);
2179
2180         if (class->parent) {
2181                 class->supertypes [class->idepth - 1] = class;
2182                 memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
2183         } else {
2184                 class->supertypes [0] = class;
2185         }
2186 }       
2187
2188 /*
2189  * If we inherit a type parameter from an outer class, set its owner to that class.
2190  */
2191 static int
2192 set_generic_param_owner (MonoGenericContainer *container, MonoClass *klass, int pos)
2193 {
2194         MonoGenericContainer *gc;
2195         int i;
2196
2197         if (klass->nested_in)
2198                 pos = set_generic_param_owner (container, klass->nested_in, pos);
2199
2200         if (!klass->generic_container)
2201                 return pos;
2202
2203         gc = klass->generic_container;
2204         for (i = pos; i < gc->type_argc; i++)
2205                 container->type_params [i].owner = gc;
2206
2207         return pos + gc->type_argc;
2208 }
2209
2210 static MonoGenericInst *
2211 get_shared_inst (MonoGenericContainer *container)
2212 {
2213         MonoGenericInst *nginst;
2214         int i;
2215
2216         nginst = g_new0 (MonoGenericInst, 1);
2217         nginst->type_argc = container->type_argc;
2218         nginst->type_argv = g_new0 (MonoType *, nginst->type_argc);
2219         nginst->is_reference = 1;
2220         nginst->is_open = 1;
2221
2222         for (i = 0; i < nginst->type_argc; i++) {
2223                 MonoType *t = g_new0 (MonoType, 1);
2224
2225                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2226                 t->data.generic_param = &container->type_params [i];
2227
2228                 nginst->type_argv [i] = t;
2229         }
2230
2231         return mono_metadata_lookup_generic_inst (nginst);
2232 }
2233
2234 MonoGenericClass *
2235 mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
2236 {
2237         MonoGenericClass *gclass;
2238
2239         if (is_dynamic) {
2240                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
2241                 gclass = &dgclass->generic_class;
2242                 gclass->is_dynamic = 1;
2243         } else
2244                 gclass = g_new0 (MonoGenericClass, 1);
2245
2246         gclass->context = &container->context;
2247         gclass->container_class = container->klass;
2248         gclass->inst = get_shared_inst (container);
2249
2250         if (!is_dynamic) {
2251                 MonoGenericClass *cached = mono_metadata_lookup_generic_class (gclass);
2252
2253                 if (cached) {
2254                         g_free (gclass);
2255                         return cached;
2256                 }
2257         }
2258
2259         gclass->klass = container->klass;
2260
2261         return gclass;
2262 }
2263
2264 /**
2265  * @image: context where the image is created
2266  * @type_token:  typedef token
2267  */
2268 static MonoClass *
2269 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
2270 {
2271         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
2272         MonoClass *class, *parent = NULL;
2273         guint32 cols [MONO_TYPEDEF_SIZE];
2274         guint32 cols_next [MONO_TYPEDEF_SIZE];
2275         guint tidx = mono_metadata_token_index (type_token);
2276         MonoGenericContext *context = NULL;
2277         const char *name, *nspace;
2278         guint icount = 0; 
2279         MonoClass **interfaces;
2280
2281         mono_loader_lock ();
2282
2283         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
2284                 mono_loader_unlock ();
2285                 return class;
2286         }
2287
2288         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
2289
2290         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
2291         
2292         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2293         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2294
2295         class = g_malloc0 (sizeof (MonoClass));
2296
2297         class->name = name;
2298         class->name_space = nspace;
2299
2300         class->image = image;
2301         class->type_token = type_token;
2302         class->flags = cols [MONO_TYPEDEF_FLAGS];
2303
2304         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
2305
2306         class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
2307         if (class->generic_container) {
2308                 class->generic_container->klass = class;
2309                 context = &class->generic_container->context;
2310
2311                 context->gclass = mono_get_shared_generic_class (context->container, FALSE);
2312         }
2313
2314         if (cols [MONO_TYPEDEF_EXTENDS])
2315                 parent = mono_class_get_full (
2316                         image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
2317
2318         mono_class_setup_parent (class, parent);
2319
2320         mono_class_setup_mono_type (class);
2321
2322         interfaces = mono_metadata_interfaces_from_typedef_full (image, type_token, &icount, context);
2323
2324         class->interfaces = interfaces;
2325         class->interface_count = icount;
2326
2327         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
2328                 class->unicode = 1;
2329         /* fixme: maybe we must set this on windows 
2330         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
2331                 class->unicode = 1;
2332         */
2333
2334         class->cast_class = class->element_class = class;
2335
2336         /*g_print ("Load class %s\n", name);*/
2337
2338         /*
2339          * Compute the field and method lists
2340          */
2341         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
2342         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
2343
2344         if (tt->rows > tidx){           
2345                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
2346                 class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
2347                 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
2348         } else {
2349                 class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
2350                 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
2351         }
2352
2353         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
2354             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
2355                 class->field.count = class->field.last - class->field.first;
2356         else
2357                 class->field.count = 0;
2358
2359         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
2360                 class->method.count = class->method.last - class->method.first;
2361         else
2362                 class->method.count = 0;
2363
2364         /* reserve space to store vector pointer in arrays */
2365         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
2366                 class->instance_size += 2 * sizeof (gpointer);
2367                 g_assert (class->field.count == 0);
2368         }
2369
2370         if (class->enumtype)
2371                 class_compute_field_layout (class);
2372
2373         if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
2374                 class->nested_in = mono_class_create_from_typedef (image, type_token);
2375
2376         if (class->nested_in && class->generic_container)
2377                 set_generic_param_owner (class->generic_container, class->nested_in, 0);
2378
2379         mono_loader_unlock ();
2380
2381         return class;
2382 }
2383
2384 void
2385 mono_class_create_generic (MonoGenericClass *gclass)
2386 {
2387         MonoClass *klass, *gklass;
2388
2389         if (!gclass->klass)
2390                 gclass->klass = g_malloc0 (sizeof (MonoClass));
2391         klass = gclass->klass;
2392
2393         gklass = gclass->container_class;
2394
2395         klass->nested_in = gklass->nested_in;
2396
2397         klass->name = gklass->name;
2398         klass->name_space = gklass->name_space;
2399         klass->image = gklass->image;
2400         klass->flags = gklass->flags;
2401
2402         klass->generic_class = gclass;
2403
2404         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
2405         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
2406         klass->this_arg.byref = TRUE;
2407
2408         klass->cast_class = klass->element_class = klass;
2409
2410         if (gclass->is_dynamic) {
2411                 klass->instance_size = gklass->instance_size;
2412                 klass->class_size = gklass->class_size;
2413                 klass->size_inited = 1;
2414                 klass->inited = 1;
2415
2416                 klass->valuetype = gklass->valuetype;
2417
2418                 mono_class_setup_supertypes (klass);
2419         }
2420 }
2421
2422 static void
2423 mono_class_create_generic_2 (MonoGenericClass *gclass)
2424 {
2425         MonoClass *klass, *gklass;
2426         GList *list;
2427         int i;
2428
2429         klass = gclass->klass;
2430         gklass = gclass->container_class;
2431
2432         klass->interface_count = gklass->interface_count;
2433         klass->interfaces = g_new0 (MonoClass *, klass->interface_count);
2434         for (i = 0; i < klass->interface_count; i++) {
2435                 MonoType *it = &gklass->interfaces [i]->byval_arg;
2436                 MonoType *inflated = mono_class_inflate_generic_type (it, gclass->context);
2437                 klass->interfaces [i] = mono_class_from_mono_type (inflated);
2438         }
2439
2440         for (list = gklass->nested_classes; list; list = list->next)
2441                 klass->nested_classes = g_list_append (
2442                         klass->nested_classes, list->data);
2443
2444         if (gclass->parent)
2445                 klass->parent = mono_class_from_mono_type (gclass->parent);
2446         else if (gklass->parent) {
2447                 MonoType *inflated = mono_class_inflate_generic_type (&gklass->parent->byval_arg, gclass->context);
2448
2449                 klass->parent = mono_class_from_mono_type (inflated);
2450         }
2451
2452         if (klass->parent)
2453                 mono_class_setup_parent (klass, klass->parent);
2454 }
2455
2456 MonoClass *
2457 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
2458 {
2459         MonoClass *klass, **ptr;
2460         int count, pos, i;
2461
2462         if (param->pklass)
2463                 return param->pklass;
2464
2465         klass = param->pklass = g_new0 (MonoClass, 1);
2466
2467         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2468                 ;
2469
2470         pos = 0;
2471         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
2472                 klass->parent = param->constraints [0];
2473                 pos++;
2474         }
2475
2476         if (count - pos > 0) {
2477                 klass->interface_count = count - pos;
2478                 klass->interfaces = g_new0 (MonoClass *, count - pos);
2479                 for (i = pos; i < count; i++)
2480                         klass->interfaces [i - pos] = param->constraints [i];
2481         }
2482
2483         g_assert (param->name && param->owner);
2484
2485         klass->name = param->name;
2486         klass->name_space = "";
2487         klass->image = image;
2488         klass->cast_class = klass->element_class = klass;
2489         klass->enum_basetype = &klass->element_class->byval_arg;
2490         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
2491
2492         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2493         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
2494         klass->this_arg.byref = TRUE;
2495
2496         mono_class_init (klass);
2497
2498         return klass;
2499 }
2500
2501 static MonoClass *
2502 my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
2503 {
2504         MonoClass *klass;
2505
2506         if (param->pklass)
2507                 return param->pklass;
2508
2509         g_assert (param->owner);
2510
2511         klass = g_new0 (MonoClass, 1);
2512
2513         if (param->name)
2514                 klass->name = param->name;
2515         else
2516                 klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
2517         klass->name_space = "";
2518         klass->image = mono_defaults.corlib;
2519         klass->cast_class = klass->element_class = klass;
2520         klass->enum_basetype = &klass->element_class->byval_arg;
2521         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
2522
2523         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2524         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
2525         klass->this_arg.byref = TRUE;
2526
2527         mono_class_init (klass);
2528
2529         return klass;
2530 }
2531
2532 MonoClass *
2533 mono_ptr_class_get (MonoType *type)
2534 {
2535         MonoClass *result;
2536         MonoClass *el_class;
2537         static GHashTable *ptr_hash = NULL;
2538
2539         mono_loader_lock ();
2540
2541         if (!ptr_hash)
2542                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
2543         el_class = mono_class_from_mono_type (type);
2544         if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
2545                 mono_loader_unlock ();
2546                 return result;
2547         }
2548         result = g_new0 (MonoClass, 1);
2549
2550         result->parent = NULL; /* no parent for PTR types */
2551         result->name_space = el_class->name_space;
2552         result->name = g_strdup_printf ("%s*", el_class->name);
2553         result->image = el_class->image;
2554         result->inited = TRUE;
2555         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2556         /* Can pointers get boxed? */
2557         result->instance_size = sizeof (gpointer);
2558         result->cast_class = result->element_class = el_class;
2559         result->enum_basetype = &result->element_class->byval_arg;
2560         result->blittable = TRUE;
2561
2562         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
2563         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
2564         result->this_arg.byref = TRUE;
2565
2566         mono_class_setup_supertypes (result);
2567
2568         g_hash_table_insert (ptr_hash, el_class, result);
2569
2570         mono_loader_unlock ();
2571
2572         return result;
2573 }
2574
2575 static MonoClass *
2576 mono_fnptr_class_get (MonoMethodSignature *sig)
2577 {
2578         MonoClass *result;
2579         static GHashTable *ptr_hash = NULL;
2580
2581         mono_loader_lock ();
2582
2583         if (!ptr_hash)
2584                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
2585         
2586         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
2587                 mono_loader_unlock ();
2588                 return result;
2589         }
2590         result = g_new0 (MonoClass, 1);
2591
2592         result->parent = NULL; /* no parent for PTR types */
2593         result->name = "System";
2594         result->name_space = "MonoFNPtrFakeClass";
2595         result->image = NULL; /* need to fix... */
2596         result->inited = TRUE;
2597         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
2598         /* Can pointers get boxed? */
2599         result->instance_size = sizeof (gpointer);
2600         result->cast_class = result->element_class = result;
2601         result->blittable = TRUE;
2602
2603         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
2604         result->this_arg.data.method = result->byval_arg.data.method = sig;
2605         result->this_arg.byref = TRUE;
2606         result->enum_basetype = &result->element_class->byval_arg;
2607         result->blittable = TRUE;
2608
2609         mono_class_setup_supertypes (result);
2610
2611         g_hash_table_insert (ptr_hash, sig, result);
2612
2613         mono_loader_unlock ();
2614
2615         return result;
2616 }
2617
2618 MonoClass *
2619 mono_class_from_mono_type (MonoType *type)
2620 {
2621         switch (type->type) {
2622         case MONO_TYPE_OBJECT:
2623                 return type->data.klass? type->data.klass: mono_defaults.object_class;
2624         case MONO_TYPE_VOID:
2625                 return type->data.klass? type->data.klass: mono_defaults.void_class;
2626         case MONO_TYPE_BOOLEAN:
2627                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
2628         case MONO_TYPE_CHAR:
2629                 return type->data.klass? type->data.klass: mono_defaults.char_class;
2630         case MONO_TYPE_I1:
2631                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
2632         case MONO_TYPE_U1:
2633                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
2634         case MONO_TYPE_I2:
2635                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
2636         case MONO_TYPE_U2:
2637                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
2638         case MONO_TYPE_I4:
2639                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
2640         case MONO_TYPE_U4:
2641                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
2642         case MONO_TYPE_I:
2643                 return type->data.klass? type->data.klass: mono_defaults.int_class;
2644         case MONO_TYPE_U:
2645                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
2646         case MONO_TYPE_I8:
2647                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
2648         case MONO_TYPE_U8:
2649                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
2650         case MONO_TYPE_R4:
2651                 return type->data.klass? type->data.klass: mono_defaults.single_class;
2652         case MONO_TYPE_R8:
2653                 return type->data.klass? type->data.klass: mono_defaults.double_class;
2654         case MONO_TYPE_STRING:
2655                 return type->data.klass? type->data.klass: mono_defaults.string_class;
2656         case MONO_TYPE_TYPEDBYREF:
2657                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
2658         case MONO_TYPE_ARRAY:
2659                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
2660         case MONO_TYPE_PTR:
2661                 return mono_ptr_class_get (type->data.type);
2662         case MONO_TYPE_FNPTR:
2663                 return mono_fnptr_class_get (type->data.method);
2664         case MONO_TYPE_SZARRAY:
2665                 return mono_array_class_get (type->data.klass, 1);
2666         case MONO_TYPE_CLASS:
2667         case MONO_TYPE_VALUETYPE:
2668                 return type->data.klass;
2669         case MONO_TYPE_GENERICINST:
2670                 g_assert (type->data.generic_class->klass);
2671                 return type->data.generic_class->klass;
2672         case MONO_TYPE_VAR:
2673                 return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
2674         case MONO_TYPE_MVAR:
2675                 return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
2676         default:
2677                 g_warning ("implement me 0x%02x\n", type->type);
2678                 g_assert_not_reached ();
2679         }
2680         
2681         return NULL;
2682 }
2683
2684 /**
2685  * @image: context where the image is created
2686  * @type_spec:  typespec token
2687  */
2688 static MonoClass *
2689 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec,
2690                                  MonoGenericContext *context)
2691 {
2692         MonoType *type, *inflated;
2693         MonoClass *class;
2694
2695         type = mono_type_create_from_typespec_full (image, context, type_spec);
2696
2697         switch (type->type) {
2698         case MONO_TYPE_ARRAY:
2699                 class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
2700                 break;
2701         case MONO_TYPE_SZARRAY:
2702                 class = mono_array_class_get (type->data.klass, 1);
2703                 break;
2704         case MONO_TYPE_PTR:
2705                 class = mono_ptr_class_get (type->data.type);
2706                 break;
2707         case MONO_TYPE_GENERICINST:
2708                 g_assert (type->data.generic_class->klass);
2709                 class = type->data.generic_class->klass;
2710                 break;
2711         default:
2712                 /* it seems any type can be stored in TypeSpec as well */
2713                 class = mono_class_from_mono_type (type);
2714                 break;
2715         }
2716
2717         if (!class || !context || (!context->gclass && !context->gmethod))
2718                 return class;
2719
2720         inflated = mono_class_inflate_generic_type (&class->byval_arg, context);
2721
2722         return mono_class_from_mono_type (inflated);
2723 }
2724
2725 /**
2726  * mono_bounded_array_class_get:
2727  * @element_class: element class 
2728  * @rank: the dimension of the array class
2729  * @bounded: whenever the array has non-zero bounds
2730  *
2731  * Returns: a class object describing the array with element type @element_type and 
2732  * dimension @rank. 
2733  */
2734 MonoClass *
2735 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
2736 {
2737         MonoImage *image;
2738         MonoClass *class;
2739         MonoClass *parent = NULL;
2740         GSList *list, *rootlist;
2741         int nsize;
2742         char *name;
2743         gboolean corlib_type = FALSE;
2744
2745         g_assert (rank <= 255);
2746
2747         if (rank > 1)
2748                 /* bounded only matters for one-dimensional arrays */
2749                 bounded = FALSE;
2750
2751         image = eclass->image;
2752
2753         mono_loader_lock ();
2754
2755         if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
2756                 for (; list; list = list->next) {
2757                         class = list->data;
2758                         if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
2759                                 mono_loader_unlock ();
2760                                 return class;
2761                         }
2762                 }
2763         }
2764
2765         /* for the building corlib use System.Array from it */
2766         if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
2767                 parent = mono_class_from_name (image, "System", "Array");
2768                 corlib_type = TRUE;
2769         } else {
2770                 parent = mono_defaults.array_class;
2771                 if (!parent->inited)
2772                         mono_class_init (parent);
2773         }
2774
2775         class = g_malloc0 (sizeof (MonoClass));
2776
2777         class->image = image;
2778         class->name_space = eclass->name_space;
2779         nsize = strlen (eclass->name);
2780         name = g_malloc (nsize + 2 + rank);
2781         memcpy (name, eclass->name, nsize);
2782         name [nsize] = '[';
2783         if (rank > 1)
2784                 memset (name + nsize + 1, ',', rank - 1);
2785         name [nsize + rank] = ']';
2786         name [nsize + rank + 1] = 0;
2787         class->name = name;
2788         class->type_token = 0;
2789         /* all arrays are marked serializable and sealed, bug #42779 */
2790         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
2791                 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2792         class->parent = parent;
2793         class->instance_size = mono_class_instance_size (class->parent);
2794         class->class_size = 0;
2795         mono_class_setup_supertypes (class);
2796         if (eclass->generic_class)
2797                 mono_class_init (eclass);
2798         if (!eclass->size_inited)
2799                 class_compute_field_layout (eclass);
2800         class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
2801
2802         class->rank = rank;
2803         
2804         if (eclass->enumtype)
2805                 class->cast_class = eclass->element_class;
2806         else
2807                 class->cast_class = eclass;
2808
2809         class->element_class = eclass;
2810
2811         if ((rank > 1) || bounded) {
2812                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
2813                 class->byval_arg.type = MONO_TYPE_ARRAY;
2814                 class->byval_arg.data.array = at;
2815                 at->eklass = eclass;
2816                 at->rank = rank;
2817                 /* FIXME: complete.... */
2818         } else {
2819                 class->byval_arg.type = MONO_TYPE_SZARRAY;
2820                 class->byval_arg.data.klass = eclass;
2821         }
2822         class->this_arg = class->byval_arg;
2823         class->this_arg.byref = 1;
2824         if (corlib_type) {
2825                 class->inited = 1;
2826         }
2827
2828         list = g_slist_append (rootlist, class);
2829         g_hash_table_insert (image->array_cache, eclass, list);
2830
2831         mono_loader_unlock ();
2832
2833         return class;
2834 }
2835
2836 /**
2837  * mono_array_class_get:
2838  * @element_class: element class 
2839  * @rank: the dimension of the array class
2840  *
2841  * Returns: a class object describing the array with element type @element_type and 
2842  * dimension @rank. 
2843  */
2844 MonoClass *
2845 mono_array_class_get (MonoClass *eclass, guint32 rank)
2846 {
2847         return mono_bounded_array_class_get (eclass, rank, FALSE);
2848 }
2849
2850 /**
2851  * mono_class_instance_size:
2852  * @klass: a class 
2853  * 
2854  * Returns: the size of an object instance
2855  */
2856 gint32
2857 mono_class_instance_size (MonoClass *klass)
2858 {       
2859         if (!klass->size_inited)
2860                 mono_class_init (klass);
2861
2862         g_assert (!klass->generic_container &&
2863                   (!klass->generic_class || !klass->generic_class->inst->is_open));
2864         return klass->instance_size;
2865 }
2866
2867 /**
2868  * mono_class_min_align:
2869  * @klass: a class 
2870  * 
2871  * Returns: minimm alignment requirements 
2872  */
2873 gint32
2874 mono_class_min_align (MonoClass *klass)
2875 {       
2876         if (!klass->size_inited)
2877                 mono_class_init (klass);
2878
2879         return klass->min_align;
2880 }
2881
2882 /**
2883  * mono_class_value_size:
2884  * @klass: a class 
2885  *
2886  * This function is used for value types, and return the
2887  * space and the alignment to store that kind of value object.
2888  *
2889  * Returns: the size of a value of kind @klass
2890  */
2891 gint32
2892 mono_class_value_size      (MonoClass *klass, guint32 *align)
2893 {
2894         gint32 size;
2895
2896         /* fixme: check disable, because we still have external revereces to
2897          * mscorlib and Dummy Objects 
2898          */
2899         /*g_assert (klass->valuetype);*/
2900
2901         size = mono_class_instance_size (klass) - sizeof (MonoObject);
2902
2903         if (align)
2904                 *align = klass->min_align;
2905
2906         return size;
2907 }
2908
2909 /**
2910  * mono_class_data_size:
2911  * @klass: a class 
2912  * 
2913  * Returns: the size of the static class data
2914  */
2915 gint32
2916 mono_class_data_size (MonoClass *klass)
2917 {       
2918         if (!klass->inited)
2919                 mono_class_init (klass);
2920
2921         return klass->class_size;
2922 }
2923
2924 /*
2925  * Auxiliary routine to mono_class_get_field
2926  *
2927  * Takes a field index instead of a field token.
2928  */
2929 static MonoClassField *
2930 mono_class_get_field_idx (MonoClass *class, int idx)
2931 {
2932         if (class->field.count){
2933                 if ((idx >= class->field.first) && (idx < class->field.last)){
2934                         return &class->fields [idx - class->field.first];
2935                 }
2936         }
2937
2938         if (!class->parent)
2939                 return NULL;
2940         
2941         return mono_class_get_field_idx (class->parent, idx);
2942 }
2943
2944 /**
2945  * mono_class_get_field:
2946  * @class: the class to lookup the field.
2947  * @field_token: the field token
2948  *
2949  * Returns: A MonoClassField representing the type and offset of
2950  * the field, or a NULL value if the field does not belong to this
2951  * class.
2952  */
2953 MonoClassField *
2954 mono_class_get_field (MonoClass *class, guint32 field_token)
2955 {
2956         int idx = mono_metadata_token_index (field_token);
2957
2958         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
2959
2960         return mono_class_get_field_idx (class, idx - 1);
2961 }
2962
2963 MonoClassField *
2964 mono_class_get_field_from_name (MonoClass *klass, const char *name)
2965 {
2966         int i;
2967
2968         while (klass) {
2969                 for (i = 0; i < klass->field.count; ++i) {
2970                         if (strcmp (name, klass->fields [i].name) == 0)
2971                                 return &klass->fields [i];
2972                 }
2973                 klass = klass->parent;
2974         }
2975         return NULL;
2976 }
2977
2978 guint32
2979 mono_class_get_field_token (MonoClassField *field)
2980 {
2981         MonoClass *klass = field->parent;
2982         int i;
2983
2984         while (klass) {
2985                 for (i = 0; i < klass->field.count; ++i) {
2986                         if (&klass->fields [i] == field)
2987                                 return mono_metadata_make_token (MONO_TABLE_FIELD, klass->field.first + i + 1);
2988                 }
2989                 klass = klass->parent;
2990         }
2991
2992         g_assert_not_reached ();
2993         return 0;
2994 }
2995
2996 guint32
2997 mono_class_get_event_token (MonoEvent *event)
2998 {
2999         MonoClass *klass = event->parent;
3000         int i;
3001
3002         while (klass) {
3003                 for (i = 0; i < klass->event.count; ++i) {
3004                         if (&klass->events [i] == event)
3005                                 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->event.first + i + 1);
3006                 }
3007                 klass = klass->parent;
3008         }
3009
3010         g_assert_not_reached ();
3011         return 0;
3012 }
3013
3014 void *
3015 mono_vtable_get_static_field_data (MonoVTable *vt)
3016 {
3017         return vt->data;
3018 }
3019
3020 MonoProperty*
3021 mono_class_get_property_from_name (MonoClass *klass, const char *name)
3022 {
3023         while (klass) {
3024                 MonoProperty* p;
3025                 gpointer iter = NULL;
3026                 while ((p = mono_class_get_properties (klass, &iter))) {
3027                         if (! strcmp (name, p->name))
3028                                 return p;
3029                 }
3030                 klass = klass->parent;
3031         }
3032         return NULL;
3033 }
3034
3035 guint32
3036 mono_class_get_property_token (MonoProperty *prop)
3037 {
3038         MonoClass *klass = prop->parent;
3039         while (klass) {
3040                 MonoProperty* p;
3041                 int i = 0;
3042                 gpointer iter = NULL;
3043                 while ((p = mono_class_get_properties (klass, &iter))) {
3044                         if (&klass->properties [i] == prop)
3045                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->property.first + i + 1);
3046                         
3047                         i ++;
3048                 }
3049                 klass = klass->parent;
3050         }
3051
3052         g_assert_not_reached ();
3053         return 0;
3054 }
3055
3056 char *
3057 mono_class_name_from_token (MonoImage *image, guint32 type_token, MonoGenericContext *context)
3058 {
3059         const char *name, *nspace;
3060         if (image->dynamic)
3061                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
3062         
3063         switch (type_token & 0xff000000){
3064         case MONO_TOKEN_TYPE_DEF: {
3065                 guint32 cols [MONO_TYPEDEF_SIZE];
3066                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
3067                 guint tidx = mono_metadata_token_index (type_token);
3068
3069                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
3070                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3071                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3072                 if (strlen (nspace) == 0)
3073                         return g_strdup_printf ("%s", name);
3074                 else
3075                         return g_strdup_printf ("%s.%s", nspace, name);
3076         }
3077
3078         case MONO_TOKEN_TYPE_REF: {
3079                 guint32 cols [MONO_TYPEREF_SIZE];
3080                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
3081
3082                 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
3083                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
3084                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
3085                 if (strlen (nspace) == 0)
3086                         return g_strdup_printf ("%s", name);
3087                 else
3088                         return g_strdup_printf ("%s.%s", nspace, name);
3089         }
3090                 
3091         case MONO_TOKEN_TYPE_SPEC:
3092                 return g_strdup_printf ("Typespec 0x%08x", type_token);
3093         default:
3094                 g_assert_not_reached ();
3095         }
3096
3097         return NULL;
3098 }
3099
3100 /**
3101  * mono_class_get:
3102  * @image: the image where the class resides
3103  * @type_token: the token for the class
3104  * @at: an optional pointer to return the array element type
3105  *
3106  * Returns: the MonoClass that represents @type_token in @image
3107  */
3108 static MonoClass *
3109 _mono_class_get (MonoImage *image, guint32 type_token, MonoGenericContext *context)
3110 {
3111         MonoClass *class = NULL;
3112
3113         if (image->dynamic)
3114                 return mono_lookup_dynamic_token (image, type_token);
3115
3116         switch (type_token & 0xff000000){
3117         case MONO_TOKEN_TYPE_DEF:
3118                 class = mono_class_create_from_typedef (image, type_token);
3119                 break;          
3120         case MONO_TOKEN_TYPE_REF:
3121                 class = mono_class_from_typeref (image, type_token);
3122                 break;
3123         case MONO_TOKEN_TYPE_SPEC:
3124                 class = mono_class_create_from_typespec (image, type_token, context);
3125                 break;
3126         default:
3127                 g_warning ("unknown token type %x", type_token & 0xff000000);
3128                 g_assert_not_reached ();
3129         }
3130
3131         if (!class){
3132                 char *name = mono_class_name_from_token (image, type_token, context);
3133                 g_warning ("The class %s could not be loaded, used in %s (token 0x%08x)", name, image->name, type_token);
3134                 g_free (name);
3135         }
3136
3137         return class;
3138 }
3139
3140 MonoClass *
3141 mono_class_get (MonoImage *image, guint32 type_token)
3142 {
3143         return _mono_class_get (image, type_token, NULL);
3144 }
3145
3146 MonoClass *
3147 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
3148 {
3149         MonoClass *class = _mono_class_get (image, type_token, context);
3150         MonoType *inflated;
3151
3152         if (!class || !context || (!context->gclass && !context->gmethod))
3153                 return class;
3154
3155         switch (class->byval_arg.type) {
3156         case MONO_TYPE_GENERICINST:
3157                 if (!class->generic_class->inst->is_open)
3158                         return class;
3159                 break;
3160         case MONO_TYPE_VAR:
3161         case MONO_TYPE_MVAR:
3162                 break;
3163         default:
3164                 return class;
3165         }
3166
3167         inflated = inflate_generic_type (&class->byval_arg, context);
3168         if (!inflated)
3169                 return class;
3170
3171         return mono_class_from_mono_type (inflated);
3172 }
3173
3174 /**
3175  * mono_class_from_name_case:
3176  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
3177  * @name_space: the type namespace
3178  * @name: the type short name.
3179  *
3180  * Obtains a MonoClass with a given namespace and a given name which
3181  * is located in the given MonoImage.   The namespace and name
3182  * lookups are case insensitive.
3183  *
3184  * You can also pass @NULL to the image, and that will lookup for
3185  * a type with the given namespace and name in all of the loaded
3186  * assemblies: notice that since there might be a name clash in this
3187  * case, passing @NULL is not encouraged if you need a precise type.
3188  *
3189  */
3190 MonoClass *
3191 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
3192 {
3193         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
3194         guint32 cols [MONO_TYPEDEF_SIZE];
3195         const char *n;
3196         const char *nspace;
3197         guint32 i, visib;
3198
3199         /* add a cache if needed */
3200         for (i = 1; i <= t->rows; ++i) {
3201                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
3202                 /* nested types are accessed from the nesting name */
3203                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3204                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
3205                         continue;
3206                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3207                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3208                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
3209                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
3210         }
3211         return NULL;
3212 }
3213
3214 static MonoClass*
3215 return_nested_in (MonoClass *class, char *nested) {
3216         MonoClass *found;
3217         char *s = strchr (nested, '/');
3218         GList *tmp;
3219
3220         if (s) {
3221                 *s = 0;
3222                 s++;
3223         }
3224         for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
3225                 found = tmp->data;
3226                 if (strcmp (found->name, nested) == 0) {
3227                         if (s)
3228                                 return return_nested_in (found, s);
3229                         return found;
3230                 }
3231         }
3232         return NULL;
3233 }
3234
3235
3236 /**
3237  * mono_class_from_name_case:
3238  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
3239  * @name_space: the type namespace
3240  * @name: the type short name.
3241  *
3242  * Obtains a MonoClass with a given namespace and a given name which
3243  * is located in the given MonoImage.   
3244  *
3245  * You can also pass `NULL' to the image, and that will lookup for
3246  * a type with the given namespace and name in all of the loaded
3247  * assemblies: notice that since there might be a name clash in this
3248  * case, passing NULL is not encouraged if you need a precise type.
3249  *
3250  */
3251 MonoClass *
3252 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
3253 {
3254         GHashTable *nspace_table;
3255         MonoImage *loaded_image;
3256         guint32 token = 0;
3257         MonoClass *class;
3258         char *nested;
3259         char buf [1024];
3260
3261         if ((nested = strchr (name, '/'))) {
3262                 int pos = nested - name;
3263                 int len = strlen (name);
3264                 if (len > 1023)
3265                         return NULL;
3266                 memcpy (buf, name, len + 1);
3267                 buf [pos] = 0;
3268                 nested = buf + pos + 1;
3269                 name = buf;
3270         }
3271
3272         mono_loader_lock ();
3273
3274         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
3275
3276         if (nspace_table)
3277                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
3278
3279         mono_loader_unlock ();
3280
3281         if (!token)
3282                 return NULL;
3283
3284         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
3285                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
3286                 guint32 cols [MONO_EXP_TYPE_SIZE];
3287                 guint32 idx, impl;
3288
3289                 idx = mono_metadata_token_index (token);
3290
3291                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
3292
3293                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
3294                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
3295                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
3296                         if (!loaded_image)
3297                                 return NULL;
3298                         class = mono_class_from_name (loaded_image, name_space, name);
3299                         if (nested)
3300                                 return return_nested_in (class, nested);
3301                         return class;
3302                 } else {
3303                         g_error ("not yet implemented");
3304                 }
3305         }
3306
3307         token = MONO_TOKEN_TYPE_DEF | token;
3308
3309         class = mono_class_get (image, token);
3310         if (nested)
3311                 return return_nested_in (class, nested);
3312         return class;
3313 }
3314
3315 gboolean
3316 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
3317                            gboolean check_interfaces)
3318 {
3319  again:
3320         g_assert (klassc->idepth > 0);
3321         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
3322                 if ((klassc->interface_id <= klass->max_interface_id) &&
3323                         (klass->interface_offsets [klassc->interface_id] >= 0))
3324                         return TRUE;
3325         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
3326                 int i;
3327
3328                 for (i = 0; i < klass->interface_count; i ++) {
3329                         MonoClass *ic =  klass->interfaces [i];
3330                         if (ic == klassc)
3331                                 return TRUE;
3332                 }
3333         } else {
3334                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
3335                         return TRUE;
3336         }
3337
3338         /* 
3339          * MS.NET thinks interfaces are a subclass of Object, so we think it as
3340          * well.
3341          */
3342         if (klassc == mono_defaults.object_class)
3343                 return TRUE;
3344
3345         if (klass->generic_class) {
3346                 MonoType *parent = klass->generic_class->parent;
3347                 if (!parent)
3348                         return FALSE;
3349
3350                 if (mono_metadata_type_equal (parent, &klassc->byval_arg))
3351                         return TRUE;
3352                 klass = mono_class_from_mono_type (parent);
3353                 goto again;
3354         }
3355         
3356         return FALSE;
3357 }
3358
3359 gboolean
3360 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
3361 {
3362         if (!klass->inited)
3363                 mono_class_init (klass);
3364
3365         if (!oklass->inited)
3366                 mono_class_init (oklass);
3367
3368         if (klass->generic_class)
3369                 klass = klass->generic_class->container_class;
3370         if (oklass->generic_class)
3371                 oklass = oklass->generic_class->container_class;
3372
3373         if (MONO_CLASS_IS_INTERFACE (klass)) {
3374                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
3375                         return FALSE;
3376
3377                 /* interface_offsets might not be set for dynamic classes */
3378                 if (oklass->reflection_info && !oklass->interface_offsets)
3379                         /* 
3380                          * oklass might be a generic type parameter but they have 
3381                          * interface_offsets set.
3382                          */
3383                         return mono_reflection_call_is_assignable_to (oklass, klass);
3384
3385                 if ((klass->interface_id <= oklass->max_interface_id) &&
3386                     (oklass->interface_offsets [klass->interface_id] != -1))
3387                         return TRUE;
3388         } else
3389                 if (klass->rank) {
3390                         MonoClass *eclass, *eoclass;
3391
3392                         if (oklass->rank != klass->rank)
3393                                 return FALSE;
3394
3395                         /* vectors vs. one dimensional arrays */
3396                         if (oklass->byval_arg.type != klass->byval_arg.type)
3397                                 return FALSE;
3398
3399                         eclass = klass->cast_class;
3400                         eoclass = oklass->cast_class;
3401
3402
3403                         /* 
3404                          * a is b does not imply a[] is b[] when a is a valuetype, and
3405                          * b is a reference type.
3406                          */
3407
3408                         if (eoclass->valuetype) {
3409                                 if ((eclass == mono_defaults.enum_class) || 
3410                                         (eclass == mono_defaults.enum_class->parent) ||
3411                                         (eclass == mono_defaults.object_class))
3412                                         return FALSE;
3413                         }
3414
3415                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
3416                 }
3417         else
3418                 if (klass == mono_defaults.object_class)
3419                         return TRUE;
3420
3421         return mono_class_has_parent (oklass, klass);
3422 }       
3423
3424 /*
3425  * mono_class_get_cctor:
3426  *
3427  *   Returns the static constructor of @klass if it exists, NULL otherwise.
3428  */
3429 MonoMethod*
3430 mono_class_get_cctor (MonoClass *klass)
3431 {
3432         MonoCachedClassInfo cached_info;
3433
3434         if (!klass->has_cctor)
3435                 return NULL;
3436
3437         if (mono_class_get_cached_class_info (klass, &cached_info))
3438                 return mono_get_method (klass->image, cached_info.cctor_token, klass);
3439
3440         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
3441 }
3442
3443 /*
3444  * mono_class_get_finalizer:
3445  *
3446  *   Returns the finalizer method of @klass if it exists, NULL otherwise.
3447  */
3448 MonoMethod*
3449 mono_class_get_finalizer (MonoClass *klass)
3450 {
3451         MonoCachedClassInfo cached_info;
3452         static int finalize_slot = -1;
3453
3454         if (finalize_slot < 0) {
3455                 int i;
3456                 MonoClass* obj_class = mono_get_object_class ();
3457                 mono_class_setup_vtable (obj_class);
3458                 for (i = 0; i < obj_class->vtable_size; ++i) {
3459                         MonoMethod *cm = obj_class->vtable [i];
3460                
3461                         if (!strcmp (mono_method_get_name (cm), "Finalize")) {
3462                                 finalize_slot = i;
3463                                 break;
3464                         }
3465                 }
3466         }
3467
3468         if (!klass->has_finalize)
3469                 return NULL;
3470
3471         if (mono_class_get_cached_class_info (klass, &cached_info))
3472                 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
3473         else {
3474                 mono_class_setup_vtable (klass);
3475                 return klass->vtable [finalize_slot];
3476         }
3477 }
3478
3479 /*
3480  * mono_class_needs_cctor_run:
3481  *
3482  *  Determines whenever the class has a static constructor and whenever it
3483  * needs to be called when executing CALLER.
3484  */
3485 gboolean
3486 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
3487 {
3488         MonoMethod *method;
3489
3490         method = mono_class_get_cctor (klass);
3491         if (method)
3492                 return (method == caller) ? FALSE : TRUE;
3493         else
3494                 return TRUE;
3495 }
3496
3497 /**
3498  * mono_class_array_element_size:
3499  * @klass: 
3500  *
3501  * Returns: the number of bytes an element of type @klass
3502  * uses when stored into an array.
3503  */
3504 gint32
3505 mono_class_array_element_size (MonoClass *klass)
3506 {
3507         MonoType *type = &klass->byval_arg;
3508         
3509 handle_enum:
3510         switch (type->type) {
3511         case MONO_TYPE_I1:
3512         case MONO_TYPE_U1:
3513         case MONO_TYPE_BOOLEAN:
3514                 return 1;
3515         case MONO_TYPE_I2:
3516         case MONO_TYPE_U2:
3517         case MONO_TYPE_CHAR:
3518                 return 2;
3519         case MONO_TYPE_I4:
3520         case MONO_TYPE_U4:
3521         case MONO_TYPE_R4:
3522                 return 4;
3523         case MONO_TYPE_I:
3524         case MONO_TYPE_U:
3525         case MONO_TYPE_PTR:
3526         case MONO_TYPE_CLASS:
3527         case MONO_TYPE_STRING:
3528         case MONO_TYPE_OBJECT:
3529         case MONO_TYPE_SZARRAY:
3530         case MONO_TYPE_ARRAY: 
3531         case MONO_TYPE_VAR:
3532         case MONO_TYPE_MVAR:   
3533                 return sizeof (gpointer);
3534         case MONO_TYPE_I8:
3535         case MONO_TYPE_U8:
3536         case MONO_TYPE_R8:
3537                 return 8;
3538         case MONO_TYPE_VALUETYPE:
3539                 if (type->data.klass->enumtype) {
3540                         type = type->data.klass->enum_basetype;
3541                         klass = klass->element_class;
3542                         goto handle_enum;
3543                 }
3544                 return mono_class_instance_size (klass) - sizeof (MonoObject);
3545         case MONO_TYPE_GENERICINST:
3546                 type = &type->data.generic_class->container_class->byval_arg;
3547                 goto handle_enum;
3548         default:
3549                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
3550         }
3551         return -1;
3552 }
3553
3554 /**
3555  * mono_array_element_size:
3556  * @ac: pointer to a #MonoArrayClass
3557  *
3558  * Returns: the size of single array element.
3559  */
3560 gint32
3561 mono_array_element_size (MonoClass *ac)
3562 {
3563         return mono_class_array_element_size (ac->element_class);
3564 }
3565
3566 gpointer
3567 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
3568               MonoGenericContext *context)
3569 {
3570         if (image->dynamic) {
3571                 MonoClass *tmp_handle_class;
3572                 gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class);
3573
3574                 g_assert (tmp_handle_class);
3575                 if (handle_class)
3576                         *handle_class = tmp_handle_class;
3577
3578                 if (tmp_handle_class == mono_defaults.typehandle_class)
3579                         return &((MonoClass*)obj)->byval_arg;
3580                 else
3581                         return obj;
3582         }
3583
3584         switch (token & 0xff000000) {
3585         case MONO_TOKEN_TYPE_DEF:
3586         case MONO_TOKEN_TYPE_REF: {
3587                 MonoClass *class;
3588                 if (handle_class)
3589                         *handle_class = mono_defaults.typehandle_class;
3590                 class = mono_class_get_full (image, token, context);
3591                 mono_class_init (class);
3592                 /* We return a MonoType* as handle */
3593                 return &class->byval_arg;
3594         }
3595         case MONO_TOKEN_TYPE_SPEC: {
3596                 MonoClass *class;
3597                 if (handle_class)
3598                         *handle_class = mono_defaults.typehandle_class;
3599                 class = mono_class_create_from_typespec (image, token, context);
3600                 mono_class_init (class);
3601                 return &class->byval_arg;
3602         }
3603         case MONO_TOKEN_FIELD_DEF: {
3604                 MonoClass *class;
3605                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
3606                 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
3607                 mono_class_init (class);
3608                 if (handle_class)
3609                         *handle_class = mono_defaults.fieldhandle_class;
3610                 return mono_class_get_field (class, token);
3611         }
3612         case MONO_TOKEN_METHOD_DEF: {
3613                 MonoMethod *meth;
3614                 meth = mono_get_method_full (image, token, NULL, context);
3615                 if (handle_class)
3616                         *handle_class = mono_defaults.methodhandle_class;
3617                 return meth;
3618         }
3619         case MONO_TOKEN_MEMBER_REF: {
3620                 guint32 cols [MONO_MEMBERREF_SIZE];
3621                 const char *sig;
3622                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
3623                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
3624                 mono_metadata_decode_blob_size (sig, &sig);
3625                 if (*sig == 0x6) { /* it's a field */
3626                         MonoClass *klass;
3627                         MonoClassField *field;
3628                         field = mono_field_from_token (image, token, &klass, context);
3629                         if (handle_class)
3630                                 *handle_class = mono_defaults.fieldhandle_class;
3631                         return field;
3632                 } else {
3633                         MonoMethod *meth;
3634                         meth = mono_get_method_full (image, token, NULL, context);
3635                         if (handle_class)
3636                                 *handle_class = mono_defaults.methodhandle_class;
3637                         return meth;
3638                 }
3639         }
3640         default:
3641                 g_warning ("Unknown token 0x%08x in ldtoken", token);
3642                 break;
3643         }
3644         return NULL;
3645 }
3646
3647 /**
3648  * This function might need to call runtime functions so it can't be part
3649  * of the metadata library.
3650  */
3651 static MonoLookupDynamicToken lookup_dynamic = NULL;
3652
3653 void
3654 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
3655 {
3656         lookup_dynamic = func;
3657 }
3658
3659 gpointer
3660 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
3661 {
3662         MonoClass *handle_class;
3663
3664         return lookup_dynamic (image, token, &handle_class);
3665 }
3666
3667 gpointer
3668 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class)
3669 {
3670         return lookup_dynamic (image, token, handle_class);
3671 }
3672
3673 static MonoGetCachedClassInfo get_cached_class_info = NULL;
3674
3675 void
3676 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
3677 {
3678         get_cached_class_info = func;
3679 }
3680
3681 static gboolean
3682 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
3683 {
3684         if (!get_cached_class_info)
3685                 return FALSE;
3686         else
3687                 return get_cached_class_info (klass, res);
3688 }
3689
3690 MonoImage*
3691 mono_class_get_image (MonoClass *klass)
3692 {
3693         return klass->image;
3694 }
3695
3696 /**
3697  * mono_class_get_element_class:
3698  * @klass: the MonoClass to act on
3699  *
3700  * Returns: the element class of an array or an enumeration.
3701  */
3702 MonoClass*
3703 mono_class_get_element_class (MonoClass *klass)
3704 {
3705         return klass->element_class;
3706 }
3707
3708 /**
3709  * mono_class_is_valuetype:
3710  * @klass: the MonoClass to act on
3711  *
3712  * Returns: true if the MonoClass represents a ValueType.
3713  */
3714 gboolean
3715 mono_class_is_valuetype (MonoClass *klass)
3716 {
3717         return klass->valuetype;
3718 }
3719
3720 /**
3721  * mono_class_is_enum:
3722  * @klass: the MonoClass to act on
3723  *
3724  * Returns: true if the MonoClass represents an enumeration.
3725  */
3726 gboolean
3727 mono_class_is_enum (MonoClass *klass)
3728 {
3729         return klass->enumtype;
3730 }
3731
3732 /**
3733  * mono_class_enum_basetype:
3734  * @klass: the MonoClass to act on
3735  *
3736  * Returns: the underlying type representation for an enumeration.
3737  */
3738 MonoType*
3739 mono_class_enum_basetype (MonoClass *klass)
3740 {
3741         return klass->enum_basetype;
3742 }
3743
3744 /**
3745  * mono_class_get_parent
3746  * @klass: the MonoClass to act on
3747  *
3748  * Returns: the parent class for this class.
3749  */
3750 MonoClass*
3751 mono_class_get_parent (MonoClass *klass)
3752 {
3753         return klass->parent;
3754 }
3755
3756 /**
3757  * mono_class_get_nesting_type;
3758  * @klass: the MonoClass to act on
3759  *
3760  * Returns: the container type where this type is nested or NULL if this type is not a nested type.
3761  */
3762 MonoClass*
3763 mono_class_get_nesting_type (MonoClass *klass)
3764 {
3765         return klass->nested_in;
3766 }
3767
3768 /**
3769  * mono_class_get_rank:
3770  * @klass: the MonoClass to act on
3771  *
3772  * Returns: the rank for the array (the number of dimensions).
3773  */
3774 int
3775 mono_class_get_rank (MonoClass *klass)
3776 {
3777         return klass->rank;
3778 }
3779
3780 /**
3781  * mono_class_get_flags:
3782  * @klass: the MonoClass to act on
3783  *
3784  * The type flags from the TypeDef table from the metadata.
3785  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
3786  * different values.
3787  *
3788  * Returns: the flags from the TypeDef table.
3789  */
3790 guint32
3791 mono_class_get_flags (MonoClass *klass)
3792 {
3793         return klass->flags;
3794 }
3795
3796 /**
3797  * mono_class_get_name
3798  * @klass: the MonoClass to act on
3799  *
3800  * Returns: the name of the class.
3801  */
3802 const char*
3803 mono_class_get_name (MonoClass *klass)
3804 {
3805         return klass->name;
3806 }
3807
3808 /**
3809  * mono_class_get_namespace:
3810  * @klass: the MonoClass to act on
3811  *
3812  * Returns: the namespace of the class.
3813  */
3814 const char*
3815 mono_class_get_namespace (MonoClass *klass)
3816 {
3817         return klass->name_space;
3818 }
3819
3820 /**
3821  * mono_class_get_type:
3822  * @klass: the MonoClass to act on
3823  *
3824  * This method returns the internal Type representation for the class.
3825  *
3826  * Returns: the MonoType from the class.
3827  */
3828 MonoType*
3829 mono_class_get_type (MonoClass *klass)
3830 {
3831         return &klass->byval_arg;
3832 }
3833
3834 /**
3835  * mono_class_get_byref_type:
3836  * @klass: the MonoClass to act on
3837  *
3838  * 
3839  */
3840 MonoType*
3841 mono_class_get_byref_type (MonoClass *klass)
3842 {
3843         return &klass->this_arg;
3844 }
3845
3846 /**
3847  * mono_class_num_fields:
3848  * @klass: the MonoClass to act on
3849  *
3850  * Returns: the number of static and instance fields in the class.
3851  */
3852 int
3853 mono_class_num_fields (MonoClass *klass)
3854 {
3855         return klass->field.count;
3856 }
3857
3858 /**
3859  * mono_class_num_methods:
3860  * @klass: the MonoClass to act on
3861  *
3862  * Returns: the number of methods in the class.
3863  */
3864 int
3865 mono_class_num_methods (MonoClass *klass)
3866 {
3867         return klass->method.count;
3868 }
3869
3870 /**
3871  * mono_class_num_properties
3872  * @klass: the MonoClass to act on
3873  *
3874  * Returns: the number of properties in the class.
3875  */
3876 int
3877 mono_class_num_properties (MonoClass *klass)
3878 {
3879         mono_class_setup_properties (klass);
3880
3881         return klass->property.count;
3882 }
3883
3884 /**
3885  * mono_class_num_events:
3886  * @klass: the MonoClass to act on
3887  *
3888  * Returns: the number of events in the class.
3889  */
3890 int
3891 mono_class_num_events (MonoClass *klass)
3892 {
3893         mono_class_setup_events (klass);
3894
3895         return klass->event.count;
3896 }
3897
3898 /**
3899  * mono_class_get_fields:
3900  * @klass: the MonoClass to act on
3901  *
3902  * This routine is an iterator routine for retrieving the fields in a class.
3903  *
3904  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3905  * iterate over all of the elements.  When no more values are
3906  * available, the return value is NULL.
3907  *
3908  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
3909  */
3910 MonoClassField*
3911 mono_class_get_fields (MonoClass* klass, gpointer *iter)
3912 {
3913         MonoClassField* field;
3914         if (!iter)
3915                 return NULL;
3916         if (!klass->inited)
3917                 mono_class_init (klass);
3918         if (!*iter) {
3919                 /* start from the first */
3920                 if (klass->field.count) {
3921                         return *iter = &klass->fields [0];
3922                 } else {
3923                         /* no fields */
3924                         return NULL;
3925                 }
3926         }
3927         field = *iter;
3928         field++;
3929         if (field < &klass->fields [klass->field.count]) {
3930                 return *iter = field;
3931         }
3932         return NULL;
3933 }
3934
3935 /**
3936  * mono_class_get_methods
3937  * @klass: the MonoClass to act on
3938  *
3939  * This routine is an iterator routine for retrieving the fields in a class.
3940  *
3941  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3942  * iterate over all of the elements.  When no more values are
3943  * available, the return value is NULL.
3944  *
3945  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
3946  */
3947 MonoMethod*
3948 mono_class_get_methods (MonoClass* klass, gpointer *iter)
3949 {
3950         MonoMethod** method;
3951         if (!iter)
3952                 return NULL;
3953         if (!klass->inited)
3954                 mono_class_init (klass);
3955         if (!*iter) {
3956                 mono_class_setup_methods (klass);
3957                 /* start from the first */
3958                 if (klass->method.count) {
3959                         *iter = &klass->methods [0];
3960                         return klass->methods [0];
3961                 } else {
3962                         /* no method */
3963                         return NULL;
3964                 }
3965         }
3966         method = *iter;
3967         method++;
3968         if (method < &klass->methods [klass->method.count]) {
3969                 *iter = method;
3970                 return *method;
3971         }
3972         return NULL;
3973 }
3974
3975 /**
3976  * mono_class_get_properties:
3977  * @klass: the MonoClass to act on
3978  *
3979  * This routine is an iterator routine for retrieving the properties in a class.
3980  *
3981  * You must pass a gpointer that points to zero and is treated as an opaque handle to
3982  * iterate over all of the elements.  When no more values are
3983  * available, the return value is NULL.
3984  *
3985  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
3986  */
3987 MonoProperty*
3988 mono_class_get_properties (MonoClass* klass, gpointer *iter)
3989 {
3990         MonoProperty* property;
3991         if (!iter)
3992                 return NULL;
3993         if (!klass->inited)
3994                 mono_class_init (klass);
3995         if (!*iter) {
3996                 mono_class_setup_properties (klass);
3997                 /* start from the first */
3998                 if (klass->property.count) {
3999                         return *iter = &klass->properties [0];
4000                 } else {
4001                         /* no fields */
4002                         return NULL;
4003                 }
4004         }
4005         property = *iter;
4006         property++;
4007         if (property < &klass->properties [klass->property.count]) {
4008                 return *iter = property;
4009         }
4010         return NULL;
4011 }
4012
4013 /**
4014  * mono_class_get_events:
4015  * @klass: the MonoClass to act on
4016  *
4017  * This routine is an iterator routine for retrieving the properties in a class.
4018  *
4019  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4020  * iterate over all of the elements.  When no more values are
4021  * available, the return value is NULL.
4022  *
4023  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
4024  */
4025 MonoEvent*
4026 mono_class_get_events (MonoClass* klass, gpointer *iter)
4027 {
4028         MonoEvent* event;
4029         if (!iter)
4030                 return NULL;
4031         if (!klass->inited)
4032                 mono_class_init (klass);
4033         if (!*iter) {
4034                 mono_class_setup_events (klass);
4035                 /* start from the first */
4036                 if (klass->event.count) {
4037                         return *iter = &klass->events [0];
4038                 } else {
4039                         /* no fields */
4040                         return NULL;
4041                 }
4042         }
4043         event = *iter;
4044         event++;
4045         if (event < &klass->events [klass->event.count]) {
4046                 return *iter = event;
4047         }
4048         return NULL;
4049 }
4050
4051 /**
4052  * mono_class_get_interfaces
4053  * @klass: the MonoClass to act on
4054  *
4055  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4056  *
4057  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4058  * iterate over all of the elements.  When no more values are
4059  * available, the return value is NULL.
4060  *
4061  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
4062  */
4063 MonoClass*
4064 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
4065 {
4066         MonoClass** iface;
4067         if (!iter)
4068                 return NULL;
4069         if (!klass->inited)
4070                 mono_class_init (klass);
4071         if (!*iter) {
4072                 /* start from the first */
4073                 if (klass->interface_count) {
4074                         *iter = &klass->interfaces [0];
4075                         return klass->interfaces [0];
4076                 } else {
4077                         /* no interface */
4078                         return NULL;
4079                 }
4080         }
4081         iface = *iter;
4082         iface++;
4083         if (iface < &klass->interfaces [klass->interface_count]) {
4084                 *iter = iface;
4085                 return *iface;
4086         }
4087         return NULL;
4088 }
4089
4090 /**
4091  * mono_class_get_nested_types
4092  * @klass: the MonoClass to act on
4093  *
4094  * This routine is an iterator routine for retrieving the nested types of a class.
4095  *
4096  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4097  * iterate over all of the elements.  When no more values are
4098  * available, the return value is NULL.
4099  *
4100  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
4101  */
4102 MonoClass*
4103 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
4104 {
4105         GList *item;
4106         if (!iter)
4107                 return NULL;
4108         if (!klass->inited)
4109                 mono_class_init (klass);
4110         if (!*iter) {
4111                 /* start from the first */
4112                 if (klass->nested_classes) {
4113                         *iter = klass->nested_classes;
4114                         return klass->nested_classes->data;
4115                 } else {
4116                         /* no nested types */
4117                         return NULL;
4118                 }
4119         }
4120         item = *iter;
4121         item = item->next;
4122         if (item) {
4123                 *iter = item;
4124                 return item->data;
4125         }
4126         return NULL;
4127 }
4128
4129 /**
4130  * mono_field_get_name:
4131  * @field: the MonoClassField to act on
4132  *
4133  * Returns: the name of the field.
4134  */
4135 const char*
4136 mono_field_get_name (MonoClassField *field)
4137 {
4138         return field->name;
4139 }
4140
4141 /**
4142  * mono_field_get_type:
4143  * @field: the MonoClassField to act on
4144  *
4145  * Returns: MonoType of the field.
4146  */
4147 MonoType*
4148 mono_field_get_type (MonoClassField *field)
4149 {
4150         return field->type;
4151 }
4152
4153 /**
4154  * mono_field_get_type:
4155  * @field: the MonoClassField to act on
4156  *
4157  * Returns: MonoClass where the field was defined.
4158  */
4159 MonoClass*
4160 mono_field_get_parent (MonoClassField *field)
4161 {
4162         return field->parent;
4163 }
4164
4165 /**
4166  * mono_field_get_flags;
4167  * @field: the MonoClassField to act on
4168  *
4169  * The metadata flags for a field are encoded using the
4170  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
4171  *
4172  * Returns: the flags for the field.
4173  */
4174 guint32
4175 mono_field_get_flags (MonoClassField *field)
4176 {
4177         return field->type->attrs;
4178 }
4179
4180 /**
4181  * mono_property_get_name: 
4182  * @prop: the MonoProperty to act on
4183  *
4184  * Returns: the name of the property
4185  */
4186 const char*
4187 mono_property_get_name (MonoProperty *prop)
4188 {
4189         return prop->name;
4190 }
4191
4192 /**
4193  * mono_property_get_set_method
4194  * @prop: the MonoProperty to act on.
4195  *
4196  * Returns: the setter method of the property (A MonoMethod)
4197  */
4198 MonoMethod*
4199 mono_property_get_set_method (MonoProperty *prop)
4200 {
4201         return prop->set;
4202 }
4203
4204 /**
4205  * mono_property_get_get_method
4206  * @prop: the MonoProperty to act on.
4207  *
4208  * Returns: the setter method of the property (A MonoMethod)
4209  */
4210 MonoMethod*
4211 mono_property_get_get_method (MonoProperty *prop)
4212 {
4213         return prop->get;
4214 }
4215
4216 /**
4217  * mono_property_get_parent:
4218  * @prop: the MonoProperty to act on.
4219  *
4220  * Returns: the MonoClass where the property was defined.
4221  */
4222 MonoClass*
4223 mono_property_get_parent (MonoProperty *prop)
4224 {
4225         return prop->parent;
4226 }
4227
4228 /**
4229  * mono_property_get_flags:
4230  * @prop: the MonoProperty to act on.
4231  *
4232  * The metadata flags for a property are encoded using the
4233  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
4234  *
4235  * Returns: the flags for the property.
4236  */
4237 guint32
4238 mono_property_get_flags (MonoProperty *prop)
4239 {
4240         return prop->attrs;
4241 }
4242
4243 /**
4244  * mono_event_get_name:
4245  * @event: the MonoEvent to act on
4246  *
4247  * Returns: the name of the event.
4248  */
4249 const char*
4250 mono_event_get_name (MonoEvent *event)
4251 {
4252         return event->name;
4253 }
4254
4255 /**
4256  * mono_event_get_add_method:
4257  * @event: The MonoEvent to act on.
4258  *
4259  * Returns: the @add' method for the event (a MonoMethod).
4260  */
4261 MonoMethod*
4262 mono_event_get_add_method (MonoEvent *event)
4263 {
4264         return event->add;
4265 }
4266
4267 /**
4268  * mono_event_get_remove_method:
4269  * @event: The MonoEvent to act on.
4270  *
4271  * Returns: the @remove method for the event (a MonoMethod).
4272  */
4273 MonoMethod*
4274 mono_event_get_remove_method (MonoEvent *event)
4275 {
4276         return event->remove;
4277 }
4278
4279 /**
4280  * mono_event_get_raise_method:
4281  * @event: The MonoEvent to act on.
4282  *
4283  * Returns: the @raise method for the event (a MonoMethod).
4284  */
4285 MonoMethod*
4286 mono_event_get_raise_method (MonoEvent *event)
4287 {
4288         return event->raise;
4289 }
4290
4291 /**
4292  * mono_event_get_parent:
4293  * @event: the MonoEvent to act on.
4294  *
4295  * Returns: the MonoClass where the event is defined.
4296  */
4297 MonoClass*
4298 mono_event_get_parent (MonoEvent *event)
4299 {
4300         return event->parent;
4301 }
4302
4303 /**
4304  * mono_event_get_flags
4305  * @event: the MonoEvent to act on.
4306  *
4307  * The metadata flags for an event are encoded using the
4308  * EVENT_* constants.  See the tabledefs.h file for details.
4309  *
4310  * Returns: the flags for the event.
4311  */
4312 guint32
4313 mono_event_get_flags (MonoEvent *event)
4314 {
4315         return event->attrs;
4316 }
4317
4318 /**
4319  * mono_class_get_method_from_name:
4320  * @klass: where to look for the method
4321  * @name_space: name of the method
4322  * @param_count: number of parameters. -1 for any number.
4323  *
4324  * Obtains a MonoMethod with a given name and number of parameters.
4325  * It only works if there are no multiple signatures for any given method name.
4326  */
4327 MonoMethod *
4328 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
4329 {
4330         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
4331 }
4332
4333 /**
4334  * mono_class_get_method_from_name_flags:
4335  * @klass: where to look for the method
4336  * @name_space: name of the method
4337  * @param_count: number of parameters. -1 for any number.
4338  * @flags: flags which must be set in the method
4339  *
4340  * Obtains a MonoMethod with a given name and number of parameters.
4341  * It only works if there are no multiple signatures for any given method name.
4342  */
4343 MonoMethod *
4344 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
4345 {
4346         MonoMethod *res = NULL;
4347         int i;
4348
4349         mono_class_init (klass);
4350
4351         if (klass->methods) {
4352                 mono_class_setup_methods (klass);
4353                 for (i = 0; i < klass->method.count; ++i) {
4354                         MonoMethod *method = klass->methods [i];
4355
4356                         if (method->name[0] == name [0] && 
4357                                 !strcmp (name, method->name) &&
4358                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
4359                                 ((method->flags & flags) == flags)) {
4360                                 res = method;
4361                                 break;
4362                         }
4363                 }
4364         }
4365         else {
4366                 /* Search directly in the metadata to avoid calling setup_methods () */
4367                 for (i = 0; i < klass->method.count; ++i) {
4368                         guint32 cols [MONO_METHOD_SIZE];
4369                         MonoMethod *method;
4370
4371                         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_METHOD], klass->method.first + i, cols, MONO_METHOD_SIZE);
4372
4373                         if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
4374                                 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
4375                                 if ((param_count == -1) || mono_method_signature (method)->param_count == param_count) {
4376                                         res = method;
4377                                         break;
4378                                 }
4379                         }
4380                 }
4381         }
4382
4383         return res;
4384 }
4385
4386 /**
4387  * mono_class_set_failure:
4388  * @klass: class in which the failure was detected
4389  * @ex_type: the kind of exception/error to be thrown (later)
4390  * @ex_data: exception data (specific to each type of exception/error)
4391  *
4392  * Keep a detected failure informations in the class for later processing.
4393  * Note that only the first failure is kept.
4394  */
4395 gboolean
4396 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
4397 {
4398         if (klass->exception_type)
4399                 return FALSE;
4400         klass->exception_type = ex_type;
4401         klass->exception_data = ex_data;
4402         return TRUE;
4403 }
4404
4405 /**
4406  * mono_class_get_exception_for_failure:
4407  * @klass: class in which the failure was detected
4408  *
4409  * Return a constructed MonoException than the caller can then throw
4410  * using mono_raise_exception - or NULL if no failure is present (or
4411  * doesn't result in an exception).
4412  */
4413 MonoException*
4414 mono_class_get_exception_for_failure (MonoClass *klass)
4415 {
4416         switch (klass->exception_type) {
4417         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
4418                 MonoDomain *domain = mono_domain_get ();
4419                 MonoSecurityManager* secman = mono_security_manager_get_methods ();
4420                 MonoMethod *method = klass->exception_data;
4421                 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_CLASS : MONO_METADATA_INHERITANCEDEMAND_METHOD;
4422                 MonoObject *exc = NULL;
4423                 gpointer args [4];
4424
4425                 args [0] = &error;
4426                 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
4427                 args [2] = mono_type_get_object (domain, &klass->byval_arg);
4428                 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
4429
4430                 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
4431                 return (MonoException*) exc;
4432         }
4433         /* TODO - handle other class related failures */
4434         default:
4435                 return NULL;
4436         }
4437 }