MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
int i, blittable = TRUE;
guint32 rva;
+ guint32 packing_size = 0;
+
+ if (class->size_inited)
+ return;
+
+ if (class->parent) {
+ if (!class->parent->size_inited)
+ class_compute_field_layout (class->parent);
+ class->instance_size += class->parent->instance_size;
+ class->class_size += class->parent->class_size;
+ class->min_align = class->parent->min_align;
+ } else {
+ class->instance_size = sizeof (MonoObject);
+ class->min_align = 1;
+ }
+
+ if (mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &class->instance_size)) {
+ class->instance_size += sizeof (MonoObject);
+ }
+
+ g_assert ((packing_size & 0xfffffff0) == 0);
+ class->packing_size = packing_size;
+
+ if (!top) {
+ class->size_inited = 1;
+ return;
+ }
+
+ class->fields = g_new0 (MonoClassField, top);
/*
* Fetch all the field information.
}
}
+ if (class == mono_defaults.string_class)
+ blittable = FALSE;
+
class->blittable = blittable;
if (class->enumtype && !class->enum_basetype) {
return iid - 1;
}
-/**
- * mono_class_init:
- * @class: the class to initialize
- *
- * compute the instance_size, class_size and other infos that cannot be
- * computed at mono_class_get() time. Also compute a generic vtable and
- * the method slot numbers. We use this infos later to create a domain
- * specific vtable.
- */
void
-mono_class_init (MonoClass *class)
+mono_class_setup_vtable (MonoClass *class)
{
MonoClass *k, *ic;
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;
- guint32 packing_size = 0;
-
- g_assert (class);
-
- if (class->inited)
- return;
-
- if (class->init_pending) {
- /* this indicates a cyclic dependency */
- g_error ("pending init %s.%s\n", class->name_space, class->name);
- }
-
- class->init_pending = 1;
-
- mono_stats.initialized_class_count++;
+ int i, onum = 0, max_vtsize = 0, max_iid, cur_slot = 0;
+ MonoMethod **overrides;
+ for (i = 0; i < class->interface_count; i++)
+ max_vtsize += class->interfaces [i]->method.count;
+
if (class->parent) {
- if (!class->parent->inited)
- mono_class_init (class->parent);
- class->instance_size += class->parent->instance_size;
- class->class_size += class->parent->class_size;
- class->min_align = class->parent->min_align;
+ max_vtsize += class->parent->vtable_size;
cur_slot = class->parent->vtable_size;
- } else
- class->min_align = 1;
-
- if (mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &class->instance_size)) {
- class->instance_size += sizeof (MonoObject);
}
- g_assert ((packing_size & 0xfffffff0) == 0);
- class->packing_size = packing_size;
-
- /*
- * Computes the size used by the fields, and their locations
- */
- if (!class->size_inited && class->field.count > 0){
- class->fields = g_new0 (MonoClassField, class->field.count);
- 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;
- }
+ 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)
- class->methods [i] = mono_get_method (class->image,
- MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
-
- init_properties (class);
- init_events (class);
-
- i = mono_metadata_nesting_typedef (class->image, class->type_token);
- while (i) {
- MonoClass* nclass;
- guint32 cols [MONO_NESTED_CLASS_SIZE];
- mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
- if (cols [MONO_NESTED_CLASS_ENCLOSING] != mono_metadata_token_index (class->type_token))
- break;
- nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
- class->nested_classes = g_list_prepend (class->nested_classes, nclass);
- ++i;
- }
-
- if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
- for (i = 0; i < class->method.count; ++i)
- class->methods [i]->slot = i;
- class->init_pending = 0;
- class->inited = 1;
- return;
- }
-
/* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
/* compute maximum number of slots and maximum interface id */
if (class->parent && class->parent->vtable_size)
memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
-
+
+ overrides = mono_class_get_overrides (class->image, class->type_token, &onum);
+
+ /* override interface methods */
+ for (i = 0; i < onum; i++) {
+ MonoMethod *decl = overrides [i*2];
+ if (decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ int dslot;
+ g_assert (decl->slot != -1);
+ dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
+ vtable [dslot] = overrides [i*2 + 1];
+ }
+ }
+
for (k = class; k ; k = k->parent) {
for (i = 0; i < k->interface_count; i++) {
int j, l, io;
MonoMethod *im = ic->methods [l];
g_assert (io + l <= max_vtsize);
if (!(vtable [io + l])) {
+ for (j = 0; j < onum; ++j) {
+ g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name,
+ overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
+ }
msig = mono_signature_get_desc (im->signature, FALSE);
printf ("no implementation for interface method %s.%s::%s(%s) in class %s.%s\n",
ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
vtable [cm->slot] = cm;
}
+ /* override non interface methods */
+ for (i = 0; i < onum; i++) {
+ MonoMethod *decl = overrides [i*2];
+ if (!(decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ g_assert (decl->slot != -1);
+ vtable [decl->slot] = overrides [i*2 + 1];
+ }
+ }
+
+ g_free (overrides);
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;
}
}
+}
+
+/**
+ * mono_class_init:
+ * @class: the class to initialize
+ *
+ * compute the instance_size, class_size and other infos that cannot be
+ * computed at mono_class_get() time. Also compute a generic vtable and
+ * the method slot numbers. We use this infos later to create a domain
+ * specific vtable.
+ */
+void
+mono_class_init (MonoClass *class)
+{
+ int i;
+ static MonoMethod *default_ghc = NULL;
+ static MonoMethod *default_finalize = NULL;
+ static int finalize_slot = -1;
+ static int ghc_slot = -1;
+
+ g_assert (class);
+
+ if (class->inited)
+ return;
+
+ if (class->init_pending) {
+ /* this indicates a cyclic dependency */
+ g_error ("pending init %s.%s\n", class->name_space, class->name);
+ }
+
+ class->init_pending = 1;
+
+ mono_stats.initialized_class_count++;
+
+ if (class->parent && !class->parent->inited)
+ mono_class_init (class->parent);
+
+ /*
+ * Computes the size used by the fields, and their locations
+ */
+ if (!class->size_inited)
+ class_compute_field_layout (class);
+
+ /* initialize method pointers */
+ class->methods = g_new (MonoMethod*, class->method.count);
+ for (i = 0; i < class->method.count; ++i)
+ class->methods [i] = mono_get_method (class->image,
+ MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
+
+ init_properties (class);
+ init_events (class);
+
+ i = mono_metadata_nesting_typedef (class->image, class->type_token);
+ while (i) {
+ MonoClass* nclass;
+ guint32 cols [MONO_NESTED_CLASS_SIZE];
+ mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
+ if (cols [MONO_NESTED_CLASS_ENCLOSING] != mono_metadata_token_index (class->type_token))
+ break;
+ nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
+ class->nested_classes = g_list_prepend (class->nested_classes, nclass);
+ ++i;
+ }
+
+ if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ for (i = 0; i < class->method.count; ++i)
+ class->methods [i]->slot = i;
+ class->init_pending = 0;
+ class->inited = 1;
+ return;
+ }
+
+ mono_class_setup_vtable (class);
+
+ class->inited = 1;
+ class->init_pending = 0;
+
if (!default_ghc) {
if (class == mono_defaults.object_class) {
for (i = 0; i < class->vtable_size; ++i) {
- MonoMethod *cm = vtable [i];
+ MonoMethod *cm = class->vtable [i];
if (!strcmp (cm->name, "GetHashCode")) {
ghc_slot = i;
g_assert (ghc_slot > 0);
- default_ghc = vtable [ghc_slot];
+ default_ghc = class->vtable [ghc_slot];
}
}
class->ghcimpl = 1;
if (class != mono_defaults.object_class) {
- if (vtable [ghc_slot] == default_ghc) {
+ if (class->vtable [ghc_slot] == default_ghc) {
class->ghcimpl = 0;
}
}
if (class == mono_defaults.object_class) {
for (i = 0; i < class->vtable_size; ++i) {
- MonoMethod *cm = vtable [i];
+ MonoMethod *cm = class->vtable [i];
if (!strcmp (cm->name, "Finalize")) {
finalize_slot = i;
g_assert (finalize_slot > 0);
- default_finalize = vtable [finalize_slot];
+ default_finalize = class->vtable [finalize_slot];
}
}
/* Object::Finalize should have empty implemenatation */
class->has_finalize = 0;
if (class != mono_defaults.object_class) {
- if (vtable [finalize_slot] != default_finalize)
+ if (class->vtable [finalize_slot] != default_finalize)
class->has_finalize = 1;
}
}
case 'D':
if (!strcmp (name, "Double")) {
t = MONO_TYPE_R8;
+ class->blittable = TRUE;
}
break;
case 'I':
case 'S':
if (!strcmp (name, "Single")) {
t = MONO_TYPE_R4;
+ class->blittable = TRUE;
} else if (!strcmp(name, "SByte")) {
t = MONO_TYPE_I1;
class->blittable = TRUE;
guint icount = 0;
MonoClass **interfaces;
- if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
+ if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
return class;
g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
/*class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count); */
- if (class->enumtype) {
- class->fields = g_new0 (MonoClassField, class->field.count);
+ if (class->enumtype)
class_compute_field_layout (class);
- }
if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
class->nested_in = mono_class_create_from_typedef (image, type_token);
MonoClass *class;
MonoClass *parent = NULL;
GSList *list;
- int rnum = 0;
+ int rnum = 0, nsize;
eclass = mono_class_from_mono_type (element_type);
g_assert (rank <= 255);
class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
class->image = image;
- class->name_space = "System";
- class->name = "Array";
+ class->name_space = eclass->name_space;
+ nsize = strlen (eclass->name);
+ class->name = g_malloc (nsize + 2 + rank);
+ memcpy (class->name, eclass->name, nsize);
+ class->name [nsize] = '[';
+ if (rank > 1)
+ memset (class->name + nsize + 1, ',', rank - 1);
+ class->name [nsize + rank] = ']';
+ class->name [nsize + rank + 1] = 0;
class->type_token = 0;
class->flags = TYPE_ATTRIBUTE_CLASS;
class->parent = parent;
class->this_arg = class->byval_arg;
class->this_arg.byref = 1;
- if (rank == 1 && class->element_class->blittable)
- class->blittable = TRUE;
-
list = g_slist_append (list, class);
g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list);
return class;
{
int i;
- for (i = 0; i < klass->field.count; ++i) {
- if (strcmp (name, klass->fields [i].name) == 0)
- return &klass->fields [i];
+ while (klass) {
+ for (i = 0; i < klass->field.count; ++i) {
+ if (strcmp (name, klass->fields [i].name) == 0)
+ return &klass->fields [i];
+ }
+ klass = klass->parent;
+ }
+ return NULL;
+}
+
+MonoProperty*
+mono_class_get_property_from_name (MonoClass *klass, const char *name)
+{
+ int i;
+
+ while (klass) {
+ for (i = 0; i < klass->property.count; ++i) {
+ if (strcmp (name, klass->properties [i].name) == 0)
+ return &klass->properties [i];
+ }
+ klass = klass->parent;
}
return NULL;
}