#include <stdlib.h>
#include <signal.h>
#include <mono/metadata/image.h>
+#include <mono/metadata/assembly.h>
#include <mono/metadata/cil-coff.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/reflection.h>
#include <mono/os/gc_wrapper.h>
-/*
- * Uncomment this to enable GC aware auto layout: in this mode, reference
- * fields are grouped together inside objects, increasing collector
- * performance.
- * Requires that all classes whose layout is known to the runtime be annotated
- * with [StructLayout (LayoutKind.Sequential)]
- */
-//#define GC_AWARE_AUTO_LAYOUT
-
-#define CSIZE(x) (sizeof (x) / 4)
-
MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
const char *name, *nspace;
MonoClass *res;
MonoAssembly **references;
- MonoImageOpenStatus status;
mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
break;
}
- mono_image_load_references (image, &status);
references = image->references;
if (!references || !references [idx-1]) {
/*
return mono_class_from_name (image, nspace, name);
}
+static MonoType*
+dup_type (MonoType* t)
+{
+ MonoType *r = g_new0 (MonoType, 1);
+ *r = *t;
+ return r;
+}
+
+static void
+mono_type_get_name_recurse (MonoType *type, GString *str)
+{
+ MonoClass *klass;
+
+ switch (type->type) {
+ case MONO_TYPE_ARRAY: {
+ int i, rank = type->data.array->rank;
+
+ mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str);
+ g_string_append_c (str, '[');
+ for (i = 1; i < rank; i++)
+ g_string_append_c (str, ',');
+ g_string_append_c (str, ']');
+ break;
+ }
+ case MONO_TYPE_SZARRAY:
+ mono_type_get_name_recurse (&type->data.klass->byval_arg, str);
+ g_string_append (str, "[]");
+ break;
+ case MONO_TYPE_PTR:
+ mono_type_get_name_recurse (type->data.type, str);
+ g_string_append_c (str, '*');
+ break;
+ default:
+ klass = mono_class_from_mono_type (type);
+ if (klass->nested_in) {
+ mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
+ g_string_append_c (str, '+');
+ }
+ if (*klass->name_space) {
+ g_string_append (str, klass->name_space);
+ g_string_append_c (str, '.');
+ }
+ g_string_append (str, klass->name);
+ break;
+ }
+}
+
+/*
+ * mono_type_get_name:
+ * @type: a type
+ *
+ * Returns the string representation for type as required by System.Reflection.
+ * The inverse of mono_reflection_parse_type ().
+ */
+char*
+mono_type_get_name (MonoType *type)
+{
+ GString* result = g_string_new ("");
+ mono_type_get_name_recurse (type, result);
+
+ if (type->byref)
+ g_string_append_c (result, '&');
+
+ return g_string_free (result, FALSE);
+}
+
+gboolean
+mono_class_is_open_constructed_type (MonoType *t)
+{
+ switch (t->type) {
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
+ return TRUE;
+ case MONO_TYPE_SZARRAY:
+ return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
+ case MONO_TYPE_ARRAY:
+ return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
+ case MONO_TYPE_PTR:
+ return mono_class_is_open_constructed_type (t->data.type);
+ case MONO_TYPE_GENERICINST: {
+ MonoGenericInst *ginst = t->data.generic_inst;
+ int i;
+
+ if (mono_class_is_open_constructed_type (ginst->generic_type))
+ return TRUE;
+ for (i = 0; i < ginst->type_argc; i++)
+ if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
+ return TRUE;
+ return FALSE;
+ }
+ default:
+ return FALSE;
+ }
+}
+
+MonoType*
+mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst,
+ MonoGenericMethod *gmethod)
+{
+ switch (type->type) {
+ case MONO_TYPE_MVAR:
+ if (gmethod && gmethod->mtype_argv)
+ return dup_type (gmethod->mtype_argv [type->data.generic_param->num]);
+ else
+ return type;
+ case MONO_TYPE_VAR:
+ if (ginst) {
+ MonoType *t = ginst->type_argv [type->data.generic_param->num];
+
+ if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR))
+ return type;
+ else
+ return dup_type (t);
+ } else
+ return type;
+ case MONO_TYPE_SZARRAY: {
+ MonoClass *eclass = type->data.klass;
+ MonoClass *nclass;
+ MonoType *nt;
+ if ((eclass->byval_arg.type == MONO_TYPE_MVAR) && gmethod) {
+ nclass = mono_class_from_mono_type (gmethod->mtype_argv [eclass->byval_arg.data.generic_param->num]);
+ } else if ((eclass->byval_arg.type == MONO_TYPE_VAR) && ginst) {
+ nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
+ } else {
+ return type;
+ }
+ nt = dup_type (type);
+ nt->data.klass = nclass;
+ return nt;
+ }
+ case MONO_TYPE_GENERICINST: {
+ MonoGenericInst *oginst = type->data.generic_inst;
+ MonoGenericInst *nginst;
+ MonoType *nt;
+ int i;
+
+ nginst = g_new0 (MonoGenericInst, 1);
+ *nginst = *oginst;
+
+ nginst->type_argv = g_new0 (MonoType *, oginst->type_argc);
+
+ for (i = 0; i < oginst->type_argc; i++) {
+ MonoType *t = oginst->type_argv [i];
+ nginst->type_argv [i] = mono_class_inflate_generic_type (t, ginst, gmethod);
+ };
+
+ nt = dup_type (type);
+ nt->data.generic_inst = nginst;
+ return nt;
+ }
+ default:
+ return type;
+ }
+ return type;
+}
+
+static MonoMethodSignature*
+inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
+ MonoGenericMethod *gmethod)
+{
+ MonoMethodSignature *res;
+ int i;
+ res = mono_metadata_signature_alloc (image, sig->param_count);
+ res->ret = mono_class_inflate_generic_type (sig->ret, gmethod->generic_inst, gmethod);
+ for (i = 0; i < sig->param_count; ++i)
+ res->params [i] = mono_class_inflate_generic_type (sig->params [i],
+ gmethod->generic_inst,
+ gmethod);
+ res->hasthis = sig->hasthis;
+ res->explicit_this = sig->explicit_this;
+ res->call_convention = sig->call_convention;
+ res->generic_param_count = sig->generic_param_count;
+ return res;
+}
+
+static MonoMethodHeader*
+inflate_generic_header (MonoMethodHeader *header, MonoGenericMethod *gmethod)
+{
+ MonoMethodHeader *res;
+ int i;
+ res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
+ res->code = header->code;
+ res->code_size = header->code_size;
+ res->max_stack = header->max_stack;
+ res->num_clauses = header->num_clauses;
+ res->init_locals = header->init_locals;
+ res->num_locals = header->num_locals;
+ res->clauses = header->clauses;
+ res->gen_params = header->gen_params;
+ res->gen_method = gmethod;
+ for (i = 0; i < header->num_locals; ++i)
+ res->locals [i] = mono_class_inflate_generic_type (header->locals [i],
+ gmethod->generic_inst,
+ gmethod);
+ return res;
+}
+
+MonoMethod*
+mono_class_inflate_generic_method (MonoMethod *method, MonoGenericMethod *gmethod)
+{
+ MonoMethod *result;
+ if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+ MonoMethodPInvoke *nmethod = g_new0 (MonoMethodPInvoke, 1);
+ *nmethod = *(MonoMethodPInvoke*)method;
+ result = (MonoMethod*)nmethod;
+ } else {
+ MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1);
+ *nmethod = *(MonoMethodNormal*)method;
+ result = (MonoMethod*)nmethod;
+ if (nmethod->header)
+ nmethod->header = inflate_generic_header (nmethod->header, gmethod);
+ }
+ result->klass = gmethod->klass;
+ result->signature = inflate_generic_signature (
+ method->klass->image, result->signature, gmethod);
+ return result;
+}
+
/**
* class_compute_field_layout:
* @m: pointer to the metadata.
guint32 rva;
guint32 packing_size = 0;
gboolean explicit_size;
+ MonoClassField *field;
if (class->size_inited)
return;
for (i = 0; i < top; i++){
const char *sig;
guint32 cols [MONO_FIELD_SIZE];
- guint32 constant_cols [MONO_CONSTANT_SIZE];
- guint32 cindex;
int idx = class->field.first + i;
-
- mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
+
+ field = &class->fields [i];
+ mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
/* The name is needed for fieldrefs */
- class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
+ field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
mono_metadata_decode_value (sig, &sig);
/* FIELD signature == 0x06 */
g_assert (*sig == 0x06);
- class->fields [i].type = mono_metadata_parse_field_type (
+ field->type = mono_metadata_parse_field_type (
m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
+ if (mono_field_is_deleted (field))
+ continue;
+ if (class->generic_inst) {
+ field->type = mono_class_inflate_generic_type (field->type, class->generic_inst, NULL);
+ field->type->attrs = cols [MONO_FIELD_FLAGS];
+ }
- class->fields [i].parent = class;
+ field->parent = class;
- if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- if (class->fields [i].type->byref) {
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+ if (field->type->byref) {
blittable = FALSE;
} else {
- MonoClass *field_class = mono_class_from_mono_type (class->fields [i].type);
+ MonoClass *field_class = mono_class_from_mono_type (field->type);
if (!field_class || !field_class->blittable)
blittable = FALSE;
}
}
if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
- mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
- if (class->fields [i].offset == (guint32)-1)
- g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
+ mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
+ if (field->offset == (guint32)-1)
+ g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name);
}
if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
mono_metadata_field_info (m, idx, NULL, &rva, NULL);
if (!rva)
- g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name);
- class->fields [i].data = mono_cli_rva_map (class->image->image_info, rva);
+ g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
+ field->data = mono_cli_rva_map (class->image->image_info, rva);
}
if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
- class->enum_basetype = class->fields [i].type;
+ class->enum_basetype = field->type;
class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
blittable = class->element_class->blittable;
}
- if ((class->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
- (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) {
- cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (class->field.first + i + 1));
- if (!cindex) {
- g_warning ("constant for field %s:%s not found", class->name, class->fields [i].name);
- continue;
- }
- mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
- class->fields [i].def_value = g_new0 (MonoConstant, 1);
- class->fields [i].def_value->type = constant_cols [MONO_CONSTANT_TYPE];
- class->fields [i].def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
- }
+ /* The def_value of fields is compute lazily during vtable creation */
}
if (class == mono_defaults.string_class)
class->instance_size = MAX (real_size, class->instance_size);
}
+ if (class->gen_params)
+ return;
+
mono_class_layout_fields (class);
}
int i;
const int top = class->field.count;
guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
- guint32 pass, passes;
+ guint32 pass, passes, real_size;
+ gboolean gc_aware_layout = FALSE;
+ MonoClassField *field;
+
+ /*
+ * Enable GC aware auto layout: in this mode, reference
+ * fields are grouped together inside objects, increasing collector
+ * performance.
+ * Requires that all classes whose layout is known to native code be annotated
+ * with [StructLayout (LayoutKind.Sequential)]
+ */
+ /* corlib is missing [StructLayout] directives in many places */
+ if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (class->image != mono_defaults.corlib)
+ gc_aware_layout = TRUE;
+ }
/*
* Compute field layout and total size (not considering static fields)
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
-#ifdef GC_AWARE_AUTO_LAYOUT
- passes = 2;
-#else
- passes = 1;
-#endif
+ if (gc_aware_layout)
+ passes = 2;
+ else
+ passes = 1;
+
if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
passes = 1;
+ if (class->parent)
+ real_size = class->parent->instance_size;
+ else
+ real_size = sizeof (MonoObject);
+
for (pass = 0; pass < passes; ++pass) {
for (i = 0; i < top; i++){
int size, align;
+ field = &class->fields [i];
- if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
-#ifdef GC_AWARE_AUTO_LAYOUT
- /* FIXME: Fix mono_marshal_load_type_info () too */
- if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+ if (gc_aware_layout) {
/*
* We process fields with reference type in the first pass,
* and fields with non-reference type in the second pass.
* some internal structures, we store GC_MALLOCed memory
* in IntPtr fields...
*/
- if (MONO_TYPE_IS_POINTER (class->fields [i].type)) {
+ if (MONO_TYPE_IS_POINTER (field->type)) {
if (pass == 1)
continue;
} else {
continue;
}
}
-#endif
- size = mono_type_size (class->fields [i].type, &align);
+ if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
+ (strcmp (field->name, "$PRIVATE$") == 0)) {
+ /* This field is a hack inserted by MCS to empty structures */
+ continue;
+ }
+
+ size = mono_type_size (field->type, &align);
/* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
align = class->packing_size ? MIN (class->packing_size, align): align;
class->min_align = MAX (align, class->min_align);
- class->fields [i].offset = class->instance_size;
- class->fields [i].offset += align - 1;
- class->fields [i].offset &= ~(align - 1);
- class->instance_size = class->fields [i].offset + size;
+ field->offset = real_size;
+ field->offset += align - 1;
+ field->offset &= ~(align - 1);
+ real_size = field->offset + size;
}
+
+ class->instance_size = MAX (real_size, class->instance_size);
if (class->instance_size & (class->min_align - 1)) {
class->instance_size += class->min_align - 1;
}
break;
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+ real_size = 0;
for (i = 0; i < top; i++) {
int size, align;
+ field = &class->fields [i];
/*
* There must be info about all the fields in a type if it
* uses explicit layout.
*/
- if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
+ if (mono_field_is_deleted (field))
+ continue;
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
- size = mono_type_size (class->fields [i].type, &align);
+ size = mono_type_size (field->type, &align);
/*
- * When we get here, class->fields [i].offset is already set by the
+ * When we get here, field->offset is already set by the
* loader (for either runtime fields or fields loaded from metadata).
* The offset is from the start of the object: this works for both
* classes and valuetypes.
*/
- class->fields [i].offset += sizeof (MonoObject);
+ field->offset += sizeof (MonoObject);
/*
* Calc max size.
*/
- class->instance_size = MAX (class->instance_size, size + class->fields [i].offset);
+ real_size = MAX (real_size, size + field->offset);
}
+ class->instance_size = MAX (real_size, class->instance_size);
break;
}
*/
for (i = 0; i < top; i++){
int size, align;
+ field = &class->fields [i];
- if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC))
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+ continue;
+ if (mono_field_is_deleted (field))
continue;
- size = mono_type_size (class->fields [i].type, &align);
- class->fields [i].offset = class->class_size;
- class->fields [i].offset += align - 1;
- class->fields [i].offset &= ~(align - 1);
- class->class_size = class->fields [i].offset + size;
+ size = mono_type_size (field->type, &align);
+ field->offset = class->class_size;
+ field->offset += align - 1;
+ field->offset &= ~(align - 1);
+ class->class_size = field->offset + size;
}
}
g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
+ mono_loader_lock ();
+
if (!iid_hash)
iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
+ mono_loader_unlock ();
g_free (str);
return (guint)value;
} else {
++iid;
}
+ mono_loader_unlock ();
+
return iid - 1;
}
static void
-collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray *res)
+collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
{
int i;
MonoClass *ic;
for (i = 0; i < klass->interface_count; i++) {
ic = klass->interfaces [i];
- g_ptr_array_add (res, ic);
+ if (*res == NULL)
+ *res = g_ptr_array_new ();
+ g_ptr_array_add (*res, ic);
collect_implemented_interfaces_aux (ic, res);
}
}
-static GPtrArray*
+static inline GPtrArray*
collect_implemented_interfaces (MonoClass *klass)
{
- GPtrArray *res = g_ptr_array_new ();
+ GPtrArray *res = NULL;
- collect_implemented_interfaces_aux (klass, res);
+ collect_implemented_interfaces_aux (klass, &res);
return res;
}
class->interface_offsets [i] = -1;
ifaces = collect_implemented_interfaces (class);
- for (i = 0; i < ifaces->len; ++i) {
- ic = g_ptr_array_index (ifaces, i);
- class->interface_offsets [ic->interface_id] = cur_slot;
- cur_slot += ic->method.count;
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ ic = g_ptr_array_index (ifaces, i);
+ class->interface_offsets [ic->interface_id] = cur_slot;
+ cur_slot += ic->method.count;
+ }
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
for (k = class->parent; k ; k = k->parent) {
ifaces = collect_implemented_interfaces (k);
- for (i = 0; i < ifaces->len; ++i) {
- ic = g_ptr_array_index (ifaces, i);
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ ic = g_ptr_array_index (ifaces, i);
- if (class->interface_offsets [ic->interface_id] == -1) {
- int io = k->interface_offsets [ic->interface_id];
+ if (class->interface_offsets [ic->interface_id] == -1) {
+ int io = k->interface_offsets [ic->interface_id];
- g_assert (io >= 0);
+ g_assert (io >= 0);
- class->interface_offsets [ic->interface_id] = io;
+ class->interface_offsets [ic->interface_id] = io;
+ }
}
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
}
+
+ if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
+ class->interface_offsets [class->interface_id] = cur_slot;
+
return cur_slot;
}
MonoMethod **vtable;
int i, max_vtsize = 0, max_iid, cur_slot = 0;
GPtrArray *ifaces;
- MonoGHashTable *override_map;
+ MonoGHashTable *override_map = NULL;
/* setup_vtable() must be called only once on the type */
if (class->interface_offsets) {
}
ifaces = collect_implemented_interfaces (class);
- for (i = 0; i < ifaces->len; i++) {
- MonoClass *ic = g_ptr_array_index (ifaces, i);
- max_vtsize += ic->method.count;
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; i++) {
+ MonoClass *ic = g_ptr_array_index (ifaces, i);
+ max_vtsize += ic->method.count;
+ }
+ g_ptr_array_free (ifaces, TRUE);
}
- g_ptr_array_free (ifaces, TRUE);
if (class->parent) {
max_vtsize += class->parent->vtable_size;
if (class->parent && class->parent->vtable_size)
memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
- override_map = mono_g_hash_table_new (NULL, NULL);
-
/* override interface methods */
for (i = 0; i < onum; i++) {
MonoMethod *decl = overrides [i*2];
dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
vtable [dslot] = overrides [i*2 + 1];
vtable [dslot]->slot = dslot;
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
+
mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
}
}
for (k = class; k ; k = k->parent) {
+ int nifaces = 0;
ifaces = collect_implemented_interfaces (k);
- for (i = 0; i < ifaces->len; i++) {
+ if (ifaces)
+ nifaces = ifaces->len;
+ for (i = 0; i < nifaces; i++) {
int j, l, io;
ic = g_ptr_array_index (ifaces, i);
if (im->flags & METHOD_ATTRIBUTE_STATIC)
continue;
g_assert (io + l <= max_vtsize);
+
+ /*
+ * If one of our parents already implements this interface
+ * we can inherit the implementation.
+ */
+ if (!(vtable [io + l])) {
+ MonoClass *parent = class->parent;
+
+ if ((ic->interface_id <= parent->max_interface_id) &&
+ (parent->interface_offsets [ic->interface_id]) &&
+ parent->vtable)
+ vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
+ }
+
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,
}
}
}
- g_ptr_array_free (ifaces, TRUE);
+ if (ifaces)
+ g_ptr_array_free (ifaces, TRUE);
}
for (i = 0; i < class->method.count; ++i) {
mono_metadata_signature_equal (cm->signature, m1->signature)) {
slot = k->methods [j]->slot;
g_assert (cm->slot < max_vtsize);
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
mono_g_hash_table_insert (override_map, m1, cm);
break;
}
if (cm->slot < 0)
cm->slot = cur_slot++;
- if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
+ if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count)
vtable [cm->slot] = cm;
}
g_assert (decl->slot != -1);
vtable [decl->slot] = overrides [i*2 + 1];
overrides [i * 2 + 1]->slot = decl->slot;
+ if (!override_map)
+ override_map = mono_g_hash_table_new (NULL, NULL);
mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
}
}
* If a method occupies more than one place in the vtable, and it is
* overriden, then change the other occurances too.
*/
- for (i = 0; i < max_vtsize; ++i)
- if (vtable [i]) {
- MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
- if (cm)
- vtable [i] = cm;
- }
- mono_g_hash_table_destroy (override_map);
+ if (override_map) {
+ for (i = 0; i < max_vtsize; ++i)
+ if (vtable [i]) {
+ MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
+ if (cm)
+ vtable [i] = cm;
+ }
+ mono_g_hash_table_destroy (override_map);
+ }
class->vtable_size = cur_slot;
class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
if (class->inited)
return;
+ /*g_print ("Init class %s\n", class->name);*/
+
+ /* We do everything inside the lock to prevent races */
+ mono_loader_lock ();
+
+ if (class->inited) {
+ mono_loader_unlock ();
+ /* Somebody might have gotten in before us */
+ return;
+ }
+
if (class->init_pending) {
/* this indicates a cyclic dependency */
g_error ("pending init %s.%s\n", class->name_space, class->name);
ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
ctor->signature = sig;
ctor->name = ".ctor";
+ ctor->slot = -1;
class->methods = g_new (MonoMethod*, class->method.count);
class->methods [0] = ctor;
if (class->rank > 1) {
ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
ctor->signature = sig;
ctor->name = ".ctor";
+ ctor->slot = -1;
class->methods [1] = ctor;
}
} else {
- 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);
+ if (!class->generic_inst && !class->methods) {
+ 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);
+ }
}
}
* we have to setup them for interfaces, too.
*/
setup_interface_offsets (class, 0);
+ mono_loader_unlock ();
return;
}
class->has_finalize = 1;
}
+ mono_loader_unlock ();
+
if (mono_debugger_class_init_func)
mono_debugger_class_init_func (class);
}
if (!parent)
g_assert_not_reached (); /* FIXME */
+ if (parent->generic_inst && !parent->name) {
+ /*
+ * If the parent is a generic instance, we may get
+ * called before it is fully initialized, especially
+ * before it has its name.
+ */
+ return;
+ }
+
class->marshalbyref = parent->marshalbyref;
class->contextbound = parent->contextbound;
class->delegate = parent->delegate;
class->valuetype = class->enumtype = 1;
}
/*class->enumtype = class->parent->enumtype; */
- class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
mono_class_setup_supertypes (class);
} else {
class->parent = NULL;
guint icount = 0;
MonoClass **interfaces;
- if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
+ mono_loader_lock ();
+
+ if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
+ mono_loader_unlock ();
return class;
+ }
g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
class->cast_class = class->element_class = class;
- /*g_print ("Init class %s\n", name);*/
+ /*g_print ("Load class %s\n", name);*/
mono_class_setup_parent (class, parent);
class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
if (tt->rows > tidx){
- mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
+ mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
} else {
if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
class->nested_in = mono_class_create_from_typedef (image, type_token);
+ class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount);
+ class->num_gen_params = icount;
+
+ mono_loader_unlock ();
+
+ return class;
+}
+
+static char*
+get_instantiation_name (const char *name, MonoGenericInst *ginst)
+{
+ GString *res = g_string_new (name);
+ const char *p;
+ int i;
+ MonoClass *argclass;
+
+ p = strchr (name, '<');
+ if (p) {
+ g_string_truncate (res, (p - name) + 1);
+ } else {
+ g_string_append_c (res, '<');
+ }
+ for (i = 0; i < ginst->type_argc; ++i) {
+ if (i > 0)
+ g_string_append_c (res, ',');
+ argclass = mono_class_from_mono_type (ginst->type_argv [i]);
+ g_string_append (res, argclass->name);
+ }
+ g_string_append_c (res, '>');
+ return g_string_free (res, FALSE);
+}
+
+static void
+mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods)
+{
+ MonoClass *klass, *gklass, *pklass;
+
+ if (ginst->initialized || ginst->init_pending)
+ return;
+
+ gklass = mono_class_from_mono_type (ginst->generic_type);
+ mono_class_init (gklass);
+
+ klass = ginst->klass;
+ klass->name = get_instantiation_name (gklass->name, ginst);
+
+ if (ginst->parent)
+ pklass = mono_class_from_mono_type (ginst->parent);
+ else
+ pklass = gklass->parent;
+
+ mono_class_setup_parent (klass, pklass);
+ mono_class_setup_mono_type (klass);
+
+ if (inflate_methods) {
+ int i;
+
+ klass->field = gklass->field;
+ klass->method = gklass->method;
+ klass->methods = g_new0 (MonoMethod *, klass->method.count);
+
+ for (i = 0; i < klass->method.count; i++) {
+ MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1);
+
+ gmethod->klass = klass;
+ gmethod->generic_method = gklass->methods [i];
+ gmethod->generic_inst = ginst;
+
+ klass->methods [i] = mono_class_inflate_generic_method (
+ gklass->methods [i], gmethod);
+ }
+ }
+
+ ginst->initialized = TRUE;
+}
+
+MonoClass*
+mono_class_from_generic (MonoGenericInst *ginst)
+{
+ MonoClass *class, *gklass, *pklass;
+
+ if (ginst->klass) {
+ mono_class_initialize_generic (ginst, TRUE);
+ return ginst->klass;
+ }
+
+ mono_loader_lock ();
+
+ gklass = mono_class_from_mono_type (ginst->generic_type);
+ mono_class_init (gklass);
+
+ class = ginst->klass = g_malloc0 (sizeof (MonoClass));
+ class->name_space = gklass->name_space;
+ class->name = get_instantiation_name (gklass->name, ginst);
+ class->image = gklass->image;
+ class->flags = gklass->flags;
+
+ class->generic_inst = ginst;
+
+ class->cast_class = class->element_class = class;
+
+ mono_loader_unlock ();
+
return class;
}
+MonoClass *
+mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
+{
+ MonoClass *klass, **ptr;
+ int count, pos, i;
+
+ if (param->pklass)
+ return param->pklass;
+
+ klass = param->pklass = g_new0 (MonoClass, 1);
+
+ for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
+ ;
+
+ pos = 0;
+ if ((count > 0) && !(param->constraints [0]->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ klass->parent = param->constraints [0];
+ pos++;
+ } else
+ klass->parent = mono_defaults.object_class;
+
+ if (count - pos > 0) {
+ klass->interface_count = count - pos;
+ klass->interfaces = g_new0 (MonoClass *, count - pos);
+ for (i = pos; i < count; i++)
+ klass->interfaces [i - pos] = param->constraints [i];
+ }
+
+ klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+ klass->name_space = "";
+ klass->image = image;
+ klass->cast_class = klass->element_class = klass;
+ klass->enum_basetype = &klass->element_class->byval_arg;
+ klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
+
+ klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+ klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
+ klass->this_arg.byref = TRUE;
+
+ mono_class_init (klass);
+
+ return klass;
+}
+
+static MonoClass *
+my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
+{
+ MonoClass *klass;
+
+ if (param->pklass)
+ return param->pklass;
+
+ klass = g_new0 (MonoClass, 1);
+
+ klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
+ klass->name_space = "";
+ klass->image = mono_defaults.corlib;
+ klass->cast_class = klass->element_class = klass;
+ klass->enum_basetype = &klass->element_class->byval_arg;
+ klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
+
+ klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+ klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
+ klass->this_arg.byref = TRUE;
+
+ mono_class_init (klass);
+
+ return klass;
+}
+
MonoClass *
mono_ptr_class_get (MonoType *type)
{
MonoClass *el_class;
static GHashTable *ptr_hash = NULL;
+ mono_loader_lock ();
+
if (!ptr_hash)
- ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ptr_hash = g_hash_table_new (NULL, NULL);
el_class = mono_class_from_mono_type (type);
- if ((result = g_hash_table_lookup (ptr_hash, el_class)))
+ if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
+ mono_loader_unlock ();
return result;
+ }
result = g_new0 (MonoClass, 1);
result->parent = NULL; /* no parent for PTR types */
g_hash_table_insert (ptr_hash, el_class, result);
+ mono_loader_unlock ();
+
return result;
}
MonoClass *result;
static GHashTable *ptr_hash = NULL;
+ mono_loader_lock ();
+
if (!ptr_hash)
- ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ ptr_hash = g_hash_table_new (NULL, NULL);
- if ((result = g_hash_table_lookup (ptr_hash, sig)))
+ if ((result = g_hash_table_lookup (ptr_hash, sig))) {
+ mono_loader_unlock ();
return result;
+ }
result = g_new0 (MonoClass, 1);
result->parent = NULL; /* no parent for PTR types */
g_hash_table_insert (ptr_hash, sig, result);
+ mono_loader_unlock ();
+
return result;
}
{
switch (type->type) {
case MONO_TYPE_OBJECT:
- return mono_defaults.object_class;
+ return type->data.klass? type->data.klass: mono_defaults.object_class;
case MONO_TYPE_VOID:
- return mono_defaults.void_class;
+ return type->data.klass? type->data.klass: mono_defaults.void_class;
case MONO_TYPE_BOOLEAN:
- return mono_defaults.boolean_class;
+ return type->data.klass? type->data.klass: mono_defaults.boolean_class;
case MONO_TYPE_CHAR:
- return mono_defaults.char_class;
+ return type->data.klass? type->data.klass: mono_defaults.char_class;
case MONO_TYPE_I1:
- return mono_defaults.sbyte_class;
+ return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
case MONO_TYPE_U1:
- return mono_defaults.byte_class;
+ return type->data.klass? type->data.klass: mono_defaults.byte_class;
case MONO_TYPE_I2:
- return mono_defaults.int16_class;
+ return type->data.klass? type->data.klass: mono_defaults.int16_class;
case MONO_TYPE_U2:
- return mono_defaults.uint16_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint16_class;
case MONO_TYPE_I4:
- return mono_defaults.int32_class;
+ return type->data.klass? type->data.klass: mono_defaults.int32_class;
case MONO_TYPE_U4:
- return mono_defaults.uint32_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint32_class;
case MONO_TYPE_I:
- return mono_defaults.int_class;
+ return type->data.klass? type->data.klass: mono_defaults.int_class;
case MONO_TYPE_U:
- return mono_defaults.uint_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint_class;
case MONO_TYPE_I8:
- return mono_defaults.int64_class;
+ return type->data.klass? type->data.klass: mono_defaults.int64_class;
case MONO_TYPE_U8:
- return mono_defaults.uint64_class;
+ return type->data.klass? type->data.klass: mono_defaults.uint64_class;
case MONO_TYPE_R4:
- return mono_defaults.single_class;
+ return type->data.klass? type->data.klass: mono_defaults.single_class;
case MONO_TYPE_R8:
- return mono_defaults.double_class;
+ return type->data.klass? type->data.klass: mono_defaults.double_class;
case MONO_TYPE_STRING:
- return mono_defaults.string_class;
+ return type->data.klass? type->data.klass: mono_defaults.string_class;
case MONO_TYPE_TYPEDBYREF:
- return mono_defaults.typed_reference_class;
+ return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
case MONO_TYPE_ARRAY:
- return mono_array_class_get (type->data.array->type, type->data.array->rank);
+ return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
case MONO_TYPE_PTR:
return mono_ptr_class_get (type->data.type);
case MONO_TYPE_FNPTR:
return mono_fnptr_class_get (type->data.method);
case MONO_TYPE_SZARRAY:
- return mono_array_class_get (type->data.type, 1);
+ return mono_array_class_get (type->data.klass, 1);
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
return type->data.klass;
-
case MONO_TYPE_GENERICINST:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_GENERICINST");
- g_assert_not_reached ();
-
+ return mono_class_from_generic (type->data.generic_inst);
case MONO_TYPE_VAR:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_VAR");
- g_assert_not_reached ();
-
+ return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
case MONO_TYPE_MVAR:
- g_warning ("mono_class_from_type: implement me MONO_TYPE_MVAR");
- g_assert_not_reached ();
-
+ return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
default:
g_warning ("implement me 0x%02x\n", type->type);
g_assert_not_reached ();
switch (type->type) {
case MONO_TYPE_ARRAY:
- class = mono_array_class_get (type->data.array->type, type->data.array->rank);
+ class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
break;
case MONO_TYPE_SZARRAY:
- class = mono_array_class_get (type->data.type, 1);
+ class = mono_array_class_get (type->data.klass, 1);
break;
case MONO_TYPE_PTR:
class = mono_class_from_mono_type (type->data.type);
break;
+ case MONO_TYPE_GENERICINST:
+ class = mono_class_from_generic (type->data.generic_inst);
+ break;
default:
/* it seems any type can be stored in TypeSpec as well */
class = mono_class_from_mono_type (type);
break;
}
- mono_metadata_free_type (type);
-
return class;
}
/**
- * mono_array_class_get:
- * @element_type: element type
+ * mono_bounded_array_class_get:
+ * @element_class: element class
* @rank: the dimension of the array class
+ * @bounded: whenever the array has non-zero bounds
*
* Returns: a class object describing the array with element type @element_type and
* dimension @rank.
*/
MonoClass *
-mono_array_class_get (MonoType *element_type, guint32 rank)
+mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
{
- MonoClass *eclass;
MonoImage *image;
MonoClass *class;
MonoClass *parent = NULL;
- GSList *list;
+ GSList *list, *rootlist;
int nsize;
char *name;
+ gboolean corlib_type = FALSE;
- eclass = mono_class_from_mono_type (element_type);
g_assert (rank <= 255);
- parent = mono_defaults.array_class;
-
- if (!parent->inited)
- mono_class_init (parent);
+ if (rank > 1)
+ /* bounded only matters for one-dimensional arrays */
+ bounded = FALSE;
image = eclass->image;
- if ((list = g_hash_table_lookup (image->array_cache, element_type))) {
+ mono_loader_lock ();
+
+ if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
for (; list; list = list->next) {
class = list->data;
- if (class->rank == rank)
+ if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
+ mono_loader_unlock ();
return class;
+ }
}
}
-
- class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
+
+ /* for the building corlib use System.Array from it */
+ if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
+ parent = mono_class_from_name (image, "System", "Array");
+ corlib_type = TRUE;
+ } else {
+ parent = mono_defaults.array_class;
+ if (!parent->inited)
+ mono_class_init (parent);
+ }
+
+ class = g_malloc0 (sizeof (MonoClass));
class->image = image;
class->name_space = eclass->name_space;
class->parent = parent;
class->instance_size = mono_class_instance_size (class->parent);
class->class_size = 0;
- class->vtable_size = parent->vtable_size;
- class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
mono_class_setup_supertypes (class);
class->rank = rank;
class->element_class = eclass;
- if (rank > 1) {
+ if ((rank > 1) || bounded) {
MonoArrayType *at = g_new0 (MonoArrayType, 1);
class->byval_arg.type = MONO_TYPE_ARRAY;
class->byval_arg.data.array = at;
- at->type = &eclass->byval_arg;
+ at->eklass = eclass;
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->byval_arg.data.klass = eclass;
}
class->this_arg = class->byval_arg;
class->this_arg.byref = 1;
+ if (corlib_type) {
+ class->inited = 1;
+ }
+
+ list = g_slist_append (rootlist, class);
+ g_hash_table_insert (image->array_cache, eclass, list);
+
+ mono_loader_unlock ();
- list = g_slist_append (list, class);
- g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list);
return class;
}
+/**
+ * mono_array_class_get:
+ * @element_class: element class
+ * @rank: the dimension of the array class
+ *
+ * Returns: a class object describing the array with element type @element_type and
+ * dimension @rank.
+ */
+MonoClass *
+mono_array_class_get (MonoClass *eclass, guint32 rank)
+{
+ return mono_bounded_array_class_get (eclass, rank, FALSE);
+}
+
/**
* mono_class_instance_size:
* @klass: a class
*/
gint32
mono_class_instance_size (MonoClass *klass)
-{
-
+{
if (!klass->size_inited)
mono_class_init (klass);
*/
gint32
mono_class_min_align (MonoClass *klass)
-{
-
+{
if (!klass->size_inited)
mono_class_init (klass);
*/
gint32
mono_class_data_size (MonoClass *klass)
-{
-
+{
if (!klass->inited)
mono_class_init (klass);
MonoClass *
mono_class_get (MonoImage *image, guint32 type_token)
{
- MonoClass *class;
+ MonoClass *class = NULL;
- if (image->assembly->dynamic)
+ if (image->dynamic)
return mono_lookup_dynamic_token (image, type_token);
switch (type_token & 0xff000000){
return NULL;
}
-static MonoImage*
-load_file_for_image (MonoImage *image, int fileidx)
-{
- char *base_dir, *name;
- MonoImage *res;
- MonoTableInfo *t = &image->tables [MONO_TABLE_FILE];
- const char *fname;
- guint32 fname_id;
-
- if (fileidx < 1 || fileidx > t->rows)
- return NULL;
- fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME);
- fname = mono_metadata_string_heap (image, fname_id);
- base_dir = g_path_get_dirname (image->name);
- name = g_build_filename (base_dir, fname, NULL);
- res = mono_image_open (name, NULL);
- if (res) {
- int i;
- t = &res->tables [MONO_TABLE_MODULEREF];
- //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly);
- res->assembly = image->assembly;
- for (i = 0; i < t->rows; ++i) {
- if (res->modules [i] && !res->modules [i]->assembly)
- res->modules [i]->assembly = image->assembly;
- }
- mono_image_load_references (image, NULL);
- }
- g_free (name);
- g_free (base_dir);
- return res;
-}
-
static MonoClass*
return_nested_in (MonoClass *class, char *nested) {
MonoClass *found;
{
GHashTable *nspace_table;
MonoImage *loaded_image;
- guint32 token;
+ guint32 token = 0;
MonoClass *class;
char *nested;
char buf [1024];
name = buf;
}
+ mono_loader_lock ();
+
nspace_table = g_hash_table_lookup (image->name_cache, name_space);
-
- if (!nspace_table || !(token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)))) {
+
+ if (nspace_table)
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
+
+ mono_loader_unlock ();
+
+ if (!token)
+ return NULL;
+
+ if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
guint32 cols [MONO_EXP_TYPE_SIZE];
- int i;
-
- for (i = 0; i < t->rows; ++i) {
- const char *ename, *enspace;
- mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
- ename = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
- enspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
-
- if (strcmp (name, ename) == 0 && strcmp (name_space, enspace) == 0) {
- guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
- if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
- loaded_image = load_file_for_image (image, impl >> IMPLEMENTATION_BITS);
- if (!loaded_image)
- return NULL;
- class = mono_class_from_name (loaded_image, name_space, name);
- if (nested)
- return return_nested_in (class, nested);
- return class;
- } else {
- g_error ("not yet implemented");
- }
- }
+ guint32 idx, impl;
+
+ idx = mono_metadata_token_index (token);
+
+ mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
+
+ impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
+ if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
+ loaded_image = mono_assembly_load_module (image->assembly, impl >> IMPLEMENTATION_BITS);
+ if (!loaded_image)
+ return NULL;
+ class = mono_class_from_name (loaded_image, name_space, name);
+ if (nested)
+ return return_nested_in (class, nested);
+ return class;
+ } else {
+ g_error ("not yet implemented");
}
- /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
- return NULL;
}
token = MONO_TOKEN_TYPE_DEF | token;
if (!(klass->flags & TYPE_ATTRIBUTE_INTERFACE) && mono_class_has_parent (klass, klassc))
return TRUE;
}
+
+ /*
+ * MS.NET thinks interfaces are a subclass of Object, so we think it as
+ * well.
+ */
+ if (klassc == mono_defaults.object_class)
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean
+mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
+{
+ if (!klass->inited)
+ mono_class_init (klass);
+
+ if (!oklass->inited)
+ mono_class_init (oklass);
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if ((klass->interface_id <= oklass->max_interface_id) &&
+ (oklass->interface_offsets [klass->interface_id] != -1))
+ return TRUE;
+ } else
+ if (klass->rank) {
+ MonoClass *eclass, *eoclass;
+
+ if (oklass->rank != klass->rank)
+ return FALSE;
+
+ /* vectors vs. one dimensional arrays */
+ if (oklass->byval_arg.type != klass->byval_arg.type)
+ return FALSE;
+
+ eclass = klass->cast_class;
+ eoclass = oklass->cast_class;
+
+
+ /*
+ * a is b does not imply a[] is b[] when a is a valuetype, and
+ * b is a reference type.
+ */
+
+ if (eoclass->valuetype) {
+ if ((eclass == mono_defaults.enum_class) ||
+ (eclass == mono_defaults.enum_class->parent) ||
+ (eclass == mono_defaults.object_class))
+ return FALSE;
+ }
+
+ return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
+ }
+ else
+ if (klass == mono_defaults.object_class)
+ return TRUE;
+
+ return mono_class_has_parent (oklass, klass);
+}
+
+/*
+ * mono_class_needs_cctor_run:
+ *
+ * Determines whenever the class has a static constructor and whenever it
+ * needs to be called when executing CALLER.
+ */
+gboolean
+mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
+{
+ int i;
+ MonoMethod *method;
+ for (i = 0; i < klass->method.count; ++i) {
+ method = klass->methods [i];
+ if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
+ (strcmp (".cctor", method->name) == 0)) {
+ if (caller == method)
+ return FALSE;
+ return TRUE;
+ }
+ }
return FALSE;
}
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_VAR:
+ case MONO_TYPE_MVAR:
return sizeof (gpointer);
case MONO_TYPE_I8:
case MONO_TYPE_U8:
gpointer
mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
{
- if (image->assembly->dynamic) {
+ if (image->dynamic) {
gpointer obj = mono_lookup_dynamic_token (image, token);
switch (token & 0xff000000) {
class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
mono_class_init (class);
if (handle_class)
- *handle_class = mono_defaults.fieldhandle_class;
+ *handle_class = mono_defaults.fieldhandle_class;
return mono_class_get_field (class, token);
}
- case MONO_TOKEN_METHOD_DEF:
- case MONO_TOKEN_MEMBER_REF:
+ case MONO_TOKEN_METHOD_DEF: {
+ MonoMethod *meth;
+ meth = mono_get_method (image, token, NULL);
+ if (handle_class)
+ *handle_class = mono_defaults.methodhandle_class;
+ return meth;
+ }
+ case MONO_TOKEN_MEMBER_REF: {
+ guint32 cols [MONO_MEMBERREF_SIZE];
+ const char *sig;
+ mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
+ sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
+ mono_metadata_decode_blob_size (sig, &sig);
+ if (*sig == 0x6) { /* it's a field */
+ MonoClass *klass;
+ MonoClassField *field;
+ field = mono_field_from_token (image, token, &klass);
+ if (handle_class)
+ *handle_class = mono_defaults.fieldhandle_class;
+ return field;
+ } else {
+ MonoMethod *meth;
+ meth = mono_get_method (image, token, NULL);
+ if (handle_class)
+ *handle_class = mono_defaults.methodhandle_class;
+ return meth;
+ }
+ }
default:
g_warning ("Unknown token 0x%08x in ldtoken", token);
break;
{
return lookup_dynamic (image, token);
}
+
+
+