X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=74f082cd7e76cba0be6e53b24b5e9b3cc737a24c;hb=7c64dd69d21cb0ef83f76ddc6e2d65071c60b335;hp=314b0935d34fd4d3806f4d377119d720793aa2ac;hpb=724614b9191cee376ab6aaf48d3145264bb2c2d0;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 314b0935d34..74f082cd7e7 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -38,49 +38,8 @@ gboolean mono_print_vtable = FALSE; static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token); -static gpointer -default_trampoline (MonoMethod *method) -{ - return method; -} - -static gpointer -default_remoting_trampoline (MonoMethod *method) -{ - g_error ("remoting not installed"); - return NULL; -} - -static void -default_runtime_class_init (MonoClass *klass) -{ - return; -} - -static MonoTrampoline arch_create_jit_trampoline = default_trampoline; -static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline; -static MonoRuntimeClassInit mono_runtime_class_init = default_runtime_class_init; - -void -mono_install_trampoline (MonoTrampoline func) -{ - arch_create_jit_trampoline = func? func: default_trampoline; -} - -void -mono_install_remoting_trampoline (MonoTrampoline func) -{ - arch_create_remoting_trampoline = func? func: default_remoting_trampoline; -} - -void -mono_install_runtime_class_init (MonoRuntimeClassInit func) -{ - mono_runtime_class_init = func? func: default_runtime_class_init; -} - -static MonoClass * -mono_class_create_from_typeref (MonoImage *image, guint32 type_token) +MonoClass * +mono_class_from_typeref (MonoImage *image, guint32 type_token) { guint32 cols [MONO_TYPEREF_SIZE]; MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF]; @@ -89,8 +48,24 @@ mono_class_create_from_typeref (MonoImage *image, guint32 type_token) MonoClass *res; mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE); - g_assert ((cols [MONO_TYPEREF_SCOPE] & 0x3) == 2); - idx = cols [MONO_TYPEREF_SCOPE] >> 2; + + name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]); + nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]); + + idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS; + switch (cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK) { + case RESOLTION_SCOPE_MODULE: + if (!idx) + g_error ("null ResolutionScope not yet handled"); + /* a typedef in disguise */ + return mono_class_from_name (image, nspace, name); + case RESOLTION_SCOPE_MODULEREF: + g_error ("ModuleRef ResolutionScope not yet handled"); + case RESOLTION_SCOPE_TYPEREF: + g_error ("TypeRef ResolutionScope not yet handled"); + case RESOLTION_SCOPE_ASSEMBLYREF: + break; + } if (!image->references || !image->references [idx-1]) { /* @@ -107,9 +82,6 @@ mono_class_create_from_typeref (MonoImage *image, guint32 type_token) return res; } - name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]); - nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]); - /* load referenced assembly */ image = image->references [idx-1]->image; @@ -380,9 +352,11 @@ void mono_class_init (MonoClass *class) { MonoClass *k, *ic; - MonoMethod **vtable = class->vtable; - int i, max_iid, cur_slot = 0; + MonoMethod **vtable; + int i, max_vtsize = 0, max_iid, cur_slot = 0; static MonoMethod *default_ghc = NULL; + static MonoMethod *default_finalize = NULL; + static int finalize_slot = -1; static int ghc_slot = -1; g_assert (class); @@ -397,6 +371,8 @@ mono_class_init (MonoClass *class) class->init_pending = 1; +// mono_stats.initialized_class_count++; + if (class->parent) { if (!class->parent->inited) mono_class_init (class->parent); @@ -415,6 +391,19 @@ mono_class_init (MonoClass *class) class_compute_field_layout (class); } + if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) { + for (i = 0; i < class->interface_count; i++) + max_vtsize += class->interfaces [i]->method.count; + + if (class->parent) + max_vtsize += class->parent->vtable_size; + + max_vtsize += class->method.count; + } + + vtable = alloca (sizeof (gpointer) * max_vtsize); + memset (vtable, 0, sizeof (gpointer) * max_vtsize); + /* initialize method pointers */ class->methods = g_new (MonoMethod*, class->method.count); for (i = 0; i < class->method.count; ++i) @@ -480,7 +469,7 @@ mono_class_init (MonoClass *class) int io = k->interface_offsets [ic->interface_id]; g_assert (io >= 0); - g_assert (io <= class->vtable_size); + g_assert (io <= max_vtsize); class->interface_offsets [ic->interface_id] = io; } @@ -488,7 +477,7 @@ mono_class_init (MonoClass *class) } if (class->parent && class->parent->vtable_size) - memcpy (class->vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size); + memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size); for (k = class; k ; k = k->parent) { for (i = 0; i < k->interface_count; i++) { @@ -498,7 +487,7 @@ mono_class_init (MonoClass *class) io = k->interface_offsets [ic->interface_id]; g_assert (io >= 0); - g_assert (io <= class->vtable_size); + g_assert (io <= max_vtsize); if (k == class) { for (l = 0; l < ic->method.count; l++) { @@ -511,7 +500,7 @@ mono_class_init (MonoClass *class) continue; if (!strcmp(cm->name, im->name) && mono_metadata_signature_equal (cm->signature, im->signature)) { - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; } } @@ -526,7 +515,7 @@ mono_class_init (MonoClass *class) MonoMethod *im = ic->methods [l]; MonoClass *k1; - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); if (vtable [io + l]) continue; @@ -541,13 +530,13 @@ mono_class_init (MonoClass *class) if (!strcmp(cm->name, im->name) && mono_metadata_signature_equal (cm->signature, im->signature)) { - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; break; } } - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); if (vtable [io + l]) break; } @@ -571,7 +560,7 @@ mono_class_init (MonoClass *class) if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) && mono_metadata_signature_equal (cm->signature, im->signature)) { - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; break; } @@ -584,7 +573,7 @@ mono_class_init (MonoClass *class) if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) { for (l = 0; l < ic->method.count; l++) { MonoMethod *im = ic->methods [l]; - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); if (!(vtable [io + l])) { printf ("no implementation for interface method %s.%s::%s in class %s.%s\n", ic->name_space, ic->name, im->name, class->name_space, class->name); @@ -603,7 +592,7 @@ mono_class_init (MonoClass *class) MonoMethod *im = vtable [io + l]; if (im) { - g_assert (io + l <= class->vtable_size); + g_assert (io + l <= max_vtsize); if (im->slot < 0) { // fixme: why do we need this ? im->slot = io + l; @@ -639,7 +628,7 @@ mono_class_init (MonoClass *class) if (!strcmp(cm->name, m1->name) && mono_metadata_signature_equal (cm->signature, m1->signature)) { cm->slot = k->methods [j]->slot; - g_assert (cm->slot < class->vtable_size); + g_assert (cm->slot < max_vtsize); break; } } @@ -655,6 +644,14 @@ mono_class_init (MonoClass *class) vtable [cm->slot] = cm; } + + class->vtable_size = cur_slot; + class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size); + memcpy (class->vtable, vtable, sizeof (gpointer) * class->vtable_size); + + class->inited = 1; + class->init_pending = 0; + if (mono_print_vtable) { int icount = 0; @@ -699,9 +696,6 @@ mono_class_init (MonoClass *class) } } - class->inited = 1; - class->init_pending = 0; - if (!default_ghc) { if (class == mono_defaults.object_class) { @@ -726,207 +720,32 @@ mono_class_init (MonoClass *class) if (vtable [ghc_slot] == default_ghc) { class->ghcimpl = 0; } - } -} - -#if HAVE_BOEHM_GC -static void -vtable_finalizer (void *obj, void *data) { - g_print ("%s finalized (%p)\n", (char*)data, obj); -} -#endif -/** - * mono_class_vtable: - * @domain: the application domain - * @class: the class to initialize - * - * VTables are domain specific because we create domain specific code, and - * they contain the domain specific static class data. - */ -MonoVTable * -mono_class_vtable (MonoDomain *domain, MonoClass *class) -{ - MonoClass *k; - MonoVTable *vt; - MonoClassField *field; - guint32 cindex; - guint32 cols [MONO_CONSTANT_SIZE]; - const char *p; - char *t; - int i, len; - - g_assert (class); - - /* can interfaces have static fields? */ - if (class->flags & TYPE_ATTRIBUTE_INTERFACE) - g_assert_not_reached (); - - if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) - return vt; - - if (!class->inited) - mono_class_init (class); - -#if HAVE_BOEHM_GC - vt = GC_malloc (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer)); - /*vt = GC_debug_malloc (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer), class->name, 1);*/ - GC_register_finalizer (vt, vtable_finalizer, "vtable", NULL, NULL); -#else - vt = g_malloc0 (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer)); -#endif - vt->klass = class; - vt->domain = domain; - - if (class->class_size) { -#if HAVE_BOEHM_GC - vt->data = GC_malloc (class->class_size + 8); - /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/ - GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL); -#else - vt->data = g_malloc0 (class->class_size + 8); -#endif - /* align: fixme not 64 bit clean */ - if (((guint32)vt->data) & 0x7) - vt->data = (char*)vt->data + 8 - (((guint32)vt->data) & 0x7); - } - - for (i = class->field.first; i < class->field.last; ++i) { - field = &class->fields [i - class->field.first]; - if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) - continue; - if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) - continue; - cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1)); - if (!cindex) { - g_warning ("constant for field %s not found", field->name); - continue; - } - mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE); - p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]); - len = mono_metadata_decode_blob_size (p, &p); - t = (char*)vt->data + field->offset; - /* should we check that the type matches? */ - switch (cols [MONO_CONSTANT_TYPE]) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_U1: - case MONO_TYPE_I1: - *t = *p; - break; - case MONO_TYPE_CHAR: - case MONO_TYPE_U2: - case MONO_TYPE_I2: { - guint16 *val = (guint16*)t; - *val = read16 (p); - break; - } - case MONO_TYPE_U4: - case MONO_TYPE_I4: { - guint32 *val = (guint32*)t; - *val = read32 (p); - break; - } - case MONO_TYPE_U8: - case MONO_TYPE_I8: { - guint64 *val = (guint64*)t; - *val = read64 (p); - break; - } - case MONO_TYPE_R4: { - float *val = (float*)t; - readr4 (p, val); - break; - } - case MONO_TYPE_R8: { - double *val = (double*)t; - readr8 (p, val); - break; - } - case MONO_TYPE_STRING: { - gpointer *val = (gpointer*)t; - *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2); - break; - } - case MONO_TYPE_CLASS: - /* nothing to do, we malloc0 the data and the value can be 0 only */ - break; - default: - g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]); - } - } + if (!default_finalize) { + if (class == mono_defaults.object_class) { + + for (i = 0; i < class->vtable_size; ++i) { + MonoMethod *cm = vtable [i]; + + if (!strcmp (cm->name, "Finalize")) { + finalize_slot = i; + break; + } + } - vt->interface_offsets = g_malloc0 (sizeof (gpointer) * (class->max_interface_id + 1)); + g_assert (finalize_slot > 0); - /* initialize interface offsets */ - for (k = class; k ; k = k->parent) { - for (i = 0; i < k->interface_count; i++) { - int slot; - MonoClass *ic = k->interfaces [i]; - slot = class->interface_offsets [ic->interface_id]; - vt->interface_offsets [ic->interface_id] = &vt->vtable [slot]; + default_finalize = vtable [finalize_slot]; } } - /* initialize vtable */ - for (i = 0; i < class->vtable_size; ++i) { - MonoMethod *cm; - - if ((cm = class->vtable [i])) - vt->vtable [i] = arch_create_jit_trampoline (cm); - } - - mono_g_hash_table_insert (domain->class_vtable_hash, class, vt); - - mono_runtime_class_init (class); - - return vt; -} - -/** - * mono_class_proxy_vtable: - * @domain: the application domain - * @class: the class to proxy - * - * Creates a vtable for transparent proxies. It is basically - * a copy of the real vtable of @class, but all function pointers invoke - * the remoting functions, and vtable->klass points to the - * transparent proxy class, and not to @class. - */ -MonoVTable * -mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class) -{ - MonoVTable *vt, *pvt; - int i, vtsize; - - if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class))) - return pvt; - - vt = mono_class_vtable (domain, class); - vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer); - -#if HAVE_BOEHM_GC - pvt = GC_malloc (vtsize); - GC_register_finalizer (vt, vtable_finalizer, "vtable", NULL, NULL); -#else - pvt = g_malloc0 (vtsize); -#endif - - memcpy (pvt, vt, vtsize); - - pvt->klass = mono_defaults.transparent_proxy_class; - - /* initialize vtable */ - for (i = 0; i < class->vtable_size; ++i) { - MonoMethod *cm; - - if ((cm = class->vtable [i])) - pvt->vtable [i] = arch_create_remoting_trampoline (cm); + /* Object::Finalize should have empty implemenatation */ + class->has_finalize = 0; + if (class != mono_defaults.object_class) { + if (vtable [finalize_slot] != default_finalize) + class->has_finalize = 1; } - - mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt); - - return pvt; } @@ -1062,6 +881,9 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent) int rnum = 0; class->parent = parent; + if (!parent) + g_assert_not_reached (); /* FIXME */ + class->marshalbyref = parent->marshalbyref; class->contextbound = parent->contextbound; class->delegate = parent->delegate; @@ -1105,9 +927,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) guint32 cols_next [MONO_TYPEDEF_SIZE]; guint tidx = mono_metadata_token_index (type_token); const char *name, *nspace; - guint vtsize = 0, icount = 0; + guint icount = 0; MonoClass **interfaces; - int i; if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) return class; @@ -1116,13 +937,6 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) mono_metadata_decode_row (tt, tidx - 1, cols, CSIZE (cols)); - if (tt->rows > tidx) { - mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next)); - vtsize += cols_next [MONO_TYPEDEF_METHOD_LIST] - cols [MONO_TYPEDEF_METHOD_LIST]; - } else { - vtsize += image->tables [MONO_TABLE_METHOD].rows - cols [MONO_TYPEDEF_METHOD_LIST] + 1; - } - name = mono_metadata_string_heap (image, cols[1]); nspace = mono_metadata_string_heap (image, cols[2]); @@ -1132,22 +946,12 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) } interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount); - for (i = 0; i < icount; i++) - vtsize += interfaces [i]->method.count; - - if (parent) - vtsize += parent->vtable_size; - - if (cols [0] & TYPE_ATTRIBUTE_INTERFACE) - vtsize = 0; - - class = g_malloc0 (sizeof (MonoClass) + vtsize * sizeof (gpointer)); - + class = g_malloc0 (sizeof (MonoClass)); + g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class); class->interfaces = interfaces; class->interface_count = icount; - class->vtable_size = vtsize; class->name = name; class->name_space = nspace; @@ -1325,8 +1129,9 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec) class = mono_class_from_mono_type (type->data.type); break; default: - g_warning ("implement me: %08x", type->type); - g_assert_not_reached (); + /* it seems any type can be stored in TypeSpec as well */ + class = mono_class_from_mono_type (type); + break; } mono_metadata_free_type (type); @@ -1348,27 +1153,27 @@ mono_array_class_get (MonoType *element_type, guint32 rank) MonoClass *eclass; MonoImage *image; MonoClass *class; - static MonoClass *parent = NULL; - guint32 key; + MonoClass *parent = NULL; + GSList *list; int rnum = 0; eclass = mono_class_from_mono_type (element_type); g_assert (rank <= 255); - if (!parent) - parent = mono_defaults.array_class; + parent = mono_defaults.array_class; if (!parent->inited) mono_class_init (parent); image = eclass->image; - g_assert (!eclass->type_token || - mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF); - - key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff); - if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key)))) - return class; + if ((list = g_hash_table_lookup (image->array_cache, element_type))) { + for (; list; list = list->next) { + class = list->data; + if (class->rank == rank) + return class; + } + } class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer)); @@ -1394,13 +1199,15 @@ mono_array_class_get (MonoType *element_type, guint32 rank) at->rank = rank; /* FIXME: complete.... */ } else { + /* FIXME: this is not correct. the lbound could be >0 */ class->byval_arg.type = MONO_TYPE_SZARRAY; class->byval_arg.data.type = &eclass->byval_arg; } class->this_arg = class->byval_arg; class->this_arg.byref = 1; - - g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class); + + list = g_slist_append (list, class); + g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list); return class; } @@ -1532,7 +1339,8 @@ mono_class_get (MonoImage *image, guint32 type_token) class = mono_class_create_from_typedef (image, type_token); break; case MONO_TOKEN_TYPE_REF: - return mono_class_create_from_typeref (image, type_token); + class = mono_class_from_typeref (image, type_token); + break; case MONO_TOKEN_TYPE_SPEC: class = mono_class_create_from_typespec (image, type_token); break; @@ -1541,6 +1349,8 @@ mono_class_get (MonoImage *image, guint32 type_token) g_assert_not_reached (); } + if (!class) + g_warning ("Could not load class from token 0x%08x in %s", type_token, image->name); return class; }