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