Mon Apr 22 19:28:14 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / class.c
1 /*
2  * class.c: Class management for the Mono runtime
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  *
9  * Possible Optimizations:
10  *     in mono_class_create, do not allocate the class right away,
11  *     but wait until you know the size of the FieldMap, so that
12  *     the class embeds directly the FieldMap after the vtable.
13  *
14  * 
15  */
16 #include <config.h>
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #if HAVE_BOEHM_GC
32 #include <gc/gc.h>
33 #endif
34
35 #define CSIZE(x) (sizeof (x) / 4)
36
37 gboolean mono_print_vtable = FALSE;
38
39 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
40
41 static MonoClass *
42 mono_class_create_from_typeref (MonoImage *image, guint32 type_token)
43 {
44         guint32 cols [MONO_TYPEREF_SIZE];
45         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
46         guint32 idx;
47         const char *name, *nspace;
48         MonoClass *res;
49
50         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
51         idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
52         switch (cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK) {
53         case RESOLTION_SCOPE_MODULE:
54                 if (!idx)
55                         g_error ("null ResolutionScope not yet handled");
56                 /* a typedef in disguise */
57                 return mono_class_create_from_typedef (image, MONO_TOKEN_TYPE_DEF | (1+idx));
58         case RESOLTION_SCOPE_MODULEREF:
59                         g_error ("ModuleRef ResolutionScope not yet handled");
60         case RESOLTION_SCOPE_TYPEREF:
61                         g_error ("TypeRef ResolutionScope not yet handled");
62         case RESOLTION_SCOPE_ASSEMBLYREF:
63                 break;
64         }
65
66         if (!image->references ||  !image->references [idx-1]) {
67                 /* 
68                  * detected a reference to mscorlib, we simply return a reference to a dummy 
69                  * until we have a better solution.
70                  */
71                 fprintf(stderr, "Sending dummy where %s.%s expected\n", mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]), mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME])); 
72                 
73                 res = mono_class_from_name (image, "System", "MonoDummy");
74                 /* prevent method loading */
75                 res->dummy = 1;
76                 /* some storage if the type is used  - very ugly hack */
77                 res->instance_size = 2*sizeof (gpointer);
78                 return res;
79         }       
80
81         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
82         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
83         
84         /* load referenced assembly */
85         image = image->references [idx-1]->image;
86
87         return mono_class_from_name (image, nspace, name);
88 }
89
90 /** 
91  * class_compute_field_layout:
92  * @m: pointer to the metadata.
93  * @class: The class to initialize
94  *
95  * Initializes the class->fields.
96  *
97  * Currently we only support AUTO_LAYOUT, and do not even try to do
98  * a good job at it.  This is temporary to get the code for Paolo.
99  */
100 static void
101 class_compute_field_layout (MonoClass *class)
102 {
103         MonoImage *m = class->image; 
104         const int top = class->field.count;
105         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
106         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
107         int i;
108
109         /*
110          * Fetch all the field information.
111          */
112         for (i = 0; i < top; i++){
113                 const char *sig;
114                 guint32 cols [MONO_FIELD_SIZE];
115                 int idx = class->field.first + i;
116                 
117                 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
118                 /* The name is needed for fieldrefs */
119                 class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
120                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
121                 mono_metadata_decode_value (sig, &sig);
122                 /* FIELD signature == 0x06 */
123                 g_assert (*sig == 0x06);
124                 class->fields [i].type = mono_metadata_parse_field_type (
125                         m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
126                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
127                         mono_metadata_field_info (m, idx, NULL, &class->fields [i].data, NULL);
128                         if (!class->fields [i].data)
129                                 g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name);
130                 }
131                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
132                         class->enum_basetype = class->fields [i].type;
133                         class->element_class = mono_class_from_mono_type (class->enum_basetype);
134                 }
135         }
136         if (class->enumtype && !class->enum_basetype) {
137                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
138                         G_BREAKPOINT ();
139         }
140         /*
141          * Compute field layout and total size (not considering static fields)
142          */
143         switch (layout) {
144         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
145         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
146                 for (i = 0; i < top; i++){
147                         int size, align;
148                         
149                         if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
150                                 continue;
151
152                         size = mono_type_size (class->fields [i].type, &align);
153
154                         class->min_align = MAX (align, class->min_align);
155                         class->fields [i].offset = class->instance_size;
156                         class->fields [i].offset += align - 1;
157                         class->fields [i].offset &= ~(align - 1);
158                         class->instance_size = class->fields [i].offset + size;
159                 }
160        
161                 if (class->instance_size & (class->min_align - 1)) {
162                         class->instance_size += class->min_align - 1;
163                         class->instance_size &= ~(class->min_align - 1);
164                 }
165                 break;
166         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
167                 for (i = 0; i < top; i++) {
168                         int size, align;
169                         int idx = class->field.first + i;
170
171                         /*
172                          * There must be info about all the fields in a type if it
173                          * uses explicit layout.
174                          */
175
176                         if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
177                                 continue;
178
179                         size = mono_type_size (class->fields [i].type, &align);
180                         
181                         mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
182                         if (class->fields [i].offset == (guint32)-1)
183                                 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
184                         /*
185                          * The offset is from the start of the object: this works for both
186                          * classes and valuetypes.
187                          */
188                         class->fields [i].offset += sizeof (MonoObject);
189                         /*
190                          * Calc max size.
191                          */
192                         size += class->fields [i].offset;
193                         class->instance_size = MAX (class->instance_size, size);
194                 }
195                 break;
196         }
197
198         class->size_inited = 1;
199
200         /*
201          * Compute static field layout and size
202          */
203         switch (layout) {
204         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
205         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
206                 for (i = 0; i < top; i++){
207                         int size, align;
208                         
209                         if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
210                                 continue;
211                         
212                         size = mono_type_size (class->fields [i].type, &align);
213                         class->fields [i].offset = class->class_size;
214                         class->fields [i].offset += align - 1;
215                         class->fields [i].offset &= ~(align - 1);
216                         class->class_size = class->fields [i].offset + size;
217                 }
218                 break;
219         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
220                 for (i = 0; i < top; i++){
221                         int size, align;
222
223                         /*
224                          * There must be info about all the fields in a type if it
225                          * uses explicit layout.
226                          */
227
228                         
229                         if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
230                                 continue;
231
232                         size = mono_type_size (class->fields [i].type, &align);
233                         class->fields [i].offset = class->class_size;
234                         class->fields [i].offset += align - 1;
235                         class->fields [i].offset &= ~(align - 1);
236                         class->class_size = class->fields [i].offset + size;
237                 }
238                 break;
239         }
240 }
241
242 static void
243 init_properties (MonoClass *class)
244 {
245         guint startm, endm, i, j;
246         guint32 cols [MONO_PROPERTY_SIZE];
247         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
248         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
249
250         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
251         class->property.count = class->property.last - class->property.first;
252
253         class->properties = g_new0 (MonoProperty, class->property.count);
254         for (i = class->property.first; i < class->property.last; ++i) {
255                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
256                 class->properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
257                 class->properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
258
259                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
260                 for (j = startm; j < endm; ++j) {
261                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
262                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
263                         case METHOD_SEMANTIC_SETTER:
264                                 class->properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
265                                 break;
266                         case METHOD_SEMANTIC_GETTER:
267                                 class->properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
268                                 break;
269                         default:
270                                 break;
271                         }
272                 }
273         }
274 }
275
276 static void
277 init_events (MonoClass *class)
278 {
279         guint startm, endm, i, j;
280         guint32 cols [MONO_EVENT_SIZE];
281         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
282         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
283
284         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
285         class->event.count = class->event.last - class->event.first;
286
287         class->events = g_new0 (MonoEvent, class->event.count);
288         for (i = class->event.first; i < class->event.last; ++i) {
289                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
290                 class->events [i - class->event.first].attrs = cols [MONO_EVENT_FLAGS];
291                 class->events [i - class->event.first].name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
292
293                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
294                 for (j = startm; j < endm; ++j) {
295                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
296                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
297                         case METHOD_SEMANTIC_ADD_ON:
298                                 class->events [i - class->event.first].add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
299                                 break;
300                         case METHOD_SEMANTIC_REMOVE_ON:
301                                 class->events [i - class->event.first].remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
302                                 break;
303                         case METHOD_SEMANTIC_FIRE:
304                                 class->events [i - class->event.first].raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
305                                 break;
306                         case METHOD_SEMANTIC_OTHER: /* don't care for now */
307                         default:
308                                 break;
309                         }
310                 }
311         }
312 }
313
314 static guint
315 mono_get_unique_iid (MonoClass *class)
316 {
317         static GHashTable *iid_hash = NULL;
318         static guint iid = 0;
319
320         char *str;
321         gpointer value;
322         
323         g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
324
325         if (!iid_hash)
326                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
327
328         str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
329
330         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
331                 g_free (str);
332                 return (guint)value;
333         } else {
334                 g_hash_table_insert (iid_hash, str, (gpointer)iid);
335                 ++iid;
336         }
337
338         return iid - 1;
339 }
340
341 /**
342  * mono_class_init:
343  * @class: the class to initialize
344  *
345  * compute the instance_size, class_size and other infos that cannot be 
346  * computed at mono_class_get() time. Also compute a generic vtable and 
347  * the method slot numbers. We use this infos later to create a domain
348  * specific vtable.  
349  */
350 void
351 mono_class_init (MonoClass *class)
352 {
353         MonoClass *k, *ic;
354         MonoMethod **vtable;
355         int i, max_vtsize = 0, max_iid, cur_slot = 0;
356         static MonoMethod *default_ghc = NULL;
357         static int ghc_slot = -1;
358
359         g_assert (class);
360
361         if (class->inited)
362                 return;
363
364         if (class->init_pending) {
365                 /* this indicates a cyclic dependency */
366                 g_error ("pending init %s.%s\n", class->name_space, class->name);
367         }
368
369         class->init_pending = 1;
370
371 //      mono_stats.initialized_class_count++;
372
373         if (class->parent) {
374                 if (!class->parent->inited)
375                         mono_class_init (class->parent);
376                 class->instance_size += class->parent->instance_size;
377                 class->class_size += class->parent->class_size;
378                 class->min_align = class->parent->min_align;
379                 cur_slot = class->parent->vtable_size;
380         } else
381                 class->min_align = 1;
382
383         /*
384          * Computes the size used by the fields, and their locations
385          */
386         if (!class->size_inited && class->field.count > 0){
387                 class->fields = g_new0 (MonoClassField, class->field.count);
388                 class_compute_field_layout (class);
389         }
390
391         if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
392                 for (i = 0; i < class->interface_count; i++) 
393                         max_vtsize += class->interfaces [i]->method.count;
394         
395                 if (class->parent)
396                         max_vtsize += class->parent->vtable_size;
397
398                 max_vtsize += class->method.count;
399         }
400
401         vtable = alloca (sizeof (gpointer) * max_vtsize);
402         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
403
404         /* initialize method pointers */
405         class->methods = g_new (MonoMethod*, class->method.count);
406         for (i = 0; i < class->method.count; ++i)
407                 class->methods [i] = mono_get_method (class->image,
408                         MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
409
410         init_properties (class);
411         init_events (class);
412
413         i = mono_metadata_nesting_typedef (class->image, class->type_token);
414         while (i) {
415                 MonoClass* nclass;
416                 guint32 cols [MONO_NESTED_CLASS_SIZE];
417                 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
418                 if (cols [MONO_NESTED_CLASS_ENCLOSING] != mono_metadata_token_index (class->type_token))
419                         break;
420                 nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
421                 class->nested_classes = g_list_prepend (class->nested_classes, nclass);
422                 ++i;
423         }
424
425         if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
426                 for (i = 0; i < class->method.count; ++i)
427                         class->methods [i]->slot = i;
428                 class->init_pending = 0;
429                 class->inited = 1;
430                 return;
431         }
432
433         //printf ("METAINIT %s.%s\n", class->name_space, class->name);
434
435         /* compute maximum number of slots and maximum interface id */
436         max_iid = 0;
437         for (k = class; k ; k = k->parent) {
438                 for (i = 0; i < k->interface_count; i++) {
439                         ic = k->interfaces [i];
440
441                         if (!ic->inited)
442                                 mono_class_init (ic);
443
444                         if (max_iid < ic->interface_id)
445                                 max_iid = ic->interface_id;
446                 }
447         }
448         
449         class->max_interface_id = max_iid;
450         /* compute vtable offset for interfaces */
451         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
452
453         for (i = 0; i <= max_iid; i++)
454                 class->interface_offsets [i] = -1;
455
456         for (i = 0; i < class->interface_count; i++) {
457                 ic = class->interfaces [i];
458                 class->interface_offsets [ic->interface_id] = cur_slot;
459                 cur_slot += ic->method.count;
460         }
461
462         for (k = class->parent; k ; k = k->parent) {
463                 for (i = 0; i < k->interface_count; i++) {
464                         ic = k->interfaces [i]; 
465                         if (class->interface_offsets [ic->interface_id] == -1) {
466                                 int io = k->interface_offsets [ic->interface_id];
467
468                                 g_assert (io >= 0);
469                                 g_assert (io <= max_vtsize);
470
471                                 class->interface_offsets [ic->interface_id] = io;
472                         }
473                 }
474         }
475
476         if (class->parent && class->parent->vtable_size)
477                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
478  
479         for (k = class; k ; k = k->parent) {
480                 for (i = 0; i < k->interface_count; i++) {
481                         int j, l, io;
482
483                         ic = k->interfaces [i];
484                         io = k->interface_offsets [ic->interface_id];
485                         
486                         g_assert (io >= 0);
487                         g_assert (io <= max_vtsize);
488
489                         if (k == class) {
490                                 for (l = 0; l < ic->method.count; l++) {
491                                         MonoMethod *im = ic->methods [l];                                               
492                                         for (j = 0; j < class->method.count; ++j) {
493                                                 MonoMethod *cm = class->methods [j];
494                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
495                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC) ||
496                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
497                                                         continue;
498                                                 if (!strcmp(cm->name, im->name) && 
499                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
500                                                         g_assert (io + l <= max_vtsize);
501                                                         vtable [io + l] = cm;
502                                                 }
503                                         }
504                                 }
505                         } else {
506                                 /* already implemented */
507                                 if (io >= k->vtable_size)
508                                         continue;
509                         }
510                                 
511                         for (l = 0; l < ic->method.count; l++) {
512                                 MonoMethod *im = ic->methods [l];                                               
513                                 MonoClass *k1;
514
515                                 g_assert (io + l <= max_vtsize);
516
517                                 if (vtable [io + l])
518                                         continue;
519                                         
520                                 for (k1 = class; k1; k1 = k1->parent) {
521                                         for (j = 0; j < k1->method.count; ++j) {
522                                                 MonoMethod *cm = k1->methods [j];
523
524                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
525                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
526                                                         continue;
527                                                 
528                                                 if (!strcmp(cm->name, im->name) && 
529                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
530                                                         g_assert (io + l <= max_vtsize);
531                                                         vtable [io + l] = cm;
532                                                         break;
533                                                 }
534                                                 
535                                         }
536                                         g_assert (io + l <= max_vtsize);
537                                         if (vtable [io + l])
538                                                 break;
539                                 }
540                         }
541
542                         for (l = 0; l < ic->method.count; l++) {
543                                 MonoMethod *im = ic->methods [l];                                               
544                                 char *qname, *fqname;
545                                 
546                                 qname = g_strconcat (ic->name, ".", im->name, NULL); 
547                                 if (ic->name_space && ic->name_space [0])
548                                         fqname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
549                                 else
550                                         fqname = NULL;
551
552                                 for (j = 0; j < class->method.count; ++j) {
553                                         MonoMethod *cm = class->methods [j];
554
555                                         if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
556                                                 continue;
557                                         
558                                         if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
559                                             mono_metadata_signature_equal (cm->signature, im->signature)) {
560                                                 g_assert (io + l <= max_vtsize);
561                                                 vtable [io + l] = cm;
562                                                 break;
563                                         }
564                                 }
565                                 g_free (qname);
566                                 g_free (fqname);
567                         }
568
569                         
570                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
571                                 for (l = 0; l < ic->method.count; l++) {
572                                         MonoMethod *im = ic->methods [l];                                               
573                                         g_assert (io + l <= max_vtsize);
574                                         if (!(vtable [io + l])) {
575                                                 printf ("no implementation for interface method %s.%s::%s in class %s.%s\n",
576                                                         ic->name_space, ic->name, im->name, class->name_space, class->name);
577                                                 
578                                                 for (j = 0; j < class->method.count; ++j) {
579                                                         MonoMethod *cm = class->methods [j];
580                                                         
581                                                         printf ("METHOD %s\n", cm->name);
582                                                 }
583                                                 g_assert_not_reached ();
584                                         }
585                                 }
586                         }
587                 
588                         for (l = 0; l < ic->method.count; l++) {
589                                 MonoMethod *im = vtable [io + l];
590
591                                 if (im) {
592                                         g_assert (io + l <= max_vtsize);
593                                         if (im->slot < 0) {
594                                                 // fixme: why do we need this ?
595                                                 im->slot = io + l;
596                                                 // g_assert_not_reached ();
597                                         }
598                                 }
599                         }
600                 }
601         } 
602
603         for (i = 0; i < class->method.count; ++i) {
604                 MonoMethod *cm;
605                
606                 cm = class->methods [i];
607
608                 
609 #if 0
610                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
611                     (cm->slot >= 0))
612                         continue;
613 #else  /* EXT_VTABLE_HACK */
614                 if (cm->slot >= 0)
615                         continue;
616 #endif
617
618                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && (cm->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
619                         for (k = class->parent; k ; k = k->parent) {
620                                 int j;
621                                 for (j = 0; j < k->method.count; ++j) {
622                                         MonoMethod *m1 = k->methods [j];
623                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
624                                                 continue;
625                                         if (!strcmp(cm->name, m1->name) && 
626                                             mono_metadata_signature_equal (cm->signature, m1->signature)) {
627                                                 cm->slot = k->methods [j]->slot;
628                                                 g_assert (cm->slot < max_vtsize);
629                                                 break;
630                                         }
631                                 }
632                                 if (cm->slot >= 0) 
633                                         break;
634                         }
635                 }
636
637                 if (cm->slot < 0)
638                         cm->slot = cur_slot++;
639
640                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
641                         vtable [cm->slot] = cm;
642         }
643
644
645         class->vtable_size = cur_slot;
646         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
647         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
648
649         class->inited = 1;
650         class->init_pending = 0;
651
652         if (mono_print_vtable) {
653                 int icount = 0;
654
655                 for (i = 0; i <= max_iid; i++)
656                         if (class->interface_offsets [i] != -1)
657                                 icount++;
658
659                 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space, 
660                         class->name, class->vtable_size, icount); 
661
662                 for (i = 0; i < class->vtable_size; ++i) {
663                         MonoMethod *cm;
664                
665                         cm = vtable [i];
666                         if (cm) {
667                                 printf ("  slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
668                                         cm->klass->name_space, cm->klass->name,
669                                         cm->name);
670                         }
671                 }
672
673
674                 if (icount) {
675                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
676                                 class->name, max_iid);
677         
678                         for (i = 0; i < class->interface_count; i++) {
679                                 ic = class->interfaces [i];
680                                 printf ("  slot %03d(%03d) %s.%s\n",  
681                                         class->interface_offsets [ic->interface_id],
682                                         ic->method.count, ic->name_space, ic->name);
683                         }
684
685                         for (k = class->parent; k ; k = k->parent) {
686                                 for (i = 0; i < k->interface_count; i++) {
687                                         ic = k->interfaces [i]; 
688                                         printf ("  slot %03d(%03d) %s.%s\n", 
689                                                 class->interface_offsets [ic->interface_id],
690                                                 ic->method.count, ic->name_space, ic->name);
691                                 }
692                         }
693                 }
694         }
695
696         if (!default_ghc) {
697                 if (class == mono_defaults.object_class) { 
698                        
699                         for (i = 0; i < class->vtable_size; ++i) {
700                                 MonoMethod *cm = vtable [i];
701                
702                                 if (!strcmp (cm->name, "GetHashCode")) {
703                                         ghc_slot = i;
704                                         break;
705                                 }
706                         }
707
708                         g_assert (ghc_slot > 0);
709
710                         default_ghc = vtable [ghc_slot];
711                 }
712         }
713         
714         class->ghcimpl = 1;
715         if (class != mono_defaults.object_class) { 
716
717                 if (vtable [ghc_slot] == default_ghc) {
718                         class->ghcimpl = 0;
719                 }
720
721         }
722 }
723
724
725 /*
726  * Compute a relative numbering of the class hierarchy as described in
727  * "Java for Large-Scale Scientific Computations?"
728  */
729 static void
730 mono_compute_relative_numbering (MonoClass *class, int *c)
731 {
732         GList *s;
733
734         (*c)++;
735
736         class->baseval = *c;
737
738         for (s = class->subclasses; s; s = s->next)
739                 mono_compute_relative_numbering ((MonoClass *)s->data, c); 
740         
741         class->diffval = *c -  class->baseval;
742 }
743
744 void
745 mono_class_setup_mono_type (MonoClass *class)
746 {
747         const char *name = class->name;
748         const char *nspace = class->name_space;
749
750         class->this_arg.byref = 1;
751         class->this_arg.data.klass = class;
752         class->this_arg.type = MONO_TYPE_CLASS;
753         class->byval_arg.data.klass = class;
754         class->byval_arg.type = MONO_TYPE_CLASS;
755
756         if (!strcmp (nspace, "System")) {
757                 if (!strcmp (name, "ValueType")) {
758                         /*
759                          * do not set the valuetype bit for System.ValueType.
760                          * class->valuetype = 1;
761                          */
762                 } else if (!strcmp (name, "Enum")) {
763                         /*
764                          * do not set the valuetype bit for System.Enum.
765                          * class->valuetype = 1;
766                          */
767                         class->valuetype = 0;
768                         class->enumtype = 0;
769                 } else if (!strcmp (name, "Object")) {
770                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
771                 } else if (!strcmp (name, "String")) {
772                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
773                 }
774         }
775         
776         if (class->valuetype) {
777                 int t = MONO_TYPE_VALUETYPE;
778                 if (!strcmp (nspace, "System")) {
779                         switch (*name) {
780                         case 'B':
781                                 if (!strcmp (name, "Boolean")) {
782                                         t = MONO_TYPE_BOOLEAN;
783                                 } else if (!strcmp(name, "Byte")) {
784                                         t = MONO_TYPE_U1;
785                                 }
786                                 break;
787                         case 'C':
788                                 if (!strcmp (name, "Char")) {
789                                         t = MONO_TYPE_CHAR;
790                                 }
791                                 break;
792                         case 'D':
793                                 if (!strcmp (name, "Double")) {
794                                         t = MONO_TYPE_R8;
795                                 }
796                                 break;
797                         case 'I':
798                                 if (!strcmp (name, "Int32")) {
799                                         t = MONO_TYPE_I4;
800                                 } else if (!strcmp(name, "Int16")) {
801                                         t = MONO_TYPE_I2;
802                                 } else if (!strcmp(name, "Int64")) {
803                                         t = MONO_TYPE_I8;
804                                 } else if (!strcmp(name, "IntPtr")) {
805                                         t = MONO_TYPE_I;
806                                 }
807                                 break;
808                         case 'S':
809                                 if (!strcmp (name, "Single")) {
810                                         t = MONO_TYPE_R4;
811                                 } else if (!strcmp(name, "SByte")) {
812                                         t = MONO_TYPE_I1;
813                                 }
814                                 break;
815                         case 'U':
816                                 if (!strcmp (name, "UInt32")) {
817                                         t = MONO_TYPE_U4;
818                                 } else if (!strcmp(name, "UInt16")) {
819                                         t = MONO_TYPE_U2;
820                                 } else if (!strcmp(name, "UInt64")) {
821                                         t = MONO_TYPE_U8;
822                                 } else if (!strcmp(name, "UIntPtr")) {
823                                         t = MONO_TYPE_U;
824                                 }
825                                 break;
826                         case 'V':
827                                 if (!strcmp (name, "Void")) {
828                                         t = MONO_TYPE_VOID;
829                                 }
830                                 break;
831                         default:
832                                 break;
833                         }
834                 }
835                 class->this_arg.type = class->byval_arg.type = t;
836         }
837 }
838
839 void
840 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
841 {
842         gboolean system_namespace;
843
844         system_namespace = !strcmp (class->name_space, "System");
845
846         /* if root of the hierarchy */
847         if (system_namespace && !strcmp (class->name, "Object")) {
848                 class->parent = NULL;
849                 class->instance_size = sizeof (MonoObject);
850                 return;
851         }
852
853         if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
854                 int rnum = 0;
855                 class->parent = parent;
856
857                 class->marshalbyref = parent->marshalbyref;
858                 class->contextbound  = parent->contextbound;
859                 class->delegate  = parent->delegate;
860                 
861                 if (system_namespace) {
862                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
863                                 class->marshalbyref = 1;
864
865                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
866                                 class->contextbound  = 1;
867
868                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
869                                 class->delegate  = 1;
870                 }
871
872                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
873                                                 (strcmp (class->parent->name_space, "System") == 0)))
874                         class->valuetype = 1;
875                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
876                         class->valuetype = class->enumtype = 1;
877                 }
878                 //class->enumtype = class->parent->enumtype;
879                 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
880                 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
881         } else {
882                 class->parent = NULL;
883         }
884
885 }
886
887 /**
888  * @image: context where the image is created
889  * @type_token:  typedef token
890  */
891 static MonoClass *
892 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
893 {
894         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
895         MonoClass *class, *parent = NULL;
896         guint32 cols [MONO_TYPEDEF_SIZE];
897         guint32 cols_next [MONO_TYPEDEF_SIZE];
898         guint tidx = mono_metadata_token_index (type_token);
899         const char *name, *nspace;
900         guint icount = 0; 
901         MonoClass **interfaces;
902
903         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
904                 return class;
905
906         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
907         
908         mono_metadata_decode_row (tt, tidx - 1, cols, CSIZE (cols));
909         
910         name = mono_metadata_string_heap (image, cols[1]);
911         nspace = mono_metadata_string_heap (image, cols[2]);
912
913         if (!(!strcmp (nspace, "System") && !strcmp (name, "Object")) &&
914             !(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
915                 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [3]));
916         }
917         interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
918
919         class = g_malloc0 (sizeof (MonoClass));
920                            
921         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
922
923         class->interfaces = interfaces;
924         class->interface_count = icount;
925
926         class->name = name;
927         class->name_space = nspace;
928
929         class->image = image;
930         class->type_token = type_token;
931         class->flags = cols [MONO_TYPEDEF_FLAGS];
932
933         class->element_class = class;
934
935         /*g_print ("Init class %s\n", name);*/
936
937         mono_class_setup_parent (class, parent);
938
939         mono_class_setup_mono_type (class);
940
941         /*
942          * Compute the field and method lists
943          */
944         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
945         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
946
947         if (tt->rows > tidx){           
948                 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
949                 class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
950                 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
951         } else {
952                 class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
953                 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
954         }
955
956         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
957             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
958                 class->field.count = class->field.last - class->field.first;
959         else
960                 class->field.count = 0;
961
962         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
963                 class->method.count = class->method.last - class->method.first;
964         else
965                 class->method.count = 0;
966
967         /* reserve space to store vector pointer in arrays */
968         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
969                 class->instance_size += 2 * sizeof (gpointer);
970                 g_assert (class->field.count == 0);
971         }
972
973         if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
974                 class->interface_id = mono_get_unique_iid (class);
975
976         //class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count);
977
978         if (class->enumtype) {
979                 class->fields = g_new0 (MonoClassField, class->field.count);
980                 class_compute_field_layout (class);
981         } 
982
983         if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
984                 class->nested_in = mono_class_create_from_typedef (image, type_token);
985         return class;
986 }
987
988 MonoClass *
989 mono_ptr_class_get (MonoType *type)
990 {
991         MonoClass *result;
992         MonoClass *el_class;
993         static GHashTable *ptr_hash = NULL;
994
995         if (!ptr_hash)
996                 ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
997         el_class = mono_class_from_mono_type (type);
998         if ((result = g_hash_table_lookup (ptr_hash, el_class)))
999                 return result;
1000         result = g_new0 (MonoClass, 1);
1001
1002         result->parent = NULL; /* no parent for PTR types */
1003         result->name = "System";
1004         result->name_space = "MonoPtrFakeClass";
1005         result->image = el_class->image;
1006         result->inited = TRUE;
1007         /* Can pointers get boxed? */
1008         result->instance_size = sizeof (gpointer);
1009         /*
1010          * baseval, diffval: need them to allow casting ?
1011          */
1012         result->element_class = el_class;
1013         result->enum_basetype = &result->element_class->byval_arg;
1014
1015         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
1016         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
1017         result->this_arg.byref = TRUE;
1018
1019         g_hash_table_insert (ptr_hash, el_class, result);
1020
1021         return result;
1022 }
1023
1024 MonoClass *
1025 mono_class_from_mono_type (MonoType *type)
1026 {
1027         switch (type->type) {
1028         case MONO_TYPE_OBJECT:
1029                 return mono_defaults.object_class;
1030         case MONO_TYPE_VOID:
1031                 return mono_defaults.void_class;
1032         case MONO_TYPE_BOOLEAN:
1033                 return mono_defaults.boolean_class;
1034         case MONO_TYPE_CHAR:
1035                 return mono_defaults.char_class;
1036         case MONO_TYPE_I1:
1037                 return mono_defaults.sbyte_class;
1038         case MONO_TYPE_U1:
1039                 return mono_defaults.byte_class;
1040         case MONO_TYPE_I2:
1041                 return mono_defaults.int16_class;
1042         case MONO_TYPE_U2:
1043                 return mono_defaults.uint16_class;
1044         case MONO_TYPE_I4:
1045                 return mono_defaults.int32_class;
1046         case MONO_TYPE_U4:
1047                 return mono_defaults.uint32_class;
1048         case MONO_TYPE_I:
1049                 return mono_defaults.int_class;
1050         case MONO_TYPE_U:
1051                 return mono_defaults.uint_class;
1052         case MONO_TYPE_I8:
1053                 return mono_defaults.int64_class;
1054         case MONO_TYPE_U8:
1055                 return mono_defaults.uint64_class;
1056         case MONO_TYPE_R4:
1057                 return mono_defaults.single_class;
1058         case MONO_TYPE_R8:
1059                 return mono_defaults.double_class;
1060         case MONO_TYPE_STRING:
1061                 return mono_defaults.string_class;
1062         case MONO_TYPE_ARRAY:
1063                 return mono_array_class_get (type->data.array->type, type->data.array->rank);
1064         case MONO_TYPE_PTR:
1065                 return mono_ptr_class_get (type->data.type);
1066         case MONO_TYPE_SZARRAY:
1067                 return mono_array_class_get (type->data.type, 1);
1068         case MONO_TYPE_CLASS:
1069         case MONO_TYPE_VALUETYPE:
1070                 return type->data.klass;
1071         default:
1072                 g_warning ("implement me %02x\n", type->type);
1073                 g_assert_not_reached ();
1074         }
1075         
1076         return NULL;
1077 }
1078
1079 /**
1080  * @image: context where the image is created
1081  * @type_spec:  typespec token
1082  */
1083 static MonoClass *
1084 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
1085 {
1086         MonoType *type;
1087         MonoClass *class;
1088
1089         type = mono_type_create_from_typespec (image, type_spec);
1090
1091         switch (type->type) {
1092         case MONO_TYPE_ARRAY:
1093                 class = mono_array_class_get (type->data.array->type, type->data.array->rank);
1094                 break;
1095         case MONO_TYPE_SZARRAY:
1096                 class = mono_array_class_get (type->data.type, 1);
1097                 break;
1098         case MONO_TYPE_PTR:
1099                 class = mono_class_from_mono_type (type->data.type);
1100                 break;
1101         default:
1102                 g_warning ("implement me: %08x", type->type);
1103                 g_assert_not_reached ();                
1104         }
1105
1106         mono_metadata_free_type (type);
1107         
1108         return class;
1109 }
1110
1111 /**
1112  * mono_array_class_get:
1113  * @element_type: element type 
1114  * @rank: the dimension of the array class
1115  *
1116  * Returns: a class object describing the array with element type @element_type and 
1117  * dimension @rank. 
1118  */
1119 MonoClass *
1120 mono_array_class_get (MonoType *element_type, guint32 rank)
1121 {
1122         MonoClass *eclass;
1123         MonoImage *image;
1124         MonoClass *class;
1125         static MonoClass *parent = NULL;
1126         guint32 key;
1127         int rnum = 0;
1128
1129         eclass = mono_class_from_mono_type (element_type);
1130         g_assert (rank <= 255);
1131
1132         if (!parent)
1133                 parent = mono_defaults.array_class;
1134
1135         if (!parent->inited)
1136                 mono_class_init (parent);
1137
1138         image = eclass->image;
1139
1140         g_assert (!eclass->type_token ||
1141                   mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
1142
1143         key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
1144         if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
1145                 return class;
1146         
1147         class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
1148
1149         class->image = image;
1150         class->name_space = "System";
1151         class->name = "Array";
1152         class->type_token = 0;
1153         class->flags = TYPE_ATTRIBUTE_CLASS;
1154         class->parent = parent;
1155         class->instance_size = mono_class_instance_size (class->parent);
1156         class->class_size = 0;
1157         class->vtable_size = parent->vtable_size;
1158         class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
1159         mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
1160
1161         class->rank = rank;
1162         class->element_class = eclass;
1163         if (rank > 1) {
1164                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
1165                 class->byval_arg.type = MONO_TYPE_ARRAY;
1166                 class->byval_arg.data.array = at;
1167                 at->type = &eclass->byval_arg;
1168                 at->rank = rank;
1169                 /* FIXME: complete.... */
1170         } else {
1171                 /* FIXME: this is not correct. the lbound could be >0 */
1172                 class->byval_arg.type = MONO_TYPE_SZARRAY;
1173                 class->byval_arg.data.type = &eclass->byval_arg;
1174         }
1175         class->this_arg = class->byval_arg;
1176         class->this_arg.byref = 1;
1177         
1178         g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
1179         return class;
1180 }
1181
1182 /**
1183  * mono_class_instance_size:
1184  * @klass: a class 
1185  * 
1186  * Returns: the size of an object instance
1187  */
1188 gint32
1189 mono_class_instance_size (MonoClass *klass)
1190 {
1191         
1192         if (!klass->size_inited)
1193                 mono_class_init (klass);
1194
1195         return klass->instance_size;
1196 }
1197
1198 /**
1199  * mono_class_value_size:
1200  * @klass: a class 
1201  *
1202  * This function is used for value types, and return the
1203  * space and the alignment to store that kind of value object.
1204  *
1205  * Returns: the size of a value of kind @klass
1206  */
1207 gint32
1208 mono_class_value_size      (MonoClass *klass, guint32 *align)
1209 {
1210         gint32 size;
1211
1212         /* fixme: check disable, because we still have external revereces to
1213          * mscorlib and Dummy Objects 
1214          */
1215         /*g_assert (klass->valuetype);*/
1216
1217         size = mono_class_instance_size (klass) - sizeof (MonoObject);
1218
1219         if (align)
1220                 *align = klass->min_align;
1221
1222         return size;
1223 }
1224
1225 /**
1226  * mono_class_data_size:
1227  * @klass: a class 
1228  * 
1229  * Returns: the size of the static class data
1230  */
1231 gint32
1232 mono_class_data_size (MonoClass *klass)
1233 {
1234         
1235         if (!klass->inited)
1236                 mono_class_init (klass);
1237
1238         return klass->class_size;
1239 }
1240
1241 /*
1242  * Auxiliary routine to mono_class_get_field
1243  *
1244  * Takes a field index instead of a field token.
1245  */
1246 static MonoClassField *
1247 mono_class_get_field_idx (MonoClass *class, int idx)
1248 {
1249         if (class->field.count){
1250                 if ((idx >= class->field.first) && (idx < class->field.last)){
1251                         return &class->fields [idx - class->field.first];
1252                 }
1253         }
1254
1255         if (!class->parent)
1256                 return NULL;
1257         
1258         return mono_class_get_field_idx (class->parent, idx);
1259 }
1260
1261 /**
1262  * mono_class_get_field:
1263  * @class: the class to lookup the field.
1264  * @field_token: the field token
1265  *
1266  * Returns: A MonoClassField representing the type and offset of
1267  * the field, or a NULL value if the field does not belong to this
1268  * class.
1269  */
1270 MonoClassField *
1271 mono_class_get_field (MonoClass *class, guint32 field_token)
1272 {
1273         int idx = mono_metadata_token_index (field_token);
1274
1275         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
1276
1277         return mono_class_get_field_idx (class, idx - 1);
1278 }
1279
1280 MonoClassField *
1281 mono_class_get_field_from_name (MonoClass *klass, const char *name)
1282 {
1283         int i;
1284
1285         for (i = 0; i < klass->field.count; ++i) {
1286                 if (strcmp (name, klass->fields [i].name) == 0)
1287                         return &klass->fields [i];
1288         }
1289         return NULL;
1290 }
1291
1292 /**
1293  * mono_class_get:
1294  * @image: the image where the class resides
1295  * @type_token: the token for the class
1296  * @at: an optional pointer to return the array element type
1297  *
1298  * Returns: the MonoClass that represents @type_token in @image
1299  */
1300 MonoClass *
1301 mono_class_get (MonoImage *image, guint32 type_token)
1302 {
1303         MonoClass *class;
1304
1305         switch (type_token & 0xff000000){
1306         case MONO_TOKEN_TYPE_DEF:
1307                 class = mono_class_create_from_typedef (image, type_token);
1308                 break;          
1309         case MONO_TOKEN_TYPE_REF:
1310                 class = mono_class_create_from_typeref (image, type_token);
1311                 break;
1312         case MONO_TOKEN_TYPE_SPEC:
1313                 class = mono_class_create_from_typespec (image, type_token);
1314                 break;
1315         default:
1316                 g_warning ("unknown token type %x", type_token & 0xff000000);
1317                 g_assert_not_reached ();
1318         }
1319
1320         if (!class)
1321                 g_warning ("Could not load class from token 0x%08x", type_token);
1322         return class;
1323 }
1324
1325 MonoClass *
1326 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
1327 {
1328         GHashTable *nspace_table;
1329         guint32 token;
1330
1331         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
1332         if (!nspace_table)
1333                 return 0;
1334         token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
1335         
1336         if (!token) {
1337                 /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
1338                 return NULL;
1339         }
1340
1341         token = MONO_TOKEN_TYPE_DEF | token;
1342
1343         return mono_class_get (image, token);
1344 }
1345
1346 /**
1347  * mono_array_element_size:
1348  * @ac: pointer to a #MonoArrayClass
1349  *
1350  * Returns: the size of single array element.
1351  */
1352 gint32
1353 mono_array_element_size (MonoClass *ac)
1354 {
1355         if (ac->element_class->valuetype)
1356                 return mono_class_instance_size (ac->element_class) - sizeof (MonoObject);
1357         else
1358                 return sizeof (gpointer);
1359 }
1360
1361 gpointer
1362 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
1363 {
1364         switch (token & 0xff000000) {
1365         case MONO_TOKEN_TYPE_DEF:
1366         case MONO_TOKEN_TYPE_REF: {
1367                 MonoClass *class;
1368                 if (handle_class)
1369                         *handle_class = mono_defaults.typehandle_class;
1370                 class = mono_class_get (image, token);
1371                 mono_class_init (class);
1372                 /* We return a MonoType* as handle */
1373                 return &class->byval_arg;
1374         }
1375         case MONO_TOKEN_TYPE_SPEC: {
1376                 MonoClass *class;
1377                 if (handle_class)
1378                         *handle_class = mono_defaults.typehandle_class;
1379                 class = mono_class_create_from_typespec (image, token);
1380                 mono_class_init (class);
1381                 return &class->byval_arg;
1382         }
1383         case MONO_TOKEN_FIELD_DEF: {
1384                 MonoClass *class;
1385                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
1386                 class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
1387                 mono_class_init (class);
1388                 if (handle_class)
1389                                 *handle_class = mono_class_from_name (mono_defaults.corlib, "System", "RuntimeFieldHandle");
1390                 return mono_class_get_field (class, token);
1391         }
1392         case MONO_TOKEN_METHOD_DEF:
1393         case MONO_TOKEN_MEMBER_REF:
1394         default:
1395                 g_warning ("Unknown token 0x%08x in ldtoken", token);
1396                 break;
1397         }
1398         return NULL;
1399 }
1400